forked from platypush/platypush
Merged network_stats
into NetworkInterface
model.
This commit is contained in:
parent
f4036be52b
commit
374f936c1f
6 changed files with 106 additions and 66 deletions
|
@ -91,12 +91,39 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="child head" :class="{expanded: !areAddressesCollapsed}"
|
||||
@click.stop="areAddressesCollapsed = !areAddressesCollapsed">
|
||||
<div class="col-11 label">Addresses</div>
|
||||
<div class="col-1 collapse-toggler pull-right">
|
||||
<i class="fas"
|
||||
:class="{'fa-chevron-down': areAddressesCollapsed, 'fa-chevron-up': !areAddressesCollapsed}" />
|
||||
<div class="child" v-if="value.speed">
|
||||
<div class="col-s-12 col-m-6 label">
|
||||
<div class="name">Speed</div>
|
||||
</div>
|
||||
<div class="value">
|
||||
<div class="name" v-text="value.speed + ' Mbps'" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="child" v-if="value.mtu">
|
||||
<div class="col-s-12 col-m-6 label">
|
||||
<div class="name">MTU</div>
|
||||
</div>
|
||||
<div class="value">
|
||||
<div class="name" v-text="value.mtu" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="child" v-if="value.flags?.length">
|
||||
<div class="col-s-12 col-m-6 label">
|
||||
<div class="name">Flags</div>
|
||||
</div>
|
||||
<div class="value">
|
||||
<div class="name" v-text="value.flags.join(', ')" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="child head" :class="{expanded: !areAddressesCollapsed}"
|
||||
@click.stop="areAddressesCollapsed = !areAddressesCollapsed">
|
||||
<div class="col-11 label">Addresses</div>
|
||||
<div class="col-1 collapse-toggler pull-right">
|
||||
<i class="fas"
|
||||
:class="{'fa-chevron-down': areAddressesCollapsed, 'fa-chevron-up': !areAddressesCollapsed}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ from sqlalchemy import Column, Float, ForeignKey, Integer, JSON, String
|
|||
from platypush.common.db import Base
|
||||
|
||||
from . import Entity
|
||||
from .devices import Device
|
||||
|
||||
|
||||
if 'cpu' not in Base.metadata:
|
||||
|
@ -179,7 +180,7 @@ if 'disk' not in Base.metadata:
|
|||
|
||||
if 'network_interface' not in Base.metadata:
|
||||
|
||||
class NetworkInterface(Entity):
|
||||
class NetworkInterface(Device):
|
||||
"""
|
||||
``NetworkInterface`` ORM model.
|
||||
"""
|
||||
|
@ -187,7 +188,7 @@ if 'network_interface' not in Base.metadata:
|
|||
__tablename__ = 'network_interface'
|
||||
|
||||
id = Column(
|
||||
Integer, ForeignKey(Entity.id, ondelete='CASCADE'), primary_key=True
|
||||
Integer, ForeignKey(Device.id, ondelete='CASCADE'), primary_key=True
|
||||
)
|
||||
|
||||
bytes_sent = Column(Integer)
|
||||
|
@ -199,6 +200,10 @@ if 'network_interface' not in Base.metadata:
|
|||
drop_in = Column(Integer)
|
||||
drop_out = Column(Integer)
|
||||
addresses = Column(JSON)
|
||||
speed = Column(Integer)
|
||||
mtu = Column(Integer)
|
||||
duplex = Column(String)
|
||||
flags = Column(JSON)
|
||||
|
||||
__mapper_args__ = {
|
||||
'polymorphic_identity': __tablename__,
|
||||
|
|
|
@ -28,23 +28,6 @@ class SensorResponse(SystemResponse):
|
|||
pass
|
||||
|
||||
|
||||
class NetworkInterfaceStatsResponse(NetworkResponse):
|
||||
def __init__(
|
||||
self, nic: str, is_up: bool, duplex: str, speed: int, mtu: int, *args, **kwargs
|
||||
):
|
||||
super().__init__(
|
||||
*args,
|
||||
output={
|
||||
'nic': nic,
|
||||
'is_up': is_up,
|
||||
'duplex': duplex,
|
||||
'speed': speed,
|
||||
'mtu': mtu,
|
||||
},
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
||||
class SensorTemperatureResponse(SensorResponse):
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -184,11 +167,6 @@ class SystemResponseList(SystemResponse):
|
|||
super().__init__(output=[r.output for r in responses], *args, **kwargs)
|
||||
|
||||
|
||||
class NetworkResponseList(NetworkResponse, SystemResponseList):
|
||||
def __init__(self, responses: List[NetworkResponse], *args, **kwargs):
|
||||
super().__init__(responses=responses, *args, **kwargs)
|
||||
|
||||
|
||||
class SensorResponseList(SensorResponse, SystemResponseList):
|
||||
def __init__(self, responses: List[SensorResponse], *args, **kwargs):
|
||||
super().__init__(responses=responses, *args, **kwargs)
|
||||
|
|
|
@ -21,8 +21,6 @@ from platypush.entities.system import (
|
|||
SwapStats as SwapStatsModel,
|
||||
)
|
||||
from platypush.message.response.system import (
|
||||
NetworkResponseList,
|
||||
NetworkInterfaceStatsResponse,
|
||||
SensorTemperatureResponse,
|
||||
SensorResponseList,
|
||||
SensorFanResponse,
|
||||
|
@ -256,15 +254,18 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
|||
|
||||
def _network_info(self) -> List[NetworkInterface]:
|
||||
addrs = psutil.net_if_addrs()
|
||||
stats = psutil.net_if_stats()
|
||||
|
||||
return NetworkInterfaceSchema().load( # type: ignore
|
||||
[
|
||||
{
|
||||
'interface': interface,
|
||||
'addresses': addrs.get(interface, []),
|
||||
**stats._asdict(),
|
||||
**(stats[interface]._asdict() if stats.get(interface) else {}),
|
||||
**info._asdict(),
|
||||
}
|
||||
for interface, stats in psutil.net_io_counters(pernic=True).items()
|
||||
if any(bool(val) for val in stats._asdict().values())
|
||||
for interface, info in psutil.net_io_counters(pernic=True).items()
|
||||
if any(bool(val) for val in info._asdict().values())
|
||||
],
|
||||
many=True,
|
||||
)
|
||||
|
@ -331,37 +332,6 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
|||
many=True,
|
||||
)
|
||||
|
||||
@action
|
||||
def net_stats(
|
||||
self, nic: Optional[str] = None
|
||||
) -> Union[NetworkInterfaceStatsResponse, NetworkResponseList]:
|
||||
"""
|
||||
Get stats about the network interfaces.
|
||||
|
||||
:param nic: Select the stats for a specific network device (e.g. 'eth0'). Default: get stats for all NICs.
|
||||
:return: :class:`platypush.message.response.system.NetworkInterfaceStatsResponse` or list of
|
||||
:class:`platypush.message.response.system.NetworkInterfaceStatsResponse`.
|
||||
"""
|
||||
stats = psutil.net_if_stats()
|
||||
|
||||
def _expand_stats(_nic, _stats):
|
||||
return NetworkInterfaceStatsResponse(
|
||||
nic=_nic,
|
||||
is_up=_stats.isup,
|
||||
duplex=_stats.duplex.name,
|
||||
speed=_stats.speed,
|
||||
mtu=_stats.mtu,
|
||||
)
|
||||
|
||||
if nic:
|
||||
stats = [addr for name, addr in stats.items() if name == nic]
|
||||
assert stats, 'No such network interface: {}'.format(nic)
|
||||
return _expand_stats(nic, stats[0])
|
||||
|
||||
return NetworkResponseList(
|
||||
[_expand_stats(nic, addr) for nic, addr in stats.items()]
|
||||
)
|
||||
|
||||
@action
|
||||
def sensors_temperature(
|
||||
self, sensor: Optional[str] = None, fahrenheit: bool = False
|
||||
|
@ -706,6 +676,7 @@ class SystemPlugin(SensorPlugin, EntityManager):
|
|||
NetworkInterfaceModel(
|
||||
id=f'system:network_interface:{nic["interface"]}',
|
||||
name=nic.pop('interface'),
|
||||
reachable=nic.pop('is_up'),
|
||||
**nic,
|
||||
)
|
||||
for nic in entities['network']
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from enum import Enum
|
||||
from socket import AddressFamily
|
||||
|
||||
from marshmallow import pre_load
|
||||
|
@ -20,6 +21,7 @@ class NetworkInterfaceBaseSchema(SystemBaseSchema):
|
|||
'errout': 'errors_out',
|
||||
'dropin': 'drop_in',
|
||||
'dropout': 'drop_out',
|
||||
'isup': 'is_up',
|
||||
}.items():
|
||||
if in_attr in data:
|
||||
data[out_attr] = data.pop(in_attr)
|
||||
|
@ -32,4 +34,10 @@ class NetworkInterfaceBaseSchema(SystemBaseSchema):
|
|||
addr['family'] = addr['family'].name
|
||||
data['addresses'][i] = addr
|
||||
|
||||
if isinstance(data.get('duplex'), Enum):
|
||||
data['duplex'] = data['duplex'].name.split('_')[-1]
|
||||
|
||||
# Split the flags string
|
||||
data['flags'] = data.get('flags', '').split(',')
|
||||
|
||||
return data
|
||||
|
|
|
@ -2,6 +2,8 @@ from dataclasses import dataclass, field
|
|||
from socket import AddressFamily
|
||||
from typing import List, Optional
|
||||
|
||||
from marshmallow.validate import OneOf
|
||||
|
||||
|
||||
@dataclass
|
||||
class NetworkInterface:
|
||||
|
@ -82,6 +84,55 @@ class NetworkInterface:
|
|||
}
|
||||
)
|
||||
|
||||
is_up: bool = field(
|
||||
metadata={
|
||||
'metadata': {
|
||||
'description': 'Whether the interface is active',
|
||||
'example': True,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
speed: int = field(
|
||||
metadata={
|
||||
'metadata': {
|
||||
'description': 'Interface reported speed in Mbps',
|
||||
'example': 10000,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
mtu: int = field(
|
||||
metadata={
|
||||
'metadata': {
|
||||
'description': 'Interface maximum transmission unit expressed '
|
||||
'in bytes',
|
||||
'example': 65535,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
duplex: str = field(
|
||||
metadata={
|
||||
'validate': OneOf(['FULL', 'HALF', 'UNKNOWN']),
|
||||
'metadata': {
|
||||
'description': 'Interface duplex configuration. Can be FULL, '
|
||||
'HALF or UNKNOWN',
|
||||
'example': 'FULL',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
flags: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
'metadata': {
|
||||
'description': 'List of flags associated to the interface',
|
||||
'example': ['up', 'broadcast', 'running'],
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
addresses: List['NetworkInterfaceAddress'] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
|
|
Loading…
Reference in a new issue