diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/NetworkInterface.vue b/platypush/backend/http/webapp/src/components/panels/Entities/NetworkInterface.vue
index 9b7a91509..8401558dc 100644
--- a/platypush/backend/http/webapp/src/components/panels/Entities/NetworkInterface.vue
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/NetworkInterface.vue
@@ -90,6 +90,51 @@
+
+
+
+
@@ -106,6 +151,8 @@ export default {
data() {
return {
isCollapsed: true,
+ areAddressesCollapsed: true,
+ displayedAddresses: {},
}
},
}
@@ -131,6 +178,12 @@ export default {
min-height: 3em;
cursor: pointer;
+ @include from($tablet) {
+ @include until($desktop) {
+ margin-left: 3.25em;
+ }
+ }
+
&:hover {
color: $default-hover-fg;
}
diff --git a/platypush/entities/system.py b/platypush/entities/system.py
index bdadc9dd4..8afa66580 100644
--- a/platypush/entities/system.py
+++ b/platypush/entities/system.py
@@ -198,6 +198,7 @@ if 'network_interface' not in Base.metadata:
errors_out = Column(Integer)
drop_in = Column(Integer)
drop_out = Column(Integer)
+ addresses = Column(JSON)
__mapper_args__ = {
'polymorphic_identity': __tablename__,
diff --git a/platypush/message/response/system/__init__.py b/platypush/message/response/system/__init__.py
index 4ddf35bd0..2078187e1 100644
--- a/platypush/message/response/system/__init__.py
+++ b/platypush/message/response/system/__init__.py
@@ -28,40 +28,6 @@ class SensorResponse(SystemResponse):
pass
-class NetworkAddressResponse(NetworkResponse):
- def __init__(
- self,
- nic: str,
- ipv4_address: Optional[str] = None,
- ipv4_netmask: Optional[str] = None,
- ipv4_broadcast: Optional[str] = None,
- ipv6_address: Optional[str] = None,
- ipv6_netmask: Optional[str] = None,
- ipv6_broadcast: Optional[str] = None,
- mac_address: Optional[str] = None,
- mac_broadcast: Optional[str] = None,
- ptp: Optional[str] = None,
- *args,
- **kwargs
- ):
- super().__init__(
- *args,
- output={
- 'nic': nic,
- 'ipv4_address': ipv4_address,
- 'ipv4_netmask': ipv4_netmask,
- 'ipv4_broadcast': ipv4_broadcast,
- 'ipv6_address': ipv6_address,
- 'ipv6_netmask': ipv6_netmask,
- 'ipv6_broadcast': ipv6_broadcast,
- 'mac_address': mac_address,
- 'mac_broadcast': mac_broadcast,
- 'ptp': ptp,
- },
- **kwargs
- )
-
-
class NetworkInterfaceStatsResponse(NetworkResponse):
def __init__(
self, nic: str, is_up: bool, duplex: str, speed: int, mtu: int, *args, **kwargs
diff --git a/platypush/plugins/system/__init__.py b/platypush/plugins/system/__init__.py
index 7e3fdc579..8c5f7a789 100644
--- a/platypush/plugins/system/__init__.py
+++ b/platypush/plugins/system/__init__.py
@@ -1,5 +1,4 @@
import os
-import socket
from datetime import datetime
from typing import Tuple, Union, List, Optional, Dict
@@ -23,7 +22,6 @@ from platypush.entities.system import (
)
from platypush.message.response.system import (
NetworkResponseList,
- NetworkAddressResponse,
NetworkInterfaceStatsResponse,
SensorTemperatureResponse,
SensorResponseList,
@@ -257,9 +255,14 @@ class SystemPlugin(SensorPlugin, EntityManager):
return DiskSchema().dump(self._disk_info(), many=True)
def _net_io_counters(self) -> List[NetworkInterface]:
+ addrs = psutil.net_if_addrs()
return NetworkInterfaceSchema().load( # type: ignore
[
- {'interface': interface, **stats._asdict()}
+ {
+ 'interface': interface,
+ 'addresses': addrs.get(interface, []),
+ **stats._asdict(),
+ }
for interface, stats in psutil.net_io_counters(pernic=True).items()
if any(bool(val) for val in stats._asdict().values())
],
@@ -328,62 +331,6 @@ class SystemPlugin(SensorPlugin, EntityManager):
many=True,
)
- @action
- def net_addresses(
- self, nic: Optional[str] = None
- ) -> Union[NetworkAddressResponse, NetworkResponseList]:
- """
- Get address info associated to 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.NetworkAddressResponse` or list of
- :class:`platypush.message.response.system.NetworkAddressResponse`.
- """
- addrs = psutil.net_if_addrs()
-
- def _expand_addresses(_nic, _addrs):
- args = {'nic': _nic}
-
- for addr in _addrs:
- if addr.family == socket.AddressFamily.AF_INET:
- args.update(
- {
- 'ipv4_address': addr.address,
- 'ipv4_netmask': addr.netmask,
- 'ipv4_broadcast': addr.broadcast,
- }
- )
- elif addr.family == socket.AddressFamily.AF_INET6:
- args.update(
- {
- 'ipv6_address': addr.address,
- 'ipv6_netmask': addr.netmask,
- 'ipv6_broadcast': addr.broadcast,
- }
- )
- elif addr.family == socket.AddressFamily.AF_PACKET:
- args.update(
- {
- 'mac_address': addr.address,
- 'mac_broadcast': addr.broadcast,
- }
- )
-
- if addr.ptp and not args.get('ptp'):
- args['ptp'] = addr.ptp
-
- return NetworkAddressResponse(**args)
-
- if nic:
- addrs = [addr for name, addr in addrs.items() if name == nic]
- assert addrs, 'No such network interface: {}'.format(nic)
- addr = addrs[0]
- return _expand_addresses(nic, addr)
-
- return NetworkResponseList(
- [_expand_addresses(nic, addr) for nic, addr in addrs.items()]
- )
-
@action
def net_stats(
self, nic: Optional[str] = None
diff --git a/platypush/schemas/system/_network/_base.py b/platypush/schemas/system/_network/_base.py
index 41231460e..2fca5fc0c 100644
--- a/platypush/schemas/system/_network/_base.py
+++ b/platypush/schemas/system/_network/_base.py
@@ -1,3 +1,5 @@
+from socket import AddressFamily
+
from marshmallow import pre_load
from .._base import SystemBaseSchema
@@ -11,6 +13,8 @@ class NetworkInterfaceBaseSchema(SystemBaseSchema):
@pre_load
def pre_load(self, data: dict, **_) -> dict:
data = super().pre_load(data)
+
+ # Custom attribute mappings
for in_attr, out_attr in {
'errin': 'errors_in',
'errout': 'errors_out',
@@ -20,4 +24,12 @@ class NetworkInterfaceBaseSchema(SystemBaseSchema):
if in_attr in data:
data[out_attr] = data.pop(in_attr)
+ # Serialize enum values
+ for i, addr in enumerate(data.get('addresses', [])):
+ if hasattr(addr, '_asdict'):
+ addr = addr._asdict()
+ if isinstance(addr.get('family'), AddressFamily):
+ addr['family'] = addr['family'].name
+ data['addresses'][i] = addr
+
return data
diff --git a/platypush/schemas/system/_network/_model.py b/platypush/schemas/system/_network/_model.py
index 98db4e4bb..c9bd7cb51 100644
--- a/platypush/schemas/system/_network/_model.py
+++ b/platypush/schemas/system/_network/_model.py
@@ -1,5 +1,6 @@
from dataclasses import dataclass, field
-from typing import Optional
+from socket import AddressFamily
+from typing import List, Optional
@dataclass
@@ -80,3 +81,63 @@ class NetworkInterface:
},
}
)
+
+ addresses: List['NetworkInterfaceAddress'] = field(
+ default_factory=list,
+ metadata={
+ 'metadata': {
+ 'description': 'List of addresses associated to the interface',
+ 'example': [
+ {
+ 'family': AddressFamily.AF_INET.name,
+ 'address': '192.168.1.2',
+ 'netmask': '255.255.255.0',
+ 'broadcast': '192.168.1.255',
+ }
+ ],
+ },
+ },
+ )
+
+
+@dataclass
+class NetworkInterfaceAddress:
+ """
+ Network interface address data class.
+ """
+
+ family: AddressFamily = field(
+ metadata={
+ 'metadata': {
+ 'description': 'Address family',
+ 'example': AddressFamily.AF_INET.name,
+ }
+ }
+ )
+
+ address: Optional[str] = field(
+ metadata={
+ 'metadata': {
+ 'description': 'IPv4 or IPv6 address of the interface',
+ 'example': '192.168.1.2',
+ }
+ }
+ )
+
+ netmask: Optional[str] = field(
+ metadata={
+ 'metadata': {
+ 'description': 'Netmask for the interface address',
+ 'example': '255.255.255.0',
+ }
+ }
+ )
+
+ broadcast: Optional[str] = field(
+ metadata={
+ 'metadata': {
+ 'description': 'Broadcast address for the interface',
+ 'example': '192.168.1.255',
+ }
+ }
+ )