def ParseInterfaceConfigurations(self): """Gets router running configurtion to collect interface configurations""" # Get running configuration to parse if not self._running_config: self._running_config = Session.ExecCommand("show running-config") self._interfaceConfigurations = {} currentIntfName = "" currentIntfConfig = [] intfConfigBlock = False for thisLine in self._running_config.splitlines(): try: words = filter(None, thisLine.split(" ")) rep_IntfLine = r"(?<=^interface)\s+(\d+\/\d+)" m_intfLine = re.findall(rep_IntfLine, thisLine, re.IGNORECASE) if len(m_intfLine): # This should be a new interface definition currentIntfConfig = [] currentIntfName = m_intfLine[0].strip() intfConfigBlock = True elif intfConfigBlock: sline = thisLine.strip() if sline and sline != "exit": currentIntfConfig.append(sline) if sline == "exit" and currentIntfName: # add the interface config self._interfaceConfigurations[ currentIntfName] = "\r\n".join(currentIntfConfig) intfConfigBlock = False except Exception as Ex: message = "Hirschmann.InterfaceParser.ParseInterfaceConfigurations() : could not parse an interface configuration for line <{0}>. Error is : {1} ".format( thisLine, str(Ex)) DebugEx.WriteLine(message)
def ParseInterfaceConfigurations(self): """Gets router running configurtion to collect interface configurations""" # Get running configuration to parse if not self._running_config: self._running_config = Session.ExecCommand( "show running-config interface") if len( self._running_config ) < 100 and "Command authorization failed" in self._running_config: # some systems may not allow running "show run" but still allow "show tech", let's give a try :-) tech_support_ipc = Session.ExecCommand("show tech-support") temp_running_config = [] riBlock = False for line in tech_support_ipc.splitlines(): if riBlock: if line.find("--- show") > 0: # end of running configuration block break temp_running_config.append(line) else: if line.find("--- show running-config ---") > 0: # start of running configuration block riBlock = True self._running_config = "\r\n".join(temp_running_config) self._interfaceConfigurations = {} self._ifNames = {} self._nameIfs = {} currentIntfName = "" currentIntfConfig = [] for thisLine in self._running_config.splitlines(): try: words = thisLine.split(" ") if thisLine.startswith("interface") and len(words) == 2: # This should be a new interface definition if currentIntfName != "": # add previous interface self._interfaceConfigurations[ currentIntfName] = "\r\n".join(currentIntfConfig) # Clear current configuration currentIntfConfig = [] currentIntfName = words[1] else: sline = thisLine.strip(' ') if sline != "!": currentIntfConfig.append(sline) # region memorize ASA nameif properties m = re.findall(r"(?<=nameif ).*", sline) if len(m) == 1: nameif = m[0].strip() self._ifNames[currentIntfName] = nameif self._nameIfs[nameif] = currentIntfName except Exception as Ex: message = "CiscoASA.InterfaceParser.ParseInterfaceConfigurations() : could not parse an interface configuration for line <{0}>. Error is : {1} ".format( thisLine, str(Ex)) DebugEx.WriteLine(message)
def GetSystemMAC(self, instance): """Returns the MAC addresses associated with the local system for the given routing instance""" systemMAC = "" v = self.GetVersion() rep_BackplaneMAC = r"^Base MAC Address(?:.+\.)\s(.*)" try: systemMAC = GetRegexGroupMatches(rep_BackplaneMAC, v, 1)[0].strip() except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.GetSystemMAC() : unexpected error : {0}". format(str(Ex))) return systemMAC
def GetManagementIP(self): """Returns the management ip address as a string""" sysIP = ConnectionInfo.DeviceIP v = self.GetVersion() rep_SystemIP = r"system ip address\.+(.*)" try: sysIP = GetRegexGroupMatches(rep_SystemIP, v, 1)[0].strip() except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.GetManagementIP() : unexpected error : {0}". format(str(Ex))) return sysIP
def GetHostName(self): """ Returns the host bane as a string""" if not self._hostName: v = self.GetVersion() rep_SystemName = r"^System Name\.+(.*)" try: self._hostName = GetRegexGroupMatches(rep_SystemName, v, 1)[0].strip() except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.GetHostName() : unexpected error : {0}". format(str(Ex))) return self._hostName
def GetInventory(self): """Returns the device inventory string""" if self.SwitchType == HirshmannSwitchType.MachSwitch: # regex group 1 : Power Supply Information rep_PSInfo = r"power supply information:([\s\S]+(?=media module information))" # regex group 1 : Media Module Information rep_MMInfo = r"media module information:([\s\S]+(?=sfp information))" # regex group 1 : Media Module Information rep_SFPInfo = r"sfp information[\w\s\S]+:([\s\S]+(?=^CPU))" v = self.GetVersion() inventoryText = "unknown" try: PSInfo = GetRegexGroupMatches(rep_PSInfo, v, 1)[0] MMInfo = GetRegexGroupMatches(rep_MMInfo, v, 1)[0] SFPInfo = GetRegexGroupMatches(rep_SFPInfo, v, 1)[0] inventoryText = "\r\n".join([PSInfo, MMInfo, SFPInfo]) except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.GetInventory() : unexpected error : {0}". format(str(Ex))) return inventoryText elif self.SwitchType == HirshmannSwitchType.RailSwitch: # regex group 1 : Power Supply Information rep_PSInfo = r"power supply.*" # regex group 1 : Media Module Information rep_MMInfo = r"media module information.*" v = self.GetVersion() inventoryText = "unknown" try: PSInfo = "\r\n".join(re.findall(rep_PSInfo, v, re.IGNORECASE)) MMInfo = "\r\n".join(re.findall(rep_MMInfo, v, re.IGNORECASE)) inventoryText = "\r\n".join([PSInfo, MMInfo]) except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.GetInventory() : unexpected error : {0}". format(str(Ex))) return inventoryText
def GetSystemSerial(self): """Returns System serial numbers as a string, calculated from Inventory""" if not self._SystemSerial : ss = "" # first try to check inventory for serial numbers inv = self.GetInventory() failwords = self.ScriptSettings.FailedCommandPattern.split(";") if any(fw in inv for fw in failwords) or "invalid input" in inv.lower(): # show inventory did not work, try to parse version information for system serial number DebugEx.WriteLine("CiscoIOSRouter : router does not support \"show inventory\" command, parsing version information", DebugLevel.Debug) r_serial = re.findall(r"(?<=System serial number : ).*", self.GetVersion(), re.IGNORECASE) if len(r_serial) > 0: self._SystemSerial = r_serial[0] else: if self.GetStackCount() > 0 : modules = Session.ExecCommand("show module") if any(fw in modules for fw in failwords) or "invalid input" in modules.lower(): # show module did not work, try to parse version information to get system serial numbers DebugEx.WriteLine("CiscoIOSRouter : router does not support \"sh module\" command, parsing version information", DebugLevel.Debug) r_serial = re.findall(r"(?<=System serial number : ).*", self.GetVersion(), re.IGNORECASE) if len(r_serial) > 0: self._SystemSerial = r_serial[0] else: # try to parse sh_version to get system serial numbers # TODO : missing command output sample to process pass else: SNs = re.finditer(r"(?<=SN: ).*", inv, re.MULTILINE) self._SystemSerial = ",".join([SN.group() for matchNum, SN in enumerate(SNs, start=1)]) FPCs = re.findall(r"FPC \d.*", inv) for thisFPC in FPCs : words = filter(None, thisFPC.split(" ")) ss += (";" + words[5]) self._SystemSerial = ss.strip(";") return self._SystemSerial
def GetSystemSerial(self): """Returns System serial numbers as a string, calculated from Inventory""" if not self._SystemSerial: v = self.GetVersion() if self.SwitchType == HirshmannSwitchType.MachSwitch: rep_BackplaneSerial = r"^Serial Number \(Backplane\)\.+(.*)" elif self.SwitchType == HirshmannSwitchType.RailSwitch: rep_BackplaneSerial = r"^Serial Number\.+(.*)" try: self._SystemSerial = GetRegexGroupMatches( rep_BackplaneSerial, v, 1)[0].strip() except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.GetSystemSerial() : unexpected error : {0}" .format(str(Ex))) return self._SystemSerial
def GetModelNumber(self): """Returns Model number as a string, calculated from Inventory""" if not self._ModelNumber: v = self.GetVersion() if self.SwitchType == HirshmannSwitchType.MachSwitch: rep_Backplane = r"Backplane Hardware Description\.+(.*)" elif self.SwitchType == HirshmannSwitchType.RailSwitch: rep_Backplane = r"Hardware Description\.+(.*)" try: self._ModelNumber = GetRegexGroupMatches(rep_Backplane, v, 1)[0].strip() except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.GetModelNumber() : unexpected error : {0}". format(str(Ex))) return self._ModelNumber
def GetSystemMAC(self, instance): """Returns the CSV list of MAC addresses associated with the local system for the given routing instance""" # For ASA, we skip the instance. Cotexts are not yet supported by this parser systemMACs = [] v = self.GetVersion() rep_systemMACs = r"(?!0000)[a-f,0-9]{4}\.[a-f,0-9]{4}\.[a-f,0-9]{4}" try: ri_systemMACs = re.finditer(rep_systemMACs, v, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(ri_systemMACs): systemMACs.append(match.group()) except Exception as Ex: DebugEx.WriteLine( "CiscoASA.GetSystemMAC() : unexpected error : {0}".format( str(Ex))) return ",".join(systemMACs)
def ResolveObjectSubnet(self, objectName): """Returns a dictionary of network address and mask for the given object name like {Subnet:"1.0.0.0", Mask:"255.0.0.0"}""" if not objectName: return None try: result = Session.ExecCommand( "show run object id {0}".format(objectName)) rep_SubnetAddressAndMask = r"\s+subnet\s(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)\s(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)" subnetAddress = GetRegexGroupMatches(rep_SubnetAddressAndMask, result, 1)[0] subnetMask = GetRegexGroupMatches(rep_SubnetAddressAndMask, result, 2)[0] return {"Subnet": subnetAddress, "Mask": subnetMask} except Exception as Ex: message = "CiscoASA Static route parser : could not resolve object name : {0} due to error : {1}".format( objectName, str(Ex)) DebugEx.WriteLine(message) return None
def Parse(self, nRegistry, cToken, instance): """Collects information about active tunnels and registers them with Network Discovery Engine""" # The neighbor registry object is received as parameter # This must be used to register a new neighbor for further discovery. # -- # A CancellationToken is also passed as parameter. The token should be checked repetitively whether cancellation was requested # by user and if yes, stop further processing. # -- # The RoutingInstance object to work with is also passed as a parameter instanceName = "default" if instance: instanceName = instance.Name.lower() OperationStatusLabel = "Collecting ip routes..." cToken.ThrowIfCancellationRequested() routes = Session.ExecCommand("show ip route static") cToken.ThrowIfCancellationRequested() OperationStatusLabel = "Processing STATIC route entries..." # regex groups => 1 : network, 2 : subnet mask, 3 : preference, 4 : next-hop, 5: status, 6 : out interface rep_StaticWithAddressOnly = r"^(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\s+(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\s+(\d+)\s+(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\s+([^\s]+)\s+([^\s]+)" # Enumerate static routes containing addresses only static_with_address = re.finditer(rep_StaticWithAddressOnly, routes, re.MULTILINE) for matchnum, match in enumerate(static_with_address): try: # Group 1 : destination network, Group 2 : metric, Group 3 : dst. network mask, Group 4: next-hop, Group5 : outgoing interface networkAddress = match.group(1).strip() networkAddressMask = match.group(2).strip() maskLength = IPOperations.GetMaskLength(networkAddressMask) routeForNetwork = "{0}/{1}".format(networkAddress, maskLength) metric = match.group(3).strip() nexthop = match.group(4).strip() routeStatus = match.group(5).strip() outInterfaceName = match.group(6).strip() ri = self.Router.GetInterfaceByName(outInterfaceName, instance) if ri != None: OperationStatusLabel = "Registering static neighbor {0}...".format( ri.Address) nRegistry.RegisterSTATICNeighbor(self.Router, instance, routeForNetwork, nexthop, ri.Address, ri) except Exception as Ex: message = "Hirschmann Static route parser: could not parse a static route entry because : {0} ".format( str(Ex)) DebugEx.WriteLine(message)
def RouteTableSize(self, instance): """Returns the size of the route table for the requested routing instance""" instanceName = self._defaultRoutingInstanceName if instance : instanceName = instance.Name routeTableSize = -1 try : cmd = "show ip route summary" if instanceName != self._defaultRoutingInstanceName: cmd = "show ip route vrf {0} summary".format(instanceName) routeSummary = Session.ExecCommand(cmd) routeTotals = filter(lambda s: s.startswith("Total"), routeSummary.splitlines()) if len(routeTotals) > 0: # return the last number in Total line words = filter(None, routeTotals[0].split(' ')) routeTableSize = int(words[2]) except Exception as Ex : DebugEx.WriteLine("CiscoIOSRouter : error calculating route table size : {0}".format(str(Ex))) return routeTableSize
def Parse(self, nRegistry, cToken, instance): """Collects information about active tunnels and registers them with Network Discovery Engine""" # The neighbor registry object is received as parameter # This must be used to register a new neighbor for further discovery. # -- # A CancellationToken is also passed as parameter. The token should be checked repetitively whether cancellation was requested # by user and if yes, stop further processing. # -- # The RoutingInstance object to work with is also passed as a parameter instanceName = "default" if instance: instanceName = instance.Name.lower() OperationStatusLabel = "Identifying router..." #-- cToken.ThrowIfCancellationRequested() # # Compiled regex search patters rep_ConnectionIndex = r"^Index\s+:\s(\d+)" rep_ConnectionAddress = r"^Connection\s+:\s(.*)" rep_Encryption = r"^Encryption\s+:\s(.*)" rep_Hashing = r"^Hashing\s+:\s(.*)" rep_EncHash = r"^Encryption\s+:\s(.+)Hashing\s+:\s(.+)" # rep_IPSecBlocks = r"IPsec:.*\s*(?:(?:(?!^IPsec:)[\s\S])*)" rep_LocalAddr = r"Local Addr\s+:\s((?:\d{1,3}.){3}\d{1,3}/(?:\d{1,3}.){3}\d{1,3})" rep_RemoteAddr = r"Remote Addr\s+:\s((?:\d{1,3}.){3}\d{1,3}/(?:\d{1,3}.){3}\d{1,3})" # get vpn session details for l2l tunnels l2lTunnels = Session.ExecCommand("show vpn-sessiondb detail l2l") # extract connection indexes, get match iterator connectionIndexes = GetRegexGroupMatches(rep_ConnectionIndex, l2lTunnels, 1) try: for thisConnectionIndex in connectionIndexes: try: # get detail for this connection index thisConnectionDetails = Session.ExecCommand( "show vpn-sessiondb detail index {0}".format( thisConnectionIndex)) # extract remote ip address from thisConnectionDetails, get match iterator thisConnectionRemoteAddresses = GetRegexGroupMatches( rep_ConnectionAddress, thisConnectionDetails, 1) for tunnel_RemoteAddress in thisConnectionRemoteAddresses: # get local address for this remote address thisConnectionIPSEC = Session.ExecCommand( "sh crypto ipsec sa | i remote crypto endpt.: {0}". format(tunnel_RemoteAddress)).splitlines()[0] # extract the first ip address from result, that will be the local address tunnel_LocalAddress = GetIndexedIPAddressFromLine( thisConnectionIPSEC, 1) if tunnel_LocalAddress: cipherAlgs = GetRegexGroupMatches( rep_EncHash, thisConnectionDetails, 1) if len(cipherAlgs) > 0: cipherAlg = cipherAlgs[0] else: cipherAlg = "n/a" hashAlgs = GetRegexGroupMatches( rep_EncHash, thisConnectionDetails, 2) if len(hashAlgs) > 0: hashAlg = hashAlgs[0] else: hashAlg = "n/a" # get local / remote networks for each ipsec tunnel localProxies = GetRegexGroupMatches( rep_LocalAddr, thisConnectionDetails, 1) remoteProxies = GetRegexGroupMatches( rep_RemoteAddr, thisConnectionDetails, 1) s_localProxies = "\r\n".join(localProxies) s_remoteProxies = "\r\n".join(remoteProxies) # # RegisterTunnel parameters in order : #/// <param name="router">The IRouter requesting registration</param> #/// <param name="instance">The routing instance the tunnel is terminating on</param> #/// <param name="tunnelProtocol">The protocol used to establish the tunnel</param> #/// <param name="tunnelType">The link-type over the tunnel</param> #/// <param name="tunnelName">Optional : tunnel name or description</param> #/// <param name="tunnelState">Tunnel connection state</param> #/// <param name="externalLocalAddress">Tunnel external, local address</param> #/// <param name="externalRemoteAddress">Tunnel external, remote address</param> #/// <param name="tunnelSourceAddress">Optional : Tunnel internal source address</param> #/// <param name="tunnelDestinationAddress">Optional : Tunnel internal destination address</param> #/// <param name="localProxy">Optional : the local networks the tunnel is forwarding for. If not empty, must contain valid ipv4 network prefixes per line</param> #/// <param name="remoteProxy">Optional : the remote networks the tunnel is forwarding for. If not empty, must contain valid ipv4 network prefixes per line</param> #/// <param name="cipher">Optional : the cipher algorithm used by the tunnel</param> #/// <param name="hash">Optional : the hashing algorithm used by the tunnel</param> #/// <param name="tag">Optional : any data to include. Max length is 1024 characters</param> nRegistry.RegisterTunnel( self.Router, instance, L3Discovery.NeighborProtocol.IPSEC, L3Discovery.LinkType.P2P, None, L3Discovery.NeighborState.Established, tunnel_LocalAddress.strip(), tunnel_RemoteAddress.strip(), None, None, s_localProxies, s_remoteProxies, cipherAlg, hashAlg, None) except Exception as Ex: pass except Exception as Ex: message = "CiscoASA Router Module Error : could not parse vpn-sessiondb information because : {1} ".format( str(Ex)) DebugEx.WriteLine(message)
def ParseInterfaces(self, instance) : """Collects interface details for all interfaces of specified routing instance, but do not collect interface configuration """ # Get the interfaces configurations if len(self._interfaceConfigurations) == 0 : self.ParseInterfaceConfigurations() # Init interface dictionary for instance instanceName = self.Router._defaultRoutingInstanceName if instance : instanceName = instance.Name if self.Interfaces.get(instanceName, None) == None: self.Interfaces[instanceName] = [] # Query the device interfaces interfaces = Session.ExecCommand("show ip interface").splitlines() # Parse the result and fill up self.Interfaces list ri = L3Discovery.RouterInterface() lineCount = len(interfaces) currentLineIndex = 1 for line in interfaces: try: indentLevel = len(line) - len(line.lstrip(' ')) if indentLevel == 0 or currentLineIndex == lineCount : # this is either a new interface block, or the end of the interface list if ri and ri.Name : # Add actual interface if vrf name matches instanceName if not ri.VRFName and instanceName == self.Router._defaultRoutingInstanceName or ri.VRFName == instanceName: ri.Configuration = self.GetInterfaceConfiguration(ri.Name) if ri.Configuration.find("encapsulation dot1q") >= 0 : ri.PortMode = L3Discovery.RouterInterfacePortMode.L3Subinterface subinterfaceDefinition = next((cline for cline in ri.Configuration.splitlines() if cline.startswith("encapsulation dot1q")), "") ri.VLANS = subinterfaceDefinition.split(' ')[-1] elif ri.Address : ri.PortMode = L3Discovery.RouterInterfacePortMode.Routed elif ri.Configuration.find("switchport mode trunk") >= 0 : ri.PortMode = L3Discovery.RouterInterfacePortMode.Trunk # get allowed vlans cmd = "show interfaces {0} trunk".format(ri.Name) cmdResult = Session.ExecCommand(cmd) #Port Mode Encapsulation Status Native vlan #Fa0/2 on 802.1q trunking 1 # #Port Vlans allowed on trunk #Fa0/2 1-4,7,11,13-4094 # #Port Vlans allowed and active in management domain #Fa0/2 1 # #Port Vlans in spanning tree forwarding state and not pruned #Fa0/2 1 vlanBlock = False for vLine in cmdResult.splitlines(): if "Vlans allowed on trunk" in vLine: vlanBlock = True continue if vlanBlock and vLine.strip() == "" : break; elif vlanBlock: words = filter(None, vLine.split(' ')) if len(words) == 2: vlanList = words[0] ri.VLANS = re.sub(r",", "|", vlanList) elif ri.Configuration.find("switchport mode access") >= 0 : ri.PortMode = L3Discovery.RouterInterfacePortMode.Access accessVlan = next((cline for cline in ri.Configuration.splitlines() if cline.startswith("switchport access vlan")), "") ri.VLANS = accessVlan.split(' ')[-1] else : ri.PortMode = L3Discovery.RouterInterfacePortMode.Unknown ri.Description = next((cline for cline in ri.Configuration.splitlines() if cline.startswith("description")), "") self.Interfaces[instanceName].Add(ri) if currentLineIndex == lineCount : break # Create new interface ri = L3Discovery.RouterInterface() words = filter(None, line.split(' ')) # words should look like : GigabitEthernet0/0/0,is,up,line,protocol,is,up ri.LogicalSystemName = "Default" ri.Name = words[0] status = [i.strip(',') for i in words if "up" in i.lower() or "down" in i.lower()] ri.Status = ",".join(status) else: # this line belongs to an iterface information block sline = line.strip().lower() if sline.startswith("internet address"): addressAndMask = GetIPAddressAndMaskFromLine(sline).split('/') ri.Address = addressAndMask[0] ri.MaskLength = addressAndMask[1] elif sline.startswith("vpn routing/forwarding"): words = filter(None, line.split(' ')) ri.VRFName = words[-1].strip('"') # PortMode and VLANS will be processed later in a second pass except Exception as Ex: DebugEx.WriteLine("CiscoIOSRouter.InterfaceParser.ParseInterfaces() : error parsing text {0}. Error is {1}".format(line, str(Ex))) currentLineIndex += 1
def CalculateRouterIDAndASNumber(self, instance): """Parse the RouterID and AS number for the requested RoutingInstance""" instanceName = self.Router._defaultRoutingInstanceName if instance : instanceName = instance.Name if self.RouterID.get(instanceName, None) == None: self.RouterID[instanceName] = {} # Determine default router ID globalRouterID = ConnectionInfo.DeviceIP l3interfaces = Session.ExecCommand("sh ip interface brief") if l3interfaces: try : loopbacks = [intf.lower() for intf in l3interfaces.splitlines() if intf.lower().startswith("loopback") and GetIPAddressFromLine(intf)] if len(loopbacks) > 0 : # find the loopback with lowest number lowestLoopback = sorted(loopbacks, key=lambda i: int(i[8:10]))[0] if lowestLoopback: globalRouterID = lowestLoopback.split()[1] else: # no loopbacks, find the interface with highest ip address highestIPLine = (sorted(l3interfaces.splitlines(), key=lambda i: IP2Int(GetIPAddressFromLine(i)))[-1]).strip() if highestIPLine: globalRouterID = GetIPAddressFromLine(highestIPLine) except Exception as Ex : DebugEx.WriteLine("CiscoIOSRouter.CalculateRouterIDAndASNumber() : error while parsing interface information : " + str(Ex)) # get the running routing protocols for this routing instance runnintRoutingProtocols = self.Router.ActiveProtocols(instance) for thisProtocol in runnintRoutingProtocols: if thisProtocol == L3Discovery.NeighborProtocol.BGP: # construct CLI command if instanceName == self.Router._defaultRoutingInstanceName : cmd = "show ip bgp summary" else: cmd = "show ip bgp vpnv4 vrf {0} summary".format(instanceName) bgpSummary = Session.ExecCommand(cmd) match = re.findall(r"(?<=BGP router identifier )[\d.]{0,99}", bgpSummary, re.IGNORECASE) if len(match) == 1 : self.RouterID[instanceName][str(thisProtocol)] = match[0] if globalRouterID == ConnectionInfo.DeviceIP : globalRouterID = match[0] # get also the BGP AS number match = re.findall(r"(?<=local AS number )[\d.]{0,99}", bgpSummary, re.IGNORECASE) if len(match) == 1 : self.BGPASNumber[instanceName] = match[0] elif thisProtocol == L3Discovery.NeighborProtocol.OSPF: cmd = "show ip ospf | i ID" ospfGeneral = Session.ExecCommand(cmd) # expecting output like this: # Routing Process "ospf 200" with ID 10.9.254.251 # Routing Process "ospf 100" with ID 192.168.1.1 # # WARNING if more than one EIGRP process is running, generate error # if len(ospfGeneral.splitlines()) == 1 : match = re.findall(r"(?<=ID )[\d.]{0,99}", ospfGeneral, re.IGNORECASE) if len(match) == 1 : self.RouterID[instanceName][str(thisProtocol)] = match[0] if globalRouterID == ConnectionInfo.DeviceIP : globalRouterID = match[0] else: raise ValueError("Parsing more than one OSPF process is not supported by parser") elif thisProtocol == L3Discovery.NeighborProtocol.EIGRP : cmd = "show ip eigrp topology | i ID" eigrpGeneral = Session.ExecCommand(cmd) # expecting output like this: # IP - EIGRP Topology Table for AS(10) / ID(10.9.240.1) # IP - EIGRP Topology Table for AS(20) / ID(10.9.240.1) # # TODO : # WARNING if more than one EIGRP process is running, generate error # if len(eigrpGeneral.splitlines()) == 1 : match = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", eigrpGeneral, re.IGNORECASE) if len(match) == 1 : self.RouterID[instanceName][str(thisProtocol)] = match[0] if globalRouterID == ConnectionInfo.DeviceIP : globalRouterID = match[0] else: raise ValueError("Parsing more than one EIGRP process is not supportedby parser") elif thisProtocol == L3Discovery.NeighborProtocol.CDP: # only for default (global) routing instance if instanceName == self.Router._defaultRoutingInstanceName : self.RouterID[instanceName][str(thisProtocol)] = self.Router.GetHostName() elif thisProtocol == L3Discovery.NeighborProtocol.RIP: # always use global router-id # TODO : this may require tuning self.RouterID[instanceName][str(thisProtocol)] = globalRouterID elif thisProtocol == L3Discovery.NeighborProtocol.STATIC: # always use global router-id self.RouterID[instanceName][str(thisProtocol)] = globalRouterID else : self.RouterID[instanceName][str(thisProtocol)] = globalRouterID
def RoutingTable(self, instance): """Returns the list of RouteTableEntry objects for requested RoutingInstance""" parsedRoutes = [] try: if instance : instanceName = instance.Name # get route table size routeTableSize = self.RouteTableSize(instance) if routeTableSize > self._maxRouteTableEntries : # query only default route if instance.IsDefaultRoutingInstance() : cmd = "show ip route 0.0.0.0" else : cmd = "show ip route vrf {0} 0.0.0.0".format(instanceName) else: # query inet.0 route table for the requested instance if instance.IsDefaultRoutingInstance() : cmd = "show ip route" else: cmd = "show ip route vrf {0}".format(instanceName) routes = Session.ExecCommand(cmd) v = self.GetVersion() if "ios-xe software" in v.lower(): thisProtocol = NeighborProtocol.UNKNOWN expectingNextHop = False prefix = "" maskLength = -1 subnettedPrefix = "" subnettedMaskLength = -1 nextHop = "" adminDistance = "" routeMetric = "" parserSuccess = False outInterface = "" for rLine in [line.strip() for line in routes.splitlines()]: if "subnetted" in rLine: # lets check if we find an ipAddress/MaskLength combination in the line m = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b\/\d{1,2}", rLine) if len(m) == 1 : prefixAndMask = m[0].split('/') if len(prefixAndMask) == 2 : subnettedPrefix = prefixAndMask[0] # proceed to next rLine continue if rLine.startswith("B") : thisProtocol = NeighborProtocol.BGP expectingNextHop = False elif rLine.startswith("O") or rLine.startswith("IA") or rLine.startswith("N1") or rLine.startswith("N2") or rLine.startswith("E1") or rLine.startswith("E2") : thisProtocol = NeighborProtocol.OSPF expectingNextHop = False elif rLine.startswith("D") or rLine.startswith("EX") : thisProtocol = NeighborProtocol.EIGRP; expectingNextHop = False; elif rLine.startswith("R") : thisProtocol = NeighborProtocol.RIP expectingNextHop = False elif rLine.startswith("L") : thisProtocol = NeighborProtocol.LOCAL expectingNextHop = False elif rLine.startswith("C") : thisProtocol = NeighborProtocol.CONNECTED expectingNextHop = False elif rLine.startswith("S") : thisProtocol = NeighborProtocol.STATIC expectingNextHop = False elif rLine.startswith("[") and expectingNextHop : pass else : thisProtocol = NeighborProtocol.UNKNOWN expectingNextHop = False # reset variables if current line is not a continuation if not expectingNextHop : prefix = "" maskLength = -1 nextHop = "" adminDistance = "" routeMetric = "" parserSuccess = False outInterface = "" if thisProtocol != NeighborProtocol.UNKNOWN : if thisProtocol == NeighborProtocol.LOCAL or thisProtocol == NeighborProtocol.CONNECTED : # we expect only one ip addresses in these lines which is the prefix m = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b\/\d{1,2}", rLine) if len(m) == 1 : s = m[0] prefixAndMask = filter(None, s.split('/')) prefix = prefixAndMask[0] maskLength = int(prefixAndMask[1]) expectingNextHop = True # this line should also contain the out interface as the last word words = filter(None, rLine.split(',')) outInterface = words[-1] expectingNextHop = False parserSuccess = True else: if not expectingNextHop: # we expect two ip addresses in these lines, first is the prefix and second is next-hop check for the prefix first m = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b\/\d{1,2}", rLine) if len(m) == 1 : s = m[0] prefixAndMask = filter(None, s.split('/')) prefix = prefixAndMask[0] maskLength = int(prefixAndMask[1]) expectingNextHop = True else: # check if we find an ip address in line and if it was a subnet of last prefix # unfortunately logic seems to be broken in cas of some IOS-XE, like below route table entry is totally crap : # 159.63.0.0 / 27 is subnetted, 2 subnets # S 159.63.248.32[1 / 0] via 212.162.30.89 # S 159.63.248.96[1 / 0] via 212.162.30.89 m = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", rLine) # Due to above issue , below check does not work and we need to trust the subnettedPrefix value anyhow # if (m.Success && IPOperations.IsIPAddressInNetwork(m.Value, subnettedPrefix, subnettedMaskLength)) if len(m) == 1: # the maskLength is still valid for this prefix prefix = m[0] maskLength = subnettedMaskLength expectingNextHop = True if expectingNextHop: # get next-hop m = re.findall(R"(?<=via )\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", rLine) if len(m) == 1 : expectingNextHop = False parserSuccess = True nextHop = m[0] # get preference m = re.findall(r"\[(.*?)\]", rLine) if len(m) == 1 : preferences = filter(None, m[0].split('/')) adminDistance = preferences[0].strip('[') routeMetric = preferences[1].strip(']') # this line should also contain the out interface words = rLine.split(',') if len(words) > 1 : outInterface = words[-1] # discard outInterface if not a real interface name, like matches date pattern m = re.findall(r"(\d{1,2}w\d{1,2}d)|(\d{1,2}d\d{1,2}h)", outInterface) if len(m) == 1: outInterface = ""; else: # only for debugging expectingNextHop = True if parserSuccess: try: rte = L3Discovery.RouteTableEntry() rte.RouterID = self.RouterID(thisProtocol, instance) rte.Prefix = prefix rte.MaskLength = maskLength rte.Protocol = str(thisProtocol) rte.AD = adminDistance rte.Metric = routeMetric rte.NextHop = nextHop rte.OutInterface = outInterface rte.Best = True # the show ip route output only lists best routes :-( rte.Tag = "" parsedRoutes.Add(rte) except Exception as Ex : msg = "CiscoIOSRouter.RoutingTable() : error processing route table : {0}".format(str(Ex)) DebugEx.WriteLine(msg) else: # Not an ios-xe thisProtocol = NeighborProtocol.UNKNOWN expectingNextHop = False prefix = "" maskLength = -1 subnettedPrefix = "" subnettedMaskLength = -1 nextHop = "" adminDistance = "" routeMetric = "" parserSuccess = False outInterface = "" for rLine in [line.strip() for line in routes.splitlines()]: words = filter(None, rLine.split(' ')) # lets check if we find an ipAddress/MaskLength combination in the line prefixFound = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b\/\d{1,2}", rLine) # or just an ipAddress addressFound = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", rLine) # if the line contains the expression "subnetted" then we will learn the subnet mask for upcoming route entries and continue the loop if "subnetted" in rLine and len(prefixFound) == 1 : addressAndMask = prefixFound[0].split('/') if len(addressAndMask) == 2: try: maskLength = int(addressAndMask[1]) except: pass # proceed to next rLine continue if len(prefixFound) == 1: addressAndMask = prefixFound[0].split('/') if len(addressAndMask) == 2: prefix = addressAndMask[0] try: maskLength = int(addressAndMask[1]) except: pass elif len(addressFound) == 1: prefix = addressFound[0] else: continue if prefix: parserSuccess = True if prefix == "0.0.0.0" : maskLength = 0 # get next-hop nexthopFound = re.findall(r"(?<=via )\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", rLine) if len(nexthopFound) == 1: nextHop = nexthopFound[0] # get preference routeDetails = re.findall(r"\[(.*?)\]", rLine) if len(routeDetails) == 1: preferences = routeDetails[0].split('/') adminDistance = preferences[0].strip('[') routeMetric = preferences[1].strip(']') # this line should also contain the out interface outInterface = words[-1] else: # no ip address in this line, proceed to next continue # here we already know a mask length and the actual routed prefix, so check the protocol if rLine.startswith("B") : thisProtocol = NeighborProtocol.BGP elif rLine.startswith("O") or rLine.startswith("IA") or rLine.startswith("N1") or rLine.startswith("N2") or rLine.startswith("E1") or rLine.startswith("E2") : thisProtocol = NeighborProtocol.OSPF elif rLine.startswith("D") or rLine.startswith("EX") : thisProtocol = NeighborProtocol.EIGRP; elif rLine.startswith("R") : thisProtocol = NeighborProtocol.RIP elif rLine.startswith("L") : thisProtocol = NeighborProtocol.LOCAL elif rLine.startswith("C") : thisProtocol = NeighborProtocol.CONNECTED elif rLine.startswith("S") : thisProtocol = NeighborProtocol.STATIC else : thisProtocol = NeighborProtocol.UNKNOWN if thisProtocol != NeighborProtocol.UNKNOWN: if parserSuccess: try : rte = RouteTableEntry() rte.RouterID = self.RouterID(thisProtocol, instance) rte.Prefix = prefix rte.MaskLength = maskLength rte.Protocol = str(thisProtocol) rte.AD = adminDistance rte.Metric = routeMetric rte.NextHop = nextHop rte.OutInterface = outInterface rte.Best = True # the show ip route output only lists best routes :-( rte.Tag = "" parsedRoutes.Add(rte) except Exception as Ex : msg = "CiscoIOSRouter.RoutingTable() : error processing route table : {0}".format(str(Ex)) DebugEx.WriteLine(msg) except Exception as Ex: msg = "CiscoIOSRouter.RoutingTable() :unexpected error while processing route table : {0}".format(str(Ex)) DebugEx.WriteLine(msg) raise Exception(msg) return parsedRoutes
def RegisterNHRP(self, neighborRegistry, instance): """Performs NHRP database registration""" # neighborRegistry :The NetworkRegistry object # instance :The Routing instance reference # # Sample input for parsing # #GigabitEthernet0/0/1 - Group 44 # State is Active # 5 state changes, last state change 4w4d # Virtual IP address is 10.81.0.1 # Active virtual MAC address is 0000.0c07.ac2c(MAC In Use) # Local virtual MAC address is 0000.0c07.ac2c(v1 default) # Hello time 1 sec, hold time 3 sec # Next hello sent in 0.256 secs # Authentication text, string "ROWVA252" # Preemption enabled, delay min 60 secs # Active router is local # Standby router is 10.81.0.3, priority 100 (expires in 3.040 sec) # Priority 105 (configured 105) # Track object 1 state Up decrement 10 # Group name is "hsrp-Gi0/0/1-44" (default) VIPAddress = "" GroupID = "" PeerAddress = "" isActive = False ri = None hsrpSummary = Session.ExecCommand("show standby") for thisLine in hsrpSummary.splitlines(): try: indentLevel = len(thisLine) - len(thisLine.lstrip(' ')) if indentLevel == 0: # interface definition is changing if GroupID and VIPAddress : neighborRegistry.RegisterNHRPPeer(self, instance, ri, L3Discovery.NHRPProtocol.HSRP, isActive, VIPAddress, GroupID, PeerAddress) VIPAddress = "" GroupID = "" PeerAddress = "" ri = None # -- words = filter(None, thisLine.split(" ")) if len(words) >= 3 : ifName = words[0] ri = self.GetInterfaceByName(ifName, instance) match = re.findall(r"(?<=Group )\d{0,99}", thisLine, re.IGNORECASE) if len(match) == 1 : GroupID = words[2] continue if ri : l = thisLine.lower().lstrip() if l.startswith("virtual ip address is") : match = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", l, re.IGNORECASE) if len(match) == 1 : VIPAddress = match[0] continue if l.startswith("active router is local") : isActive = True continue if l.startswith("standby router is") : match = re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", l, re.IGNORECASE) if len(match) == 1 : PeerAddress = match[0] continue except Exception as Ex: message = "JunOS Router Module Error : could not parse NHRP information <{0}> because : {1} ".format(thisLine, str(Ex)) DebugEx.WriteLine(message) # -- register the last one if ri and VIPAddress and GroupID : neighborRegistry.RegisterNHRPPeer(self, instance, ri, L3Discovery.NHRPProtocol.HSRP, isActive, VIPAddress, GroupID, PeerAddress)
def ParseInterfaces(self, instance): """Collects interface details for all interfaces of specified routing instance, but do not collect interface configuration """ # Get the interfaces configurations if len(self._interfaceConfigurations) == 0: self.ParseInterfaceConfigurations() # Init interface dictionary for instance instanceName = self.Router._defaultRoutingInstanceName if instance: instanceName = instance.Name if self.Interfaces.get(instanceName, None) == None: self.Interfaces[instanceName] = [] # Query the device interfaces interfaces = Session.ExecCommand("show interface summary").splitlines() # Add a dummy line at the end, required for below processing only interfaces.append("--end--") # Parse the result and fill up self.Interfaces list ri = L3Discovery.RouterInterface() lineCount = len(interfaces) currentLineIndex = 1 rep_MAC = r"(?!0000)[a-f,0-9]{4}\.[a-f,0-9]{4}\.[a-f,0-9]{4}" for line in interfaces: try: if line.lower().startswith( "interface") or currentLineIndex == lineCount: # this is either a new interface block, or the end of the interface list if ri and ri.Name: # Add actual interface if vrf name matches instanceName if not ri.VRFName and instanceName == self.Router._defaultRoutingInstanceName or ri.VRFName == instanceName: ri.Configuration = self.GetInterfaceConfiguration( ri.Name) if ri.Configuration.find("vlan ") >= 0: ri.PortMode = L3Discovery.RouterInterfacePortMode.L3Subinterface subinterfaceDefinition = next(( cline for cline in ri.Configuration.splitlines() if cline.startswith("vlan ")), "") ri.VLANS = subinterfaceDefinition.split( ' ')[-1] elif ri.Address: ri.PortMode = L3Discovery.RouterInterfacePortMode.Routed else: ri.PortMode = L3Discovery.RouterInterfacePortMode.Unknown ri.Description = next( (cline for cline in ri.Configuration.splitlines() if cline.startswith("description")), "") self.Interfaces[instanceName].Add(ri) if currentLineIndex == lineCount: break words = filter(None, line.split(' ')) interfaceName = words[1] if self.IsInterrestingInterface(interfaceName): # Create new interface ri = L3Discovery.RouterInterface() # words should look like : Interface,GigabitEthernet0/0,"outside",is,up,line,protocol,is,up ri.LogicalSystemName = "Default" ri.Name = interfaceName status = [ i.strip(',') for i in words if "up" in i.lower() or "down" in i.lower() ] ri.Status = ",".join(status) else: ri = None else: if ri: # this line belongs to an iterface information block sline = line.strip().lower() if sline.startswith("ip address"): addressAndMask = GetIPAddressAndSubnetMaskFromLine( sline) if len(addressAndMask) == 2: ri.Address = addressAndMask[0] ri.MaskLength = str( IPOperations.GetMaskLength( addressAndMask[1])) if sline.startswith("mac address"): mac = re.findall(rep_MAC, sline) if len(mac) == 1: ri.MAC = mac[0] if "member of port-channel" in sline: lagID = re.findall(r"\d+$", sline) if len(lagID) == 1: ri.AggregateID = lagID[0] # PortMode and VLANS will be processed later in a second pass except Exception as Ex: DebugEx.WriteLine( "CiscoASA.InterfaceParser.ParseInterfaces() : error parsing text {0}. Error is {1}" .format(line, str(Ex))) currentLineIndex += 1
def ActiveProtocols(self, instance): """Returns the list of NeighborProtocols running on the requested routing instance """ # no routing instances supported here instanceName = self._defaultRoutingInstanceName if instance: instanceName = instance.Name if self._runningRoutingProtocols.get(instanceName, None) == None: self._runningRoutingProtocols[instanceName] = [] if len(self._runningRoutingProtocols[instanceName]) == 0: # OSPF cmd = "show ip ospf" response = Session.ExecCommand(cmd) rep_ospfEnabled = r"^OSPF Admin Mode\.+(.*)" try: ospfStatus = GetRegexGroupMatches(rep_ospfEnabled, response, 1)[0].strip().lower() if not ("disable" in ospfStatus): self._runningRoutingProtocols[instanceName].Add( L3Discovery.NeighborProtocol.OSPF) except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.ActiveProtocols() : unexpected error parsing OSPF protocol information : {0}" .format(str(Ex))) # RIP cmd = "show ip rip" response = Session.ExecCommand(cmd) rep_ripEnabled = r"^RIP Admin Mode\.+(.*)" try: ripStatus = GetRegexGroupMatches(rep_ripEnabled, response, 1)[0].strip().lower() if not ("disable" in ripStatus): self._runningRoutingProtocols[instanceName].Add( L3Discovery.NeighborProtocol.RIP) except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.ActiveProtocols() : unexpected error parsing RIP protocol information : {0}" .format(str(Ex))) # STATIC cmd = "show ip route static" response = Session.ExecCommand(cmd) rep_ipAddress = r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" try: foundAddresses = re.findall(rep_ipAddress, response) # TODO : this may be too simple if len(foundAddresses) > 0: self._runningRoutingProtocols[instanceName].Add( L3Discovery.NeighborProtocol.STATIC) except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.ActiveProtocols() : unexpected error parsing STATIC routing information : {0}" .format(str(Ex))) # LLDP - only for default instance cmd = "show lldp config chassis admin-state" response = Session.ExecCommand(cmd) rep_lldpEnabled = r"^LLDP Config. Chassis,\s+Admin State\.+(.*)" try: lldpStatus = GetRegexGroupMatches(rep_lldpEnabled, response, 1)[0].strip().lower() if "on" in lldpStatus: self._runningRoutingProtocols[instanceName].Add( L3Discovery.NeighborProtocol.LLDP) except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.ActiveProtocols() : unexpected error parsing LLDP protocol information : {0}" .format(str(Ex))) result = self._runningRoutingProtocols[instanceName] return result
def RoutingTable(self, instance): """Returns the list of RouteTableEntry objects for requested RoutingInstance""" parsedRoutes = [] try: if instance: instanceName = instance.Name # get route table size routeTableSize = self.RouteTableSize(instance) if routeTableSize > self._maxRouteTableEntries: # query only default route cmd = "show route 0.0.0.0" else: # query inet.0 route table for the requested instance cmd = "show route" routes = Session.ExecCommand(cmd) thisProtocol = NeighborProtocol.UNKNOWN expectingNextHop = False prefix = "" maskLength = -1 subnettedPrefix = "" subnettedMaskLength = -1 nextHop = "" adminDistance = "" routeMetric = "" parserSuccess = False outInterface = "" for rLine in [line.strip() for line in routes.splitlines()]: if "subnetted" in rLine: # lets check if we find an ipAddress subnetMask combination in the line m = re.findall( r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b\/\d{1,2}", rLine) if len(m) == 1: prefixAndMask = m[0].split('/') if len(prefixAndMask) == 2: subnettedPrefix = prefixAndMask[0] # proceed to next rLine continue if rLine.startswith("B"): thisProtocol = NeighborProtocol.BGP expectingNextHop = False elif rLine.startswith("O") or rLine.startswith( "IA") or rLine.startswith("N1") or rLine.startswith( "N2") or rLine.startswith( "E1") or rLine.startswith("E2"): thisProtocol = NeighborProtocol.OSPF expectingNextHop = False elif rLine.startswith("D") or rLine.startswith("EX"): thisProtocol = NeighborProtocol.EIGRP expectingNextHop = False elif rLine.startswith("R"): thisProtocol = NeighborProtocol.RIP expectingNextHop = False elif rLine.startswith("L"): thisProtocol = NeighborProtocol.LOCAL expectingNextHop = False elif rLine.startswith("C"): thisProtocol = NeighborProtocol.CONNECTED expectingNextHop = False elif rLine.startswith("S"): thisProtocol = NeighborProtocol.STATIC expectingNextHop = False elif rLine.startswith("[") and expectingNextHop: pass else: thisProtocol = NeighborProtocol.UNKNOWN expectingNextHop = False # reset variables if current line is not a continuation if not expectingNextHop: prefix = "" maskLength = -1 nextHop = "" adminDistance = "" routeMetric = "" parserSuccess = False outInterface = "" if thisProtocol != NeighborProtocol.UNKNOWN: if thisProtocol == NeighborProtocol.LOCAL or thisProtocol == NeighborProtocol.CONNECTED: # we expect an ip addresses-subnet mask pair in these lines prefixAndMask = GetIPAddressAndSubnetMaskFromLine( rLine) if prefixAndMask: prefix = prefixAndMask[0] maskLength = IPOperations.GetMaskLength( prefixAndMask[1]) # this line should also contain the out interface as the last word words = filter(None, rLine.split(',')) asaNameif = words[-1] oif = self._interfaceParser.GetInterfaceByASANameIf( asaNameif, instance) if oif: outInterface = oif.Name else: outInterface = asaNameif expectingNextHop = False parserSuccess = True else: if not expectingNextHop: # we expect an ip addresses-subnet mask pair in these lines, and also a next-hop prefixAndMask = GetIPAddressAndSubnetMaskFromLine( rLine) if prefixAndMask: prefix = prefixAndMask[0] maskLength = IPOperations.GetMaskLength( prefixAndMask[1]) expectingNextHop = True if expectingNextHop: # get next-hop m = re.findall( R"(?<=via )\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", rLine) if len(m) == 1: expectingNextHop = False parserSuccess = True nextHop = m[0] # get preference m = re.findall(r"\[(.*?)\]", rLine) if len(m) == 1: preferences = filter(None, m[0].split('/')) adminDistance = preferences[0].strip('[') routeMetric = preferences[1].strip(']') # this line should also contain the out interface words = rLine.split(',') if len(words) > 1: asaNameif = words[-1] oif = self._interfaceParser.GetInterfaceByASANameIf( asaNameif, instance) if oif: outInterface = oif.Name else: outInterface = asaNameif else: # only for debugging expectingNextHop = True if parserSuccess: try: rte = L3Discovery.RouteTableEntry() rte.RouterID = self.RouterID(thisProtocol, instance) rte.Prefix = prefix rte.MaskLength = maskLength rte.Protocol = str(thisProtocol) rte.AD = adminDistance rte.Metric = routeMetric rte.NextHop = nextHop rte.OutInterface = outInterface rte.Best = True # the show ip route output only lists best routes :-( rte.Tag = "" parsedRoutes.Add(rte) except Exception as Ex: msg = "CiscoASA.RoutingTable() : error processing route table : {0}".format( str(Ex)) DebugEx.WriteLine(msg) except Exception as Ex: msg = "CiscoASA.RoutingTable() :unexpected error while processing route table : {0}".format( str(Ex)) DebugEx.WriteLine(msg) raise Exception(msg) return parsedRoutes
def ParseInterfaces(self, instance): """Collects interface details for all interfaces of specified routing instance, but do not collect interface configuration """ from Scriptngo.Common import IPOperations try: # First parse the VLAN database if missing if len(self._vlanIDs) == 0: self.ParseVLANDatabase() # Then collect the interfaces configurations if not yet done if len(self._interfaceConfigurations) == 0: self.ParseInterfaceConfigurations() # Init interface dictionary for current routing instance instanceName = self.Router._defaultRoutingInstanceName if instance: instanceName = instance.Name if self.Interfaces.get(instanceName, None) == None: self.Interfaces[instanceName] = [] if self.Router.SwitchType == HirshmannSwitchType.MachSwitch: # get vlan-ip data vlanRoutedInterfaces = Session.ExecCommand( "show ip vlan").splitlines() # expected output for vlanRoutedInterfaces : # Logical #VLAN ID Interface IP Address Subnet Mask MAC Address #------- ----------- --------------- --------------- ----------------- #1 9/7 10.0.40.254 255.255.255.0 EC:74:BA:50:0B:49 #2 9/1 10.0.41.254 255.255.255.0 EC:74:BA:50:0B:43 #3 9/2 10.0.39.254 255.255.255.0 EC:74:BA:50:0B:44 #4 9/3 10.0.43.254 255.255.255.0 EC:74:BA:50:0B:45 #5 9/4 10.0.38.254 255.255.255.0 EC:74:BA:50:0B:46 vlanIPHeaderLine = next( (l for l in vlanRoutedInterfaces if l.startswith("----")), None) # vlanHeaderSection will contain column start-end positions vlanIPHeaderSection = [] if vlanIPHeaderLine: matches = re.finditer(r"- -", vlanIPHeaderLine) for index, match in enumerate(matches): frompos = match.regs[0][0] topos = match.regs[0][1] #print "{0}:{1}".format(frompos, topos) if index == 0: vlanIPHeaderSection.append([0, frompos + 1]) else: vlanIPHeaderSection[index][1] = topos - 2 vlanIPHeaderSection.append([topos - 1, -1]) if len(vlanIPHeaderSection) > 0: vlanIPHeaderSection[-1][1] = len(vlanIPHeaderLine) # get all interface data responseLines = Session.ExecCommand("show port all").splitlines() # expected output responseLines : # Admin Physical Physical Link Link Cable-Cross Flow Device VLAN # Intf Type Mode Mode Status Status Trap PhysMode Fix Mode status Prio #------ ------ ------- ---------- ---------- ------ ------- ------------ ------- ------- ---- #6/1 Enable Auto 1000 Full Up Enable Unsupported Enable Ignore 0 #6/2 Enable Auto 1000 Full Up Enable Unsupported Enable Ignore 0 # interfaceLines = [ l.strip() for l in responseLines if len(re.findall(r"^\d+\/\d+\s+", l)) > 0 ] headerLine = next( (l for l in responseLines if l.startswith("----")), None) # headerSection will contain column start-end positions headerSections = [] matches = re.finditer(r"- -", headerLine) for index, match in enumerate(matches): frompos = match.regs[0][0] topos = match.regs[0][1] #print "{0}:{1}".format(frompos, topos) if index == 0: headerSections.append([0, frompos + 1]) else: headerSections[index][1] = topos - 2 headerSections.append([topos - 1, -1]) headerSections[-1][1] = len(headerLine) # -- for line in interfaceLines: try: ri = L3Discovery.RouterInterface() ri.Name = line[ headerSections[0][0]:headerSections[0][1]].strip() adminMode = line[headerSections[2][0]:headerSections[2] [1]].strip().lower() if adminMode == "enable": adminMode = "up" else: adminMode = "down" linkState = line[headerSections[5][0]:headerSections[5] [1]].strip().lower() ri.Status = "{0}/{1}".format(linkState, adminMode) ri.PortMode = L3Discovery.RouterInterfacePortMode.Access ri.Configuration = self._interfaceConfigurations.get( ri.Name, "") ri.Address = "" if "ip address" in ri.Configuration: addressline = next( (l for l in ri.Configuration.splitlines() if l.startswith("ip address")), "") if addressline: prefixAndMask = GetIPAddressAndSubnetMaskFromLine( addressline) if prefixAndMask: prefix = prefixAndMask[0] ri.Address = prefix maskLength = str( IPOperations.GetMaskLength( prefixAndMask[1])) ri.MaskLength = maskLength ri.PortMode = L3Discovery.RouterInterfacePortMode.Routed # try to get which VLAN this interface belongs to, if any for vlanLine in vlanRoutedInterfaces: vlanIntfName = vlanLine[ vlanIPHeaderSection[1][0]: vlanIPHeaderSection[1][1]].strip() if vlanIntfName == ri.Name: thisIntfVlanID = vlanLine[ vlanIPHeaderSection[0][0]: vlanIPHeaderSection[0][1]].strip() if thisIntfVlanID.isdigit(): intfVLANinfo = "" vname = self._vlanNames.get( thisIntfVlanID, "") if vname: intfVLANinfo = "{0}|{1}".format( vname, thisIntfVlanID) else: intfVLANinfo = thisIntfVlanID ri.VLANS = intfVLANinfo # process interface vlan membership if ri.PortMode != L3Discovery.RouterInterfacePortMode.Routed and ri.Configuration: try: pvid = "" rep_pvid = r"vlan pvid (\d+)" ri_pvid = re.finditer(rep_pvid, ri.Configuration, re.MULTILINE | re.IGNORECASE) for i, m in enumerate(ri_pvid): pvid = m.group(1) taggedVLANs = [] rep_taggedVLANs = r"vlan tagging (\d+)" ri_taggedVLANs = re.finditer( rep_taggedVLANs, ri.Configuration, re.MULTILINE | re.IGNORECASE) for i, m in enumerate(ri_taggedVLANs): vid = m.group(1) vname = self._vlanNames.get(vid, "") if vname: taggedVLANs.append("{0}|{1}".format( vname, vid)) else: taggedVLANs.append(vid) if len(taggedVLANs) > 0: ri.PortMode = L3Discovery.RouterInterfacePortMode.Trunk interfaceVLANInfo = ",".join(taggedVLANs) if pvid: pvidname = self._vlanNames.get(pvid, "") if pvidname: interfaceVLANInfo += ",{0}|{1}".format( pvidname, pvid) else: interfaceVLANInfo += ",{0}".format(pvid) ri.VLANS = interfaceVLANInfo.strip(',') except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.InterfaceParser.ParseInterfaces() : unexpected error procesing VLAN data for interface: {0}. Error is : {1}" .format(ri.Name, str(Ex))) self.Interfaces[instanceName].Add(ri) except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.InterfaceParser.ParseInterfaces() : unexpected error procesing interface data: {0}" .format(str(Ex))) except Exception as Ex: DebugEx.WriteLine( "HirschmannMACH.InterfaceParser.ParseInterfaces() : unexpected error : {0}" .format(str(Ex)))
def Parse(self, nRegistry, cToken, instance): """ Perform parsing logic on the given text, which should be relevant to the supported protocols and vendors""" # The neighbor registry object is received as parameter # This must be used to register a new neighbor for further discovery. # -- # A CancellationToken is also passed as parameter. The token should be checked repetitively whether cancellation was requested # by user and if yes, stop further processing. # -- # The RoutingInstance onject to work with is also passed as a parameter instanceName = L3Discovery.RoutingInstance.DefaultInstanceName( self.ParsingForVendor) if instance: instanceName = instance.Name OperationStatusLabel = "Querying LLDP neighbor data..." #-- cToken.ThrowIfCancellationRequested() # # regex search patters # Split command output to neighbor blocks. WARNING : splitting does not work with line engins \r\n, only if \r removed ! repNeighborDataBlocks = r"-+\n.*(?:(?:(?!^-+\n)[\s\S])*)" repConnectingPort = r"^Local Intf:(.*)" repRemoteChassisID = r"^Chassis id:(.*)" repRemoteSystemName = r"^System Name:(.*)" repNameOfStation = r"^System Description(.*)" repRemotePortID = r"^Port id:(.*)" repManagementAddress = r"Management Addresses:\s+ip:(.[\d.]+)" # Get data from switch lldpNeighborData = Session.ExecCommand("show lldp neighbors detail") # Must replace \r\n to simply \n lldpNeighborData = re.sub(r"\r", "", lldpNeighborData) # Parse neighbor data neighborDatablocks = re.finditer(repNeighborDataBlocks, lldpNeighborData, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(neighborDatablocks): try: thisRemoteData = match.group() localIntfName = self.GetRegexGroupMatches( repConnectingPort, thisRemoteData, 1)[0].strip() ri = self.Router.GetInterfaceByName(localIntfName, instance) if ri: remoteChassisID = self.GetRegexGroupMatches( repRemoteChassisID, thisRemoteData, 1) if remoteChassisID and remoteChassisID[0]: remoteChassisID = remoteChassisID[0].strip() else: remoteChassisID = "Unknown Chassis ID" remoteSystemName = self.GetRegexGroupMatches( repRemoteSystemName, thisRemoteData, 1) if remoteSystemName and remoteSystemName[0]: remoteSystemName = remoteSystemName[0].strip() else: remoteSystemName = self.GetRegexGroupMatches( repNameOfStation, thisRemoteData, 1) if remoteSystemName and remoteSystemName[0]: remoteSystemName = remoteSystemName[0].strip() else: remoteSystemName = "Unknown System Name" remotePortName = self.GetRegexGroupMatches( repRemotePortID, thisRemoteData, 1) remoteIntfName = "" if remotePortName and remotePortName[0]: remotePortName = remotePortName[0].strip() if remotePortName.isdigit(): remotePortName = str(int(remotePortName)) remoteIntfName = remotePortName remoteNeighboringIP = self.GetRegexGroupMatches( repManagementAddress, thisRemoteData, 1) if remoteNeighboringIP and remoteNeighboringIP[0]: remoteNeighboringIP = remoteNeighboringIP[0].strip() else: # try resolve from ARP if remote PortName is a MAC address and if that can be resolved from ARP cache isremotePortNameMAC = re.findall( r"[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}", remotePortName, re.IGNORECASE) > 0 if isremotePortNameMAC: arpEntry = Session.ExecCommand( "show arp | i {0}".format(remotePortName)) matchedIPs = re.findall( r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", arpEntry, re.IGNORECASE) if len(matchedIPs) > 0: remoteNeighboringIP = matchedIPs[0].strip() else: remoteNeighboringIP = "" if not remoteNeighboringIP: # try if remote chassi ID is MAC and if that can be resolved from ARP cache isremoteChassisIsMAC = re.findall( r"[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}", remoteChassisID, re.IGNORECASE) > 0 if isremoteChassisIsMAC: arpEntry = Session.ExecCommand( "show arp | i {0}".format(remoteChassisID)) matchedIPs = re.findall( r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", arpEntry, re.IGNORECASE) if len(matchedIPs) > 0: remoteNeighboringIP = matchedIPs[0].strip() else: remoteNeighboringIP = "" # Now we have all the data to register the neighbor nRegistry.RegisterNeighbor( self.Router, instance, L3Discovery.NeighborProtocol.LLDP, remoteChassisID, "", remoteSystemName, remoteNeighboringIP, ri, "OK", remoteIntfName) else: DebugEx.WriteLine( "CiscoIOS_LLDP.Parse() : Router object failed to provide details for interface < {0} >" .format(localIntfName), DebugLevel.Warning) except Exception as Ex: DebugEx.WriteLine( "CiscoIOS_LLDP.Parse() : Error while processing block #{0}. Error is: {1}" .format(index, str(Ex)))
def Parse(self, nRegistry, cToken, instance): """ Perform parsing logic on the given text, which should be relevant to the supported protocols and vendors""" # The neighbor registry object is received as parameter # This must be used to register a new neighbor for further discovery. # -- # A CancellationToken is also passed as parameter. The token should be checked repetitively whether cancellation was requested # by user and if yes, stop further processing. # -- # The RoutingInstance onject to work with is also passed as a parameter instanceName = L3Discovery.RoutingInstance.DefaultInstanceName( self.ParsingForVendor) if instance: instanceName = instance.Name OperationStatusLabel = "Querying LLDP neighbor data..." #-- cToken.ThrowIfCancellationRequested() # repMAC = r"[a-f0-9]{2}[:-][a-f0-9]{2}[:-][a-f0-9]{2}[:-][a-f0-9]{2}[:-][a-f0-9]{2}[:-][a-f0-9]{2}" repIPv4 = r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" if self.Router.PythonRouter._switchType == DLinkSwitchType.DGS3600: # regex search patters # Split command output to neighbor blocks. WARNING : splitting does not work with line engins \r\n, only if \r removed ! repNeighborDataBlocks = r"Port ID:.*(?:(?:(?!^Port ID:)[\s\S])*)" # Split command output to entity blocks. WARNING : splitting does not work with line engins \r\n, only if \r removed ! repEntityDataBlocks = r"Entity\s\d+.*(?:(?:(?!^Entity\s\d+)[\s\S])*)" repConnectingPort = r"^Port ID:(.*)" repRemoteChassisID = r"Chassis ID\s+:(.*)" repRemoteSystemName = r"System Name\s+:(.*)" repNameOfStation = r"^\s+Name of Station\.+\s(.*)" repRemotePortID = r"Port ID\s+:(.*)" repManagementAddress = r"Management Address\.+\s([a-f\d:.]+)" # Get data from switch lldpNeighborData = Session.ExecCommand( "show lldp neighbors interface eth1/0/1-1/0/28") # Must replace \r\n to simply \n lldpNeighborData = re.sub(r"\r", "", lldpNeighborData) # Parse neighbor data neighborDatablocks = re.finditer(repNeighborDataBlocks, lldpNeighborData, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(neighborDatablocks): try: thisRemoteData = match.group() localIntfName = self.GetRegexGroupMatches( repConnectingPort, thisRemoteData, 1)[0].strip() entityDatablocks = re.finditer( repEntityDataBlocks, thisRemoteData, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(entityDatablocks): thisEntityData = match.group() ri = self.Router.GetInterfaceByName( localIntfName, instance) if ri: remoteChassisID = self.GetRegexGroupMatches( repRemoteChassisID, thisEntityData, 1) if remoteChassisID and remoteChassisID[0]: remoteChassisID = remoteChassisID[0].strip() else: remoteChassisID = "Unknown Chassis ID" remoteSystemName = self.GetRegexGroupMatches( repRemoteSystemName, thisEntityData, 1) if remoteSystemName and remoteSystemName[0]: remoteSystemName = remoteSystemName[0].strip() else: remoteSystemName = self.GetRegexGroupMatches( repNameOfStation, thisEntityData, 1) if remoteSystemName and remoteSystemName[0]: remoteSystemName = remoteSystemName[ 0].strip() else: remoteSystemName = "Unknown System Name" remotePortName = self.GetRegexGroupMatches( repRemotePortID, thisEntityData, 1) remoteIntfName = "" if remotePortName and remotePortName[0]: remotePortName = remotePortName[0].strip() if remotePortName.isdigit(): remotePortName = str(int(remotePortName)) remoteIntfName = remotePortName remoteNeighboringIP = self.GetRegexGroupMatches( repManagementAddress, thisEntityData, 1) if remoteNeighboringIP and remoteNeighboringIP[0]: remoteNeighboringIP = remoteNeighboringIP[ 0].strip() else: remoteNeighboringIP = "" # try resolve from ARP if remote PortName is a MAC address and if that can be resolved from ARP cache isremotePortNameMAC = len( re.findall(repMAC, remotePortName, re.IGNORECASE)) > 0 if isremotePortNameMAC: arpEntry = Session.ExecCommand( "show arp | i {0}".format( remotePortName)) matchedIPs = re.findall( repIPv4, arpEntry, re.IGNORECASE) if len(matchedIPs) > 0: remoteNeighboringIP = matchedIPs[ 0].strip() if not remoteNeighboringIP: # try if remote chassi ID is MAC and if that can be resolved from ARP cache isremoteChassisIsMAC = len( re.findall(repMAC, remoteChassisID, re.IGNORECASE)) > 0 if isremoteChassisIsMAC: arpEntry = Session.ExecCommand( "show arp | i {0}".format( remoteChassisID)) matchedIPs = re.findall( repIPv4, arpEntry, re.IGNORECASE) if len(matchedIPs) > 0: remoteNeighboringIP = matchedIPs[ 0].strip() # Now we have all the data to register the neighbor nRegistry.RegisterNeighbor( self.Router, instance, L3Discovery.NeighborProtocol.LLDP, remoteChassisID, "", remoteSystemName, remoteNeighboringIP, ri, "OK", remoteIntfName) else: DebugEx.WriteLine( "DLinkSwitch_LLDP.Parse() : Router object failed to provide details for interface < {0} >" .format(localIntfName), DebugLevel.Warning) except Exception as Ex: DebugEx.WriteLine( "Error in DLinkSwitch_LLDP parser while processing block #{0}. Error is: {1}" .format(index, str(Ex))) elif self.Router.PythonRouter._switchType == DLinkSwitchType.DGS3100: # regex search patters # Split command output to neighbor blocks. WARNING : splitting does not work with line engins \r\n, only if \r removed ! repNeighborDataBlocks = r"Port ID\s+:\s\d+:\d+\n-(?:(?:(?!^Port ID\s+:\s\d+:\d+\n-)[\s\S])*)" # Split command output to entity blocks. WARNING : splitting does not work with line engins \r\n, only if \r removed ! repEntityDataBlocks = r"Entity\s\d+.*(?:(?:(?!^Entity\s\d+)[\s\S])*)" repConnectingPort = r"^Port ID\s+:\s(.*)\n--" repRemoteChassisID = r"Chassis ID\s+:(.*)" repRemotePortID = r"^Port ID\s+:\s(.*)\n[^-]" repManagementAddress = r"Management Address\.+\s([a-f\d:.]+)" # Get data from switch lldpNeighborData = Session.ExecCommand("show lldp remote_ports") # Must replace \r\n to simply \n lldpNeighborData = re.sub(r"\r", "", lldpNeighborData) # Parse neighbor data neighborDatablocks = re.finditer(repNeighborDataBlocks, lldpNeighborData, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(neighborDatablocks): try: thisRemoteData = match.group() localIntfName = self.GetRegexGroupMatches( repConnectingPort, thisRemoteData, 1)[0].strip() entityDatablocks = re.finditer( repEntityDataBlocks, thisRemoteData, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(entityDatablocks): thisEntityData = match.group() ri = self.Router.GetInterfaceByName( localIntfName, instance) if ri: remoteChassisID = self.GetRegexGroupMatches( repRemoteChassisID, thisEntityData, 1) if remoteChassisID and remoteChassisID[0]: remoteChassisID = remoteChassisID[0].strip() else: remoteChassisID = "Unknown Chassis ID" remoteSystemName = "Unknown System Name" # remoteSystemName = self.GetRegexGroupMatches(repRemoteSystemName, thisEntityData, 1) # if remoteSystemName and remoteSystemName[0] : # remoteSystemName = remoteSystemName[0].strip() # else : # remoteSystemName = self.GetRegexGroupMatches(repNameOfStation, thisEntityData, 1) # if remoteSystemName and remoteSystemName[0] : # remoteSystemName = remoteSystemName[0].strip() # else: remotePortName = self.GetRegexGroupMatches( repRemotePortID, thisEntityData, 1) remoteIntfName = "" if remotePortName and remotePortName[0]: remotePortName = remotePortName[0].strip() if remotePortName.isdigit(): remotePortName = str(int(remotePortName)) remoteIntfName = remotePortName remoteNeighboringIP = self.GetRegexGroupMatches( repManagementAddress, thisEntityData, 1) if remoteNeighboringIP and remoteNeighboringIP[0]: remoteNeighboringIP = remoteNeighboringIP[ 0].strip() else: remoteNeighboringIP = "" # try resolve from ARP if remote PortName is a MAC address and if that can be resolved from ARP cache isremotePortNameMAC = len( re.findall(repMAC, remotePortName, re.IGNORECASE)) > 0 if isremotePortNameMAC: arpEntries = Session.ExecCommand( "show arpentry") m_arpEntry = filter( lambda e: remotePortName in e, arpEntries.splitlines()) if len(m_arpEntry) > 0: arpEntry = m_arpEntry[0] else: arpEntry = "" matchedIPs = re.findall( repIPv4, arpEntry, re.IGNORECASE) if len(matchedIPs) > 0: remoteNeighboringIP = matchedIPs[ 0].strip() if not remoteNeighboringIP: # try if remote chassi ID is MAC and if that can be resolved from ARP cache isremoteChassisIsMAC = len( re.findall(repMAC, remoteChassisID, re.IGNORECASE)) > 0 if isremoteChassisIsMAC: arpEntries = Session.ExecCommand( "show arpentry") m_arpEntry = filter( lambda e: remoteChassisID in e, arpEntries.splitlines()) if len(m_arpEntry) > 0: arpEntry = m_arpEntry[0] else: arpEntry = "" matchedIPs = re.findall( repIPv4, arpEntry, re.IGNORECASE) if len(matchedIPs) > 0: remoteNeighboringIP = matchedIPs[ 0].strip() # Now we have all the data to register the neighbor nRegistry.RegisterNeighbor( self.Router, instance, L3Discovery.NeighborProtocol.LLDP, remoteChassisID, "", remoteSystemName, remoteNeighboringIP, ri, "OK", remoteIntfName) else: DebugEx.WriteLine( "DLinkSwitch_LLDP.Parse() : Router object failed to provide details for interface < {0} >" .format(localIntfName), DebugLevel.Warning) except Exception as Ex: DebugEx.WriteLine( "Error in DLinkSwitch_LLDP parser while processing block #{0}. Error is: {1}" .format(index, str(Ex))) elif self.Router.PythonRouter._switchType == DLinkSwitchType.DGS3400: # regex search patters # Split command output to neighbor blocks. WARNING : splitting does not work with line engins \r\n, only if \r removed ! repNeighborDataBlocks = r"Port ID\s+:\s+\d+\s+\n-(?:(?:(?!^Port ID\s+:\s+\d+\s+\n-)[\s\S])*)" # Split command output to entity blocks. WARNING : splitting does not work with line endings \r\n, only if \r removed ! repEntityDataBlocks = r"Entity\s\d+.*(?:(?:(?!^Entity\s\d+)[\s\S])*)" repConnectingPort = r"^Port ID\s+:\s(.*)\n--" repRemoteSystemName = r"^\s+System Name\s+:(.*)" repNameOfStation = r"^\s+System Description\.+\s(.*)" repRemoteChassisID = r"Chassis ID\s+:(.*)" repRemotePortID = r"Port ID\s+:\s(.*)\n[^-]" repManagementAddress = r"Management Address\.+\s([a-f\d:.]+)" # Get data from switch lldpNeighborData = Session.ExecCommand("show lldp remote_ports") # Must replace \r\n to simply \n # lldpNeighborData = re.sub(r"\r", "", lldpNeighborData) # Parse neighbor data neighborDatablocks = re.finditer(repNeighborDataBlocks, lldpNeighborData, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(neighborDatablocks): try: thisRemoteData = match.group() localIntfName = self.GetRegexGroupMatches( repConnectingPort, thisRemoteData, 1)[0].strip() entityDatablocks = re.finditer( repEntityDataBlocks, thisRemoteData, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(entityDatablocks): thisEntityData = match.group() ri = self.Router.GetInterfaceByName( localIntfName, instance) if ri: remoteChassisID = self.GetRegexGroupMatches( repRemoteChassisID, thisEntityData, 1) if remoteChassisID and remoteChassisID[0]: remoteChassisID = remoteChassisID[0].strip() else: remoteChassisID = "Unknown Chassis ID" remoteSystemName = "Unknown System Name" remoteSystemName = self.GetRegexGroupMatches( repRemoteSystemName, thisEntityData, 1) if remoteSystemName and remoteSystemName[0]: remoteSystemName = remoteSystemName[0].strip() else: remoteSystemName = self.GetRegexGroupMatches( repNameOfStation, thisEntityData, 1) if remoteSystemName and remoteSystemName[0]: remoteSystemName = remoteSystemName[ 0].strip() else: remoteSystemName = "Unknown System Name" remotePortName = self.GetRegexGroupMatches( repRemotePortID, thisEntityData, 1) remoteIntfName = "" if remotePortName and remotePortName[0]: remotePortName = remotePortName[0].strip() if remotePortName.isdigit(): remotePortName = str(int(remotePortName)) remoteIntfName = remotePortName remoteNeighboringIP = self.GetRegexGroupMatches( repManagementAddress, thisEntityData, 1) if remoteNeighboringIP and remoteNeighboringIP[0]: remoteNeighboringIP = remoteNeighboringIP[ 0].strip() else: remoteNeighboringIP = "" # try resolve from ARP if remote PortName is a MAC address and if that can be resolved from ARP cache isremotePortNameMAC = len( re.findall(repMAC, remotePortName, re.IGNORECASE)) > 0 if isremotePortNameMAC: arpEntries = Session.ExecCommand( "show arpentry") m_arpEntry = filter( lambda e: remotePortName in e, arpEntries.splitlines()) if len(m_arpEntry) > 0: arpEntry = m_arpEntry[0] else: arpEntry = "" matchedIPs = re.findall( repIPv4, arpEntry, re.IGNORECASE) if len(matchedIPs) > 0: remoteNeighboringIP = matchedIPs[ 0].strip() if not remoteNeighboringIP: # try if remote chassi ID is MAC and if that can be resolved from ARP cache isremoteChassisIsMAC = len( re.findall(repMAC, remoteChassisID, re.IGNORECASE)) > 0 if isremoteChassisIsMAC: arpEntries = Session.ExecCommand( "show arpentry") m_arpEntry = filter( lambda e: remoteChassisID in e, arpEntries.splitlines()) if len(m_arpEntry) > 0: arpEntry = m_arpEntry[0] else: arpEntry = "" matchedIPs = re.findall( repIPv4, arpEntry, re.IGNORECASE) if len(matchedIPs) > 0: remoteNeighboringIP = matchedIPs[ 0].strip() # Now we have all the data to register the neighbor nRegistry.RegisterNeighbor( self.Router, instance, L3Discovery.NeighborProtocol.LLDP, remoteChassisID, "", remoteSystemName, remoteNeighboringIP, ri, "OK", remoteIntfName) else: DebugEx.WriteLine( "DLinkSwitch_LLDP.Parse() : Router object failed to provide details for interface < {0} >" .format(localIntfName), DebugLevel.Warning) except Exception as Ex: DebugEx.WriteLine( "Error in DLinkSwitch_LLDP parser while processing block #{0}. Error is: {1}" .format(index, str(Ex)))
def Parse(self, nRegistry, cToken, instance): """ Perform parsing logic on the given text, which should be relevant to the supported protocols and vendors""" # The neighbor registry object is received as parameter # This must be used to register a new neighbor for further discovery. # -- # A CancellationToken is also passed as parameter. The token should be checked repetitively whether cancellation was requested # by user and if yes, stop further processing. # -- # The RoutingInstance onject to work with is also passed as a parameter instanceName = "default" if instance: instanceName = instance.Name.lower() OperationStatusLabel = "Identifying router..." #-- cToken.ThrowIfCancellationRequested() # # Compiled regex search patters repChassisType = re.compile(r"(Chassis type\s+:)(.*)", re.IGNORECASE) repChassisID = re.compile(r"(Chassis ID\s+:)(.*)", re.IGNORECASE) repSystemName = re.compile(r"(System name\s+:)(.*)", re.IGNORECASE) repLocalPortID = re.compile(r"(Local Port ID\s+:)(.*)", re.IGNORECASE) repPortID = re.compile(r"(Port ID\s+:)(.*)", re.IGNORECASE) repPortDescription = re.compile(r"(Port description\s+:)(.*)", re.IGNORECASE) repManagementAddress = re.compile(r"(Address\s+:)(.*)", re.IGNORECASE) repLLDPNeighborBlock = re.compile( r"LLDP Neighbor Information.*\s*((?:(?!^LLDP Neighbor Information)[\s\S])*)", re.IGNORECASE | re.MULTILINE) repMACAddress = re.compile( r"[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}", re.IGNORECASE) unknownSystemName = "Unknown system" unknownChassisType = "Unknown chassis type" unknownChassisID = "Unknown chassis id" # Query all LLDP neighbors lldpNeighbors = Session.ExecCommand("show lldp neighbors") # Output is like below: # Local Interface Parent Interface Chassis Id Port info System Name # ge-1/0/6 - a4:1f:72:cf:bf:04 a4:1f:72:cf:bf:04 for thisLine in [line.strip() for line in lldpNeighbors.splitlines()]: cToken.ThrowIfCancellationRequested() try: words = filter(None, thisLine.split(" ")) if len(words) >= 1: localIntfName = words[0] if self.IsInterrestingInterface(localIntfName): # Check if logical unit number is specified in localIntfName # localIntfLUN = re.findall(r"\.\d+$", localIntfName) ri = self.Router.GetInterfaceByName( localIntfName, instance) if ri != None: interfaceLUN = re.findall(r"\.\d+$", localIntfName) # Depending on JunOS version, it sometimes reports logical interfaces for LLDP peering that has no configuration # In this case wil will take the Physical interface that should have the proper port mode (inherit subinterface) set by JunOS router module if ri.PortMode == L3Discovery.RouterInterfacePortMode.Unknown and len( interfaceLUN) == 1: phIntfName = re.sub(r"\.\d+$", "", localIntfName) ri = self.Router.GetInterfaceByName( phIntfName, instance) if ri == None: # Could not find physical interface. This is an error we can't handle, let's continue to next LLDP interface DebugEx.WriteLine( "JunOS LLDP Parser error : can't find physical interface {0}" .format(phIntfName), DebugLevel.Warning) continue localIntfName = phIntfName # Neighbor registration variables remoteChassisID = "" remoteIntfName = "" remoteSystemName = "" remoteNeighboringIP = "" # Query LLDP details for this interface lldpDetails = Session.ExecCommand( "show lldp neighbors interface {0}".format( localIntfName)) # Break output to bolcks of "LLDP Neighbor Information" neighborBlocks = repLLDPNeighborBlock.findall( lldpDetails) for thisNeighborBlock in neighborBlocks: #-- Local Port ID - The SNMP index of the local interface (used to match remote) x = repLocalPortID.findall(thisNeighborBlock) localPortID = (x[0][1]).strip() ri.SNMPIndex = localPortID # Build NeighborInformationBlock niBlock = False niBlockText = [] niText = "" for detailLine in thisNeighborBlock.splitlines( ): if detailLine.lower().startswith( "neighbour information"): niBlock = True continue elif niBlock: # Empty line makrs the end of block if len(detailLine.strip()) == 0: break niBlockText.append(detailLine) if len(niBlockText) > 0: niText = "\r\n".join(niBlockText) # Search for interesting information in niText #-- SystemName - Optional field in LLDP x = repSystemName.findall(niText) if len(x) > 0: remoteSystemName = (x[0][1]).strip() else: remoteSystemName = unknownSystemName # -- ChassisID - Mandatory field in LLDP, but VMWare vSwitch does not send this, so be careful x = repChassisID.findall(niText) if len(x) > 0: remoteChassisID = (x[0][1]).strip() else: remoteChassisID = unknownChassisID #-- PortID - Mandatory field in LLDP x = repPortID.findall(niText) remoteIntfName = (x[0][1]).strip() #-- ChassisType - Optional field in LLDP x = repChassisType.findall(niText) if len(x) > 0: chassisType = (x[0][1]).strip() if remoteSystemName == unknownSystemName and chassisType.lower( ) == "mac address": # Use remoteChassisID as a unique ID if ri.Description: remoteSystemName = ri.Description else: remoteSystemName = remoteChassisID elif chassisType.lower( ) == "interface name": remoteChassisID = remoteSystemName elif chassisType.lower( ) == "network address": remoteChassisID = remoteSystemName else: chassisType = unknownChassisType # Find management address if present managementBlock = False managementBlockText = [] managementText = "" lineIndentLevel = -1 for detailLine in thisNeighborBlock.splitlines( ): if detailLine.lower().startswith( "management address"): managementBlock = True continue elif managementBlock: lineIndentLevel = len( detailLine) - len( detailLine.strip()) if lineIndentLevel > 0: managementBlockText.append( detailLine) pass if lineIndentLevel == 0: break if len(managementBlockText) > 0: managementText = "\r\n".join( managementBlockText) foundIP = repManagementAddress.findall( managementText) if len(foundIP) == 1: remoteNeighboringIP = ( foundIP[0][1]).strip() # Now we have all the data to register the neighbor nRegistry.RegisterNeighbor( self.Router, instance, L3Discovery.NeighborProtocol.LLDP, remoteChassisID, "", remoteSystemName, remoteNeighboringIP, ri, "OK", remoteIntfName) else: DebugEx.WriteLine( "Router object failed to provide details for interface < {0} >" .format(localIntfName), DebugLevel.Warning) except Exception as Ex: DebugEx.WriteLine( "Error in JunOS_LLDPParser while parsine line < {0} >. Error is: {1}" .format(thisLine, str(Ex)))
def Parse(self, nRegistry, cToken, instance): """Collects information about active tunnels and registers them with Network Discovery Engine""" # The neighbor registry object is received as parameter # This must be used to register a new neighbor for further discovery. # -- # A CancellationToken is also passed as parameter. The token should be checked repetitively whether cancellation was requested # by user and if yes, stop further processing. # -- # The RoutingInstance object to work with is also passed as a parameter instanceName = "default" if instance: instanceName = instance.Name.lower() OperationStatusLabel = "Identifying router..." #-- cToken.ThrowIfCancellationRequested() # # process legacy (not globalprotect) vpn tunnels # try: # Regex search patters rep_vpn_State = r"state:\s+(.*)" rep_vpn_localIP = r"^\s+local ip:(\s+[\.\d+]+)" rep_vpn_peerIP = r"^\s+peer ip:(\s+[\.\d+]+)" rep_Encryption = r"^\s+enc\s+algorithm:(.*)" rep_Hashing = r"^\s+auth\s+algorithm:(.*)" rep_ProxyBlock = r"(?<=proxy-id:)([\s\S]*)(?=anti replay)" rep_localProxies = r"(?:\s+local ip:)(\s+[.\d\/]+)" rep_remoteProxies = r"(?:\s+remote ip:)(\s+[.\d\/]+)" l2lTunnels = Session.ExecCommand("show vpn tunnel").splitlines() # rep_IPSecBlocks = r"IPsec:.*\s*(?:(?:(?!^IPsec:)[\s\S])*)" # the line starting with TnID is the header columnHeader = next( (line for line in l2lTunnels if line.startswith("TnID")), None) for vpnLine in l2lTunnels: tnID = GetColumnValue(vpnLine, columnHeader, "TnID", " ") if not tnID.isdigit(): continue # -- thisTunnelID = int(tnID) tunnel_Name = GetColumnValue(vpnLine, columnHeader, "Name", " ") # get detail for this connection index thisTunnelDetails = Session.ExecCommand( "show vpn flow tunnel-id {0}".format(thisTunnelID)) tunnel_StateStr = GetRegexGroupMatches(rep_vpn_State, thisTunnelDetails, 1)[0].strip().lower() tunnel_State = L3Discovery.NeighborState.Down if "active" in tunnel_StateStr: tunnel_State = L3Discovery.NeighborState.Active elif "established" in tunnel_StateStr: tunnel_State = L3Discovery.NeighborState.Established # extract local ip address from thisTunnelDetails tunnel_LocalAddress = GetRegexGroupMatches( rep_vpn_localIP, thisTunnelDetails, 1)[0].strip() # extract remote ip address from thisTunnelDetails tunnel_PeerAddress = GetRegexGroupMatches( rep_vpn_peerIP, thisTunnelDetails, 1)[0].strip() # get Cipher and Hashing algorithms cipherAlg = GetRegexGroupMatches(rep_Encryption, thisTunnelDetails, 1)[0].strip() hashAlg = GetRegexGroupMatches(rep_Hashing, thisTunnelDetails, 1)[0].strip() # get local / remote networks for each ipsec tunnel proxyBlock = GetRegexGroupMatches(rep_ProxyBlock, thisTunnelDetails, 1)[0] localProxies = GetRegexGroupMatches(rep_localProxies, proxyBlock, 1) s_localProxies = "\r\n".join([s.strip() for s in localProxies]) remoteProxies = GetRegexGroupMatches(rep_remoteProxies, proxyBlock, 1) s_remoteProxies = "\r\n".join( [s.strip() for s in remoteProxies]) # # RegisterTunnel parameters in order : #/// <param name="router">The IRouter requesting registration</param> #/// <param name="instance">The routing instance the tunnel is terminating on</param> #/// <param name="tunnelProtocol">The protocol used to establish the tunnel</param> #/// <param name="tunnelType">The link-type over the tunnel</param> #/// <param name="tunnelName">Optional : tunnel name or description</param> #/// <param name="tunnelState">The connection state</param> #/// <param name="externalLocalAddress">Tunnel external, local address</param> #/// <param name="externalRemoteAddress">Tunnel external, remote address</param> #/// <param name="tunnelSourceAddress">Optional : Tunnel internal source address</param> #/// <param name="tunnelDestinationAddress">Optional : Tunnel internal destination address</param> #/// <param name="localProxy">Optional : the local networks the tunnel is forwarding for. If not empty, must contain valid ipv4 network prefixes per line</param> #/// <param name="remoteProxy">Optional : the remote networks the tunnel is forwarding for. If not empty, must contain valid ipv4 network prefixes per line</param> #/// <param name="cipher">Optional : the cipher algorithm used by the tunnel</param> #/// <param name="hash">Optional : the hashing algorithm used by the tunnel</param> #/// <param name="tag">Optional : any data to include. Max length is 1024 characters</param> nRegistry.RegisterTunnel( self.Router, instance, L3Discovery.NeighborProtocol.IPSEC, L3Discovery.LinkType.P2P, tunnel_Name, tunnel_State, tunnel_LocalAddress, tunnel_PeerAddress, None, None, s_localProxies, s_remoteProxies, cipherAlg, hashAlg, None) except Exception as Ex: message = "PaloAlto VPN parser : error processing legacy vpn tunnel information. Error is : {0} ".format( str(Ex)) DebugEx.WriteLine(message) # # process globalprotect vpn tunnels # try: gwData = Session.ExecCommand("show global-protect-gateway gateway") isLSVPNGateway = "GlobalProtect Gateway" in gwData if isLSVPNGateway: # # Firewall acts as LSVPN Gateway # rep_gwAddress = r"(?:\s+Local Address\s+\(IPv4\)\s+:)(\s+[.\d\/]+)" rep_tunnelEnryption = r"(?:\s+Encryption\s+:)(.*)" rep_tunnelAuthentication = r"(?:\s+Authentication\s+:)(.*)" rep_tunnelSourceAddress = r"(?:\s+Tunnel Interface IP\s+:)(\s+[.\d\/]+)" rep_tunnelDestinationAddress = r"Satellite Tunnel IPs .+:([ .\d]+)" # https://stackoverflow.com/questions/52354728/regex-to-split-text-to-blocks rep_satelliteBlocks = r"Satellite\s+:.*\s*((?:(?!Satellite\s+:)[\s\S])*)" rep_satelliteHostName = r"Satellite Hostname\s+:(.*)" rep_satellitePublicIP = r"Public IP .+:([ .\d]+)" gateway_Address = GetRegexGroupMatches(rep_gwAddress, gwData, 1)[0].strip() tunnel_SourceAddress = GetRegexGroupMatches( rep_tunnelSourceAddress, gwData, 1)[0].strip() tunnel_Encryption = GetRegexGroupMatches( rep_tunnelEnryption, gwData, 1)[0].strip() tunnel_Authentication = GetRegexGroupMatches( rep_tunnelAuthentication, gwData, 1)[0].strip() # get satellite details satelliteData = Session.ExecCommand( "show global-protect-gateway current-satellite") satelliteBlocks = GetRegexGroupMatches(rep_satelliteBlocks, satelliteData, 1) for thisSatelliteBlock in satelliteBlocks: tunnel_Name = GetRegexGroupMatches(rep_satelliteHostName, thisSatelliteBlock, 1)[0].strip() tunnel_PublicAddress = GetRegexGroupMatches( rep_satellitePublicIP, thisSatelliteBlock, 1)[0].strip() tunnel_DestinationAddress = GetRegexGroupMatches( rep_tunnelDestinationAddress, thisSatelliteBlock, 1)[0].strip() # Only satellites with established tunnel status are enlisted by "show global-protect-gateway current-satellite", so no need to query tunnel status here nRegistry.RegisterTunnel( self.Router, instance, L3Discovery.NeighborProtocol.IPSEC, L3Discovery.LinkType.P2P, tunnel_Name, L3Discovery.NeighborState.Established, gateway_Address, tunnel_PublicAddress, tunnel_SourceAddress, tunnel_DestinationAddress, None, None, tunnel_Encryption, tunnel_Authentication, None) else: # # Firewall is not an LSVPN Gateway, check if a Satellite # gwData = Session.ExecCommand( "show global-protect-satellite current-gateway") isLSVPNSatellite = "GlobalProtect Satellite" in gwData if isLSVPNSatellite: # # Firewall is an LSVPN Satellite # rep_tunnelState = r"Status\s+:(.*)" rep_gwAddress = r"GlobalProtect Gateway Address\s+:(.*)" rep_tunnelDestinationAddress = r"Gateway Tunnel IP\s+:(.*)" rep_tunnelName = r"Gateway Tunnel Name\s+:(.*)" rep_tunnelEnryption = r"(?:\s+Encryption\s+:)(.*)" rep_satellitePublicIP = r"(?:\s+Local Address\s+:)(\s+[.\d\/]+)" gateway_Address = GetRegexGroupMatches( rep_gwAddress, gwData, 1)[0].strip() tunnel_StateStr = GetRegexGroupMatches( rep_tunnelState, gwData, 1)[0].strip().lower() tunnel_State = L3Discovery.NeighborState.Down if "active" in tunnel_StateStr: tunnel_State = L3Discovery.NeighborState.Active elif "established" in tunnel_StateStr: tunnel_State = L3Discovery.NeighborState.Established if tunnel_State == L3Discovery.NeighborState.Active or tunnel_State == L3Discovery.NeighborState.Established: tunnel_Encryption = GetRegexGroupMatches( rep_tunnelEnryption, gwData, 1)[0].strip() else: tunnel_Encryption = "unknown" tunnel_DestinationAddress = GetRegexGroupMatches( rep_tunnelDestinationAddress, gwData, 1)[0].strip() tunnel_Name = GetRegexGroupMatches(rep_tunnelName, gwData, 1)[0].strip() # get satellite details satelliteData = Session.ExecCommand( "show global-protect-satellite satellite") tunnel_PublicAddress = GetRegexGroupMatches( rep_satellitePublicIP, satelliteData, 1)[0].strip() tunnel_SourceAddress = "" # unknown nRegistry.RegisterTunnel( self.Router, instance, L3Discovery.NeighborProtocol.IPSEC, L3Discovery.LinkType.P2P, tunnel_Name, tunnel_State, tunnel_PublicAddress, gateway_Address, tunnel_SourceAddress, tunnel_DestinationAddress, None, None, tunnel_Encryption, "unknown", None) except Exception as Ex: message = "PaloAlto VPN parser : error processing legacy vpn tunnel information. Error is : {0} ".format( str(Ex)) DebugEx.WriteLine(message)
def Parse(self, nRegistry, cToken, instance): """ Perform parsing logic on the given text, which should be relevant to the supported protocols and vendors""" # The neighbor registry object is received as parameter # This must be used to register a new neighbor for further discovery. # -- # A CancellationToken is also passed as parameter. The token should be checked repetitively whether cancellation was requested # by user and if yes, stop further processing. # -- # The RoutingInstance onject to work with is also passed as a parameter instanceName = L3Discovery.RoutingInstance.DefaultInstanceName( self.ParsingForVendor) if instance: instanceName = instance.Name OperationStatusLabel = "Querying LLDP neighbor data..." #-- cToken.ThrowIfCancellationRequested() # # regex search patters repRemoteDataBlocks = r"Remote Data.*\s*((?:(?!^Remote Data)[\s\S])*)" repConnectingPort = r"^Remote Data,\s(\d+/\d+)" repRemoteChassisID = r"Chassis ID [^.]+\.+\s(.*)" repRemoteSystemName = r"^\s+System Name\.+\s(.*)" repNameOfStation = r"^\s+Name of Station\.+\s(.*)" # repLocalPortID : regex group 1 : port number, group2 : module number (optional)GetRegexGroupMatchesGetRegexGroupMatches repRemotePortID = r"Port ID [^)]+\)\.+\s(?:port-)?([a-f\d:]+)-?(\d+)?" # repRemotePortDescription : regex group 1 : module number, group2 : port number repRemotePortDescription = r"Port Description[\.\s]+Module:\s(\d+)\s+Port:\s(\d+)" repManagementAddress = r"Management Address\.+\s([a-f\d:.]+)" repMACAddress = re.compile( r"[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}", re.IGNORECASE) lldpNeighbors = Session.ExecCommand("show lldp neighbors") lldpRemoteData = Session.ExecCommand("show lldp remote-data") remoteDatablocks = re.finditer(repRemoteDataBlocks, lldpRemoteData, re.MULTILINE | re.IGNORECASE) for index, match in enumerate(remoteDatablocks): try: thisRemoteData = match.group() localIntfName = self.GetRegexGroupMatches( repConnectingPort, thisRemoteData, 1)[0].strip() ri = self.Router.GetInterfaceByName(localIntfName, instance) if ri: remoteChassisID = self.GetRegexGroupMatches( repRemoteChassisID, thisRemoteData, 1) if remoteChassisID and remoteChassisID[0]: remoteChassisID = remoteChassisID[0].strip() else: remoteChassisID = "Unknown Chassis ID" remoteSystemName = self.GetRegexGroupMatches( repRemoteSystemName, thisRemoteData, 1) if remoteSystemName and remoteSystemName[0]: remoteSystemName = remoteSystemName[0].strip() else: remoteSystemName = self.GetRegexGroupMatches( repNameOfStation, thisRemoteData, 1) if remoteSystemName and remoteSystemName[0]: remoteSystemName = remoteSystemName[0].strip() else: remoteSystemName = "Unknown System Name" # First try repRemotePortDescription regex remotePortName = self.GetRegexGroupMatches( repRemotePortDescription, thisRemoteData, 2) if remotePortName and remotePortName[0]: remotePortName = remotePortName[0].strip() if remotePortName.isdigit(): remotePortName = str(int(remotePortName)) remotePortModuleName = self.GetRegexGroupMatches( repRemotePortDescription, thisRemoteData, 1) if remotePortModuleName and remotePortModuleName[0]: remotePortModuleName = remotePortModuleName[ 0].strip() if remotePortModuleName.isdigit(): remotePortModuleName = str( int(remotePortModuleName)) remoteIntfName = "{0}/{1}".format( remotePortModuleName, remotePortName) else: remoteIntfName = remotePortName else: # repRemotePortDescription failed, so let's try repRemotePortID remotePortName = self.GetRegexGroupMatches( repRemotePortID, thisRemoteData, 1) if remotePortName and remotePortName[0]: remotePortName = remotePortName[0].strip() if remotePortName.isdigit(): remotePortName = str(int(remotePortName)) remotePortModuleName = self.GetRegexGroupMatches( repRemotePortID, thisRemoteData, 2) if remotePortModuleName and remotePortModuleName[0]: remotePortModuleName = remotePortModuleName[ 0].strip() if remotePortModuleName.isdigit(): remotePortModuleName = str( int(remotePortModuleName)) remoteIntfName = "{0}/{1}".format( remotePortModuleName, remotePortName) else: remoteIntfName = remotePortName remoteNeighboringIP = self.GetRegexGroupMatches( repManagementAddress, thisRemoteData, 1) if remoteNeighboringIP and remoteNeighboringIP[0]: remoteNeighboringIP = remoteNeighboringIP[0].strip() else: remoteNeighboringIP = "" # Now we have all the data to register the neighbor nRegistry.RegisterNeighbor( self.Router, instance, L3Discovery.NeighborProtocol.LLDP, remoteChassisID, "", remoteSystemName, remoteNeighboringIP, ri, "OK", remoteIntfName) else: DebugEx.WriteLine( "HirschmannSwitch_LLDP.Parse() : Router object failed to provide details for interface < {0} >" .format(localIntfName), DebugLevel.Warning) except Exception as Ex: DebugEx.WriteLine( "Error in HirschmannSwitch_LLDP parser while processing block #{0}. Error is: {1}" .format(index, str(Ex)))