-
+
+
+
+
+
+
+
diff --git a/platypush/entities/system.py b/platypush/entities/system.py
index 8afa66580..5932ea4e0 100644
--- a/platypush/entities/system.py
+++ b/platypush/entities/system.py
@@ -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__,
diff --git a/platypush/message/response/system/__init__.py b/platypush/message/response/system/__init__.py
index 2078187e1..a4269af06 100644
--- a/platypush/message/response/system/__init__.py
+++ b/platypush/message/response/system/__init__.py
@@ -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)
diff --git a/platypush/plugins/system/__init__.py b/platypush/plugins/system/__init__.py
index f686f2a10..053435b21 100644
--- a/platypush/plugins/system/__init__.py
+++ b/platypush/plugins/system/__init__.py
@@ -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']
diff --git a/platypush/schemas/system/_network/_base.py b/platypush/schemas/system/_network/_base.py
index 2fca5fc0c..97f3affc2 100644
--- a/platypush/schemas/system/_network/_base.py
+++ b/platypush/schemas/system/_network/_base.py
@@ -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
diff --git a/platypush/schemas/system/_network/_model.py b/platypush/schemas/system/_network/_model.py
index c9bd7cb51..68b1f03e7 100644
--- a/platypush/schemas/system/_network/_model.py
+++ b/platypush/schemas/system/_network/_model.py
@@ -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={