diff --git a/netbox_agent/lldp.py b/netbox_agent/lldp.py index af50d1b..ddd8697 100644 --- a/netbox_agent/lldp.py +++ b/netbox_agent/lldp.py @@ -8,18 +8,35 @@ class LLDP(): def parse(self): output_dict = {} + vlans = {} + vid = None for entry in self.output.splitlines(): if '=' not in entry: continue path, value = entry.strip().split("=", 1) - path = path.split(".") - path_components, final = path[:-1], path[-1] - + split_path = path.split(".") + interface = split_path[1] + path_components, final = split_path[:-1], split_path[-1] current_dict = output_dict + + if vlans.get(interface) is None: + vlans[interface] = {} + for path_component in path_components: current_dict[path_component] = current_dict.get(path_component, {}) current_dict = current_dict[path_component] - current_dict[final] = value + if 'vlan-id' in path: + vid = value + vlans[interface][value] = vlans[interface].get(vid, {}) + elif path.endswith('vlan'): + vid = value.replace('vlan-', '') + vlans[interface][vid] = vlans[interface].get(vid, {}) + elif 'pvid' in path: + vlans[interface][vid]['pvid'] = True + if 'vlan' not in path: + current_dict[final] = value + for interface, vlan in vlans.items(): + output_dict['lldp'][interface]['vlan'] = vlan return output_dict def get_switch_ip(self, interface): @@ -38,11 +55,4 @@ class LLDP(): # lldp.eth0.vlan.vlan-id=296 if self.data['lldp'].get(interface) is None: return None - - lldp = self.data['lldp'][interface] - if lldp.get('vlan'): - if type(lldp['vlan']) is str: - return int(lldp['vlan'].replace('vlan-', '')) - elif lldp['vlan'].get('vlan-id'): - return int(lldp['vlan'].get('vlan-id')) - return None + return self.data['lldp'][interface]['vlan'] diff --git a/netbox_agent/network.py b/netbox_agent/network.py index 398f649..bbb1b12 100644 --- a/netbox_agent/network.py +++ b/netbox_agent/network.py @@ -224,17 +224,20 @@ class Network(): interface.mode = 200 interface.tagged_vlans = [nb_vlan] if nb_vlan else [] interface.untagged_vlan = None - # if lldp reports a vlan-id - elif lldp_vlan and ( - interface.mode is None or interface.mode.value != 100 or - interface.untagged_vlan is None or - interface.untagged_vlan.vid != lldp_vlan): - logging.info('Resetting access VLAN on interface {interface}'.format( - interface=interface)) - update = True - nb_vlan = self.get_or_create_vlan(lldp_vlan) - interface.mode = 100 - interface.untagged_vlan = nb_vlan.id + # if lldp reports a vlan-id with pvid + elif lldp_vlan: + pvid_vlan = [key for (key, value) in lldp_vlan.items() if value['pvid']] + if len(pvid_vlan) > 0 and ( + interface.mode is None or + interface.mode.value != 100 or + interface.untagged_vlan is None or + interface.untagged_vlan.vid != int(pvid_vlan[0])): + logging.info('Resetting access VLAN on interface {interface}'.format( + interface=interface)) + update = True + nb_vlan = self.get_or_create_vlan(pvid_vlan[0]) + interface.mode = 100 + interface.untagged_vlan = nb_vlan.id return update, interface def create_or_update_ipmi(self): @@ -295,10 +298,14 @@ class Network(): interface.save() elif config.network.lldp and self.lldp.get_switch_vlan(nic['name']) is not None: # if lldp reports a vlan on an interface, tag the interface in access and set the vlan - vlan_id = self.lldp.get_switch_vlan(nic['name']) - nb_vlan = self.get_or_create_vlan(vlan_id) - interface.mode = 100 - interface.untagged_vlan = nb_vlan.id + # report only the interface which has `pvid=yes` (ie: lldp.eth3.vlan.pvid=yes) + # if pvid is not present, it'll be processed as a vlan tagged interface + vlans = self.lldp.get_switch_vlan(nic['name']) + for vid, vlan_infos in vlans.items(): + nb_vlan = self.get_or_create_vlan(vid) + if vlan_infos.get('vid'): + interface.mode = 100 + interface.untagged_vlan = nb_vlan.id interface.save() # cable the interface