diff --git a/labgrid/resource/ethernetport.py b/labgrid/resource/ethernetport.py index 0020f26ba..1129ca8e1 100644 --- a/labgrid/resource/ethernetport.py +++ b/labgrid/resource/ethernetport.py @@ -12,23 +12,27 @@ class SNMPSwitch: """SNMPSwitch describes a switch accessible over SNMP. This class implements functions to query ports and the forwarding database.""" hostname = attr.ib(validator=attr.validators.instance_of(str)) + loop = attr.ib() def __attrs_post_init__(self): + import pysnmp.hlapi.v3arch.asyncio as hlapi + self.logger = logging.getLogger(f"{self}") self.ports = {} self.fdb = {} self.macs_by_port = {} + self.transport = self.loop.run_until_complete(hlapi.UdpTransportTarget.create((self.hostname, 161))) self._autodetect() def _autodetect(self): - from pysnmp import hlapi + import pysnmp.hlapi.v3arch.asyncio as hlapi - for (errorIndication, errorStatus, _, varBindTable) in hlapi.getCmd( + for (errorIndication, errorStatus, _, varBindTable) in self.loop.run_until_complete(hlapi.getCmd( hlapi.SnmpEngine(), hlapi.CommunityData('public'), - hlapi.UdpTransportTarget((self.hostname, 161)), + self.transport, hlapi.ContextData(), - hlapi.ObjectType(hlapi.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))): + hlapi.ObjectType(hlapi.ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)))): if errorIndication: raise Exception(f"snmp error {errorIndication}") elif errorStatus: @@ -51,7 +55,7 @@ def _get_ports(self): Returns: Dict[Dict[]]: ports and their values """ - from pysnmp import hlapi + import pysnmp.hlapi.v3arch.asyncio as hlapi variables = [ (hlapi.ObjectType(hlapi.ObjectIdentity('IF-MIB', 'ifIndex')), 'index'), @@ -64,14 +68,14 @@ def _get_ports(self): ] ports = {} - for (errorIndication, errorStatus, _, varBindTable) in hlapi.bulkCmd( + for (errorIndication, errorStatus, _, varBindTable) in self.loop.run_until_complete(hlapi.bulkCmd( hlapi.SnmpEngine(), hlapi.CommunityData('public'), - hlapi.UdpTransportTarget((self.hostname, 161)), + self.transport, hlapi.ContextData(), 0, 20, *[x[0] for x in variables], - lexicographicMode=False): + lexicographicMode=False)): if errorIndication: raise Exception(f"snmp error {errorIndication}") elif errorStatus: @@ -93,18 +97,18 @@ def _get_fdb_dot1d(self): Returns: Dict[List[str]]: ports and their values """ - from pysnmp import hlapi + import pysnmp.hlapi.v3arch.asyncio as hlapi ports = {} - for (errorIndication, errorStatus, _, varBindTable) in hlapi.bulkCmd( + for (errorIndication, errorStatus, _, varBindTable) in self.loop.run_until_complete(hlapi.bulkCmd( hlapi.SnmpEngine(), hlapi.CommunityData('public'), - hlapi.UdpTransportTarget((self.hostname, 161)), + self.transport, hlapi.ContextData(), 0, 50, hlapi.ObjectType(hlapi.ObjectIdentity('BRIDGE-MIB', 'dot1dTpFdbPort')), - lexicographicMode=False): + lexicographicMode=False)): if errorIndication: raise Exception(f"snmp error {errorIndication}") elif errorStatus: @@ -126,18 +130,18 @@ def _get_fdb_dot1q(self): Returns: Dict[List[str]]: ports and their values """ - from pysnmp import hlapi + import pysnmp.hlapi.v3arch.asyncio as hlapi ports = {} - for (errorIndication, errorStatus, _, varBindTable) in hlapi.bulkCmd( + for (errorIndication, errorStatus, _, varBindTable) in self.loop.run_until_complete(hlapi.bulkCmd( hlapi.SnmpEngine(), hlapi.CommunityData('public'), - hlapi.UdpTransportTarget((self.hostname, 161)), + self.transport, hlapi.ContextData(), 0, 50, hlapi.ObjectType(hlapi.ObjectIdentity('Q-BRIDGE-MIB', 'dot1qTpFdbPort')), - lexicographicMode=False): + lexicographicMode=False)): if errorIndication: raise Exception(f"snmp error {errorIndication}") elif errorStatus: @@ -177,6 +181,9 @@ def update(self): self.logger.debug("updating macs by port") self._update_macs() + def deactivate(self): + self.loop.close() + @attr.s class EthernetPortManager(ResourceManager): @@ -223,6 +230,8 @@ async def poll_neighbour(self): await asyncio.sleep(1.0) + self.loop = asyncio.get_event_loop() + async def poll_switches(self): current = set(resource.switch for resource in self.resources) removed = set(self.switches) - current @@ -230,7 +239,7 @@ async def poll_switches(self): for switch in removed: del self.switches[switch] for switch in new: - self.switches[switch] = SNMPSwitch(switch) + self.switches[switch] = SNMPSwitch(switch, self.loop) for switch in current: self.switches[switch].update() await asyncio.sleep(1.0) @@ -248,7 +257,6 @@ async def poll(self, handler): import traceback traceback.print_exc(file=sys.stderr) - self.loop = asyncio.get_event_loop() self.poll_tasks.append(self.loop.create_task(poll(self, poll_neighbour))) self.poll_tasks.append(self.loop.create_task(poll(self, poll_switches))) @@ -309,7 +317,6 @@ def poll(self): resource.extra = extra self.logger.debug("new information for %s: %s", resource, extra) - @target_factory.reg_resource @attr.s class SNMPEthernetPort(ManagedResource):