wktools Version 4 - Mapper Lua API |
Table of contents:
5. Example: Lua Parser for HP ProCurve devices
1. General
With the Lua API it is possible to write custom parsers for devices not supported by wktools Mapper. wktools provides several wrapper functions to insert the parsed data into the SQLite database. This document lists all available methods and shows how to use them.
Database Layout:
2. Usage and global variables
2.1. How to start a Lua script
A script is loaded when a data file starts with "!!! UseScript scriptname". The given script file must be available in the wktools directory and must have ".lua" as file extension. scriptname itself is used without ".lua".
2.2. ParserDB
The ParserDB object is provided by wktools and represents the Sqlite database and maintains it's status. Call all functions from this object.
2.3. Get Data-File content
The data file is loaded by wktools and Lua receives the content by calling the ParserDB:getStringToParse() function:
data = ParserDB:getStringToParse()
3. Structs
The following two structs are available to save interface and crypto related data. The two main interface-insert-functions would have too many arguments, hence the structs are used to simplify the function usage.
cryptoSets: Crypto Details
struct cryptoSets { string intfName, string dev_id, string peer, string local_net, string remote_net, string vrf, string pfs_grp, string pkt_encaps, string pkt_decaps, string pkt_encrypt, string pkt_decrypt, string send_err, string rcv_err, string path_mtu, string status, string esp_i, string ah_i, string pcp_i, string esp_o, string ah_o, string pcp_o, string settings, string tag, string seqnr };
Usage:
Optional arguments may be empty strings (""), but must be set.
cSets = cryptoSets() cSets.intfName = "Intf-Name" ...
intfName | Mandatory | Interface Name (normalized) |
dev_id | Mandatory | Device ID |
peer | Mandatory | Peer IP Address |
local_net | Mandatory | Local Crypto Network |
remote_net | Mandatory | Remote Crypto Network |
vrf | Optional | VRF |
pfs_grp | Optional | PFS DH Group |
pkt_encaps | Mandatory | Number of encapsulated packets; Use "0" if not applicable. |
pkt_decaps | Mandatory | Number of decapsulated packets; Use "0" if not applicable. |
pkt_encrypt | Mandatory | Number of encrypted packets; Use "0" if not applicable. |
pkt_decrypt | Mandatory | Number of decrypted packets; Use "0" if not applicable. |
send_err | Mandatory | Number of send errors; Use "0" if not applicable. |
rcv_err | Mandatory | Number of receive errors; Use "0" if not applicable. |
path_mtu | Mandatory | Path MTU; Use "0" if not applicable. |
status | Mandatory | Status of SA |
esp_i | Optional | Inbound ESP SA |
ah_i | Optional | Inbound AH SA |
pcp_i | Optional | Inbound PCP SA |
esp_o | Optional | Outbound ESP SA |
ah_o | Optional | Outbound AH SA |
pcp_o | Optional | Outbound PCP SA |
settings | Optional | Settings |
tag | Optional | Crypto Map Tag |
seqnr | Optional | Crypto Map Sequence Number |
intfSets: Main information to define an interface
struct intfSets { string intfName, string nameif, string intfType, string phl, string macAddress, string ipAddress, string subnetMask, string duplex, string speed, string status, string description, string l2l3, string dev_id }
Usage:
Optional arguments may be empty strings (""), but must be set.
iSets = intfSets() iSets.intfName = "Intf-ID" ...
intfName | Mandatory | Interface Name (Needs Normalization -> intfNameChange() ) |
nameif | Optional | Alternate Interface name, like ASA nameif |
intfType | Mandatory | Interface Type (Needs Normalization -> intfTypeCheck() ) |
phl | Mandatory | logical or physical? (Needs Normalization -> intfPhlCheck() )
|
macAddress | Optional | Interface MAC Address |
ipAddress | Optional | Interface IP Address; Only Primary IP Address; Secondary IPs are inserted into the Subnet table |
subnetMask | Optional | Subnet Mask |
duplex | Optional | Interface Duplex Settings |
speed | Optional | Interface Speed Settings |
status | Mandatory | Interface Status (Up/Down...); !!! It is important to use "Up" for active interfaces, "Down" for inactive Interfaces and "Disabled" for shutdown interfaces (upper/lower case does not matter) !!! |
description | Optional | Description |
l2l3 | Mandatory | Layer2 (L2) or Layer3 (L3) |
dev_id | Mandatory | Device ID; The interface will be attached to the given device |
intfStats: Interface counters
struct intfStats { string errLvl, string lastClear, string loadLvl, string iCrc, string iFrame, string iOverrun, string iIgnored, string iWatchdog, string iPause, string iDribbleCondition, string ibuffer, string l2decodeDrops, string runts, string giants, string throttles, string ierrors, string underrun, string oerrors, string oCollisions, string oBabbles, string oLateColl, string oDeferred, string oLostCarrier, string oNoCarrier, string oPauseOutput, string oBufferSwapped, string resets, string obuffer, string lastInput, string intf_id }
Usage:
Optional arguments may be empty strings (""), but must be set.
iStats = intfStats() iStats.errLvl = "error-level" ...
errLvl | Mandatory | Sum of all errors; Must be "0" at least. |
lastClear | Optional | Timestamp of last "clear counters" or similar command. |
loadLvl | Mandatory | Interface Load Level; Must be "0" at least. |
iCrc | Optional | # CRC errors |
iFrame | Optional | # Frame erros |
iOverrun | Optional | # Overruns |
iIgnored | Optional | # Ignored |
iWatchdog | Optional | # Watchdog errors |
iPause | Optional | # Pause frames |
iDribbleCondition | Optional | # Dribble Condition errors |
ibuffer | Optional | # Input Buffer Drops |
l2decodeDrops | Optional | # L2 Decode Drops |
runts | Optional | # Runts |
giants | Optional | # Giants |
throttles | Optional | # Throttles |
ierrors | Optional | # Total Input errors |
underrun | Optional | # Underruns |
oerrors | Optional | # Total Output errors |
oCollisions | Optional | # Collisions |
oBabbles | Optional | # Babbles |
oLateColl | Optional | # Late Collisions |
oDeferred | Optional | # Deferred |
oLostCarrier | Optional | # Lost Carrier |
oNoCarrier | Optional | # No Carrier |
oPauseOutput | Optional | # Output Pause Frames |
oBufferSwapped | Optional | # Buffer Swaps |
resets | Optional | # Interface Resets |
obuffer | Optional | # Output Buffer Drops |
lastInput | Optional | Timestamp of last Input Packet |
intf_id | Mandatory | Interface ID; The counters will be attached to the given interface. |
4. Functions
This section lists all available wktools functions to be used by Lua.
getIntfID: Get Interface ID from Interface Name
string getIntfID( string dev_id, string interfaceName, bool err )
Usage:
iID = ParserDB:getIntfID(dev_id, port, true)
dev_id | Mandatory | Device ID |
interfaceName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
err | Mandatory | true: Print error if Interface not found; false: No error |
getIntfIDfromL3Route: Look-up Outbound Interface-ID for an Input-IP in the Routing Table
string getIntfIDfromL3Route( string ipAddress, string dev_id )
Usage:
iID = ParserDB:getIntfIDfromL3Route(ipAddress, dev_id)
ipAddress | Mandatory | IP Address for which the look-up should be done. |
dev_id | Mandatory | Device ID |
getIntfNameFromID: Get Interface Name from Interface ID
string getIntfNameFromID( string intf_id, bool error )
Usage:
iName = ParserDB:getIntfNameFromID(intf_id, false)
intf_id | Mandatory | Interface ID |
error | Mandatory | true: Print error if Interface not found; false: No error |
getIntfNamefromIP: Get Interface-Name from Interface IP address.
string getIntfNamefromIP( string ipAddress, string dev_id )
Usage:
iName = ParserDB:getIntfNamefromIP(ipAddress, dev_id)
ipAddress | Mandatory | Interface IP Address. |
dev_id | Mandatory | Device ID |
getIntfIDFromNameif: Get Interface ID from nameif
string getIntfIDFromNameif( string dev_id, string nameif, bool err )
Usage:
iID = ParserDB:getIntfID(dev_id, altName, true)
dev_id | Mandatory | Device ID |
nameif | Mandatory | Alternate Interface name or nameif for ASA firewalls |
err | Mandatory | true: Print error if Interface not found; false: No error |
getIntfNameFromNameif: Get Interface Name from nameif
string getIntfNameFromNameif( string dev_id, string nameif )
Usage:
iName = ParserDB:getIntfNameFromNameif(dev_id, altName)
dev_id | Mandatory | Device ID |
nameif | Mandatory | Alternate Interface name or nameif for ASA firewalls |
insertCDP: Add CDP or LLDP neighbors to the database
insertCDP(string hostname, string nName, string alternatenName, string intf, string nIntfIP, string nIntf, string type, string platform, string sw_version, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertCDP(localHostname, neighborHostname, alternateNeighborName, localIntf, neighborIP, neighborIntf, neighborType, neighborPlatform, neighborSW_version, dev_id)
hostname | Mandatory | Local Hostname |
nName | Mandatory | Neighbor Hostname |
alternatenName | Optional | Alternate Neighbor Hostname; May be used to differentiate between devices with the same hostname, or to save the FQDN. |
intf | Mandatory | Local Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name |
nIntfIP | Optional | Neighbor IP address |
nIntf | Mandatory | Neighbor Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name |
type | Mandatory | Neighbor Type - Use the following values to specify the neighbor device type:
|
platform | Optional | Neighbor HW Platform |
sw_version | Optional | Neighbor SW Version |
dev_id | Mandatory | Device ID |
insertCrypto: Adds a new crypto map SA to the DB
insertCrypto( cryptoSets *cSets )
Usage:
ParserDB:insertCrypto(cSets)
cSets | Mandatory | Name of the cryptoSets structure with the crypto info |
insertCryptoIntf: Add crypto information to an interface.
insertCryptoIntf( string cryptoMapTag, string cryptoLocalIP, string cryptoRemoteIP, string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertCryptoIntf(cryptoMapTag, cryptoLocalIP, cryptoRemoteIP, intfName, dev_id)
cryptoMapTag | Optional | Crypto Map Name |
cryptoLocalIP | Optional | Local Crypto Peer IP Address |
cryptoRemoteIP | Optional | Remote Crypto Peer IP Address; Only relevant for point-to-point tunnels. For Multipoint tunnels please use insertCrypto() |
intfName | Mandatory | Interface Name |
dev_id | Mandatory | Device ID |
insertCryptoMapIntf: Add a virtual Interface for each crypto Map Peer IP address.
insertCryptoMapIntf( string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertCryptoMapIntf(intfName, dev_id)
intfName | Mandatory | Interface Name |
dev_id | Mandatory | Device ID |
insertDevice: Add a new device to the database and return the Device ID, which is needed as function argument very often.
string insertDevice( string hName, string hType, string hHwtype, string hConfReg )
Usage:
Optional arguments may be empty strings (""), but must be set.
dev_id = ParserDB:insertDevice(hostname, hType, hHwtype, hConfReg)
hName | Mandatory | Hostname |
hType | Mandatory | Hardware Type - Use the following values to specify the Device Type:
|
hHwtype | Mandatory | Use the same value as for "hType"; "hType" may be changed by wktools later on, while "hHwtype" stays the same. |
hConfReg | Optional | Config Register |
insertDevTracking: Add IP Device Tracking Information.
string insertDevTracking( string macAddress, string ipAddress, string state, string vlanID, string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertDevTracking(macAddress, ipAddress, state, vlanID, intfName, dev_id)
macAddress | Mandatory | MAC Address |
ipAddress | Mandatory | IP Address |
state | Optional | State |
vlanID | Optional | VLAN ID |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name |
dev_id | Mandatory | Device ID |
insertDevTrackingDev: Add Device-related IP Device Tracking information
string insertDevTrackingDev( string devTrackingStatus, string devTrackingProbeCount, string devTrackingProbeInterval, string devTrackingProbeDelay, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertDevTrackingDev(devTrackingStatus, devTrackingProbeCount, devTrackingProbeInterval, devTrackingProbeDelay, dev_id)
devTrackingStatus | Optional | Global IP Device Tracking status |
devTrackingProbeCount | Optional | IP Device Tracking Probe Count |
devTrackingProbeInterval | Optional | IP Device Tracking Probe Interval |
devTrackingProbeDelay | Optional | IP Device Tracking Probe Delay Interval |
dev_id | Mandatory | Device ID |
insertDHCPSnooping: Add IP DHCP Snooping Information.
string insertDHCPSnooping( string macAddress, string ipAddress, string leaseTime, string vlanID, string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertDHCPSnooping(macAddress, ipAddress, leaseTime, vlanID, intfName, dev_id)
macAddress | Mandatory | MAC Address |
ipAddress | Mandatory | IP Address |
leaseTime | Optional | DHCP Lease Time |
vlanID | Optional | VLAN ID |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name |
dev_id | Mandatory | Device ID |
insertDot1xDev: Add Device-global dot1x information to the DB
insertDot1xDev( string status, string version, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertDot1xDev(status, version, dev_id)
status | Mandatory | System Auth Control Status |
version | Optional | dot1x Version |
dev_id | Mandatory | Device ID |
insertDot1xIntf: Add interface related dot1x information
insertDot1xIntf( string dot1x, string mab, string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertDot1xIntf(dot1x, mab, intfName, dev_id)
dot1x | Optional | dot1x role; If not set, mab must not be empty. |
mab | Optional | MAB status; If not set, dot1x must not be empty. |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
dev_id | Mandatory | Device ID |
insertDot1xUser: Add authentication session information to the DB
insertDot1xUser( string userMac, string method, string domain, string status, string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertDot1xUser(userMac, method, domain, status, intfName, dev_id)
userMac | Mandatory | end-client MAC address |
method | Mandatory | MAB/dot1x/... |
domain | Mandatory | Voice/Data/... |
status | Mandatory | Authentication status |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
dev_id | Mandatory | Device ID |
insertFlash: Add flash and HDD information to a device.
insertFlash( string fname, string fsize, string ffree, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertFlash(partitionName, partitionSize, free, dev_id)
fname | Mandatory | Partition Name |
fsize | Mandatory | Partition Size |
ffree | Optional | Free space |
dev_id | Mandatory | Device ID |
insertFOStatus: Add Failover status to a device.
insertFOStatus( string foStatus, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertFOStatus(foStatus, dev_id)
foStatus | Mandatory | Failover Status |
dev_id | Mandatory | Device ID |
insertHardware: Add detailed hardware information like serial number, description and part number to a device, including modules and other parts. Returns the DB ID of the added hardware. This ID is needed to attach modules to a chassis. Updates may be done with updateHardware() function
string insertHardware( string hPos, string hModell, string hDescription, string hChassisSN, string hRevision, string hMem, string hBootfile, string hVersion, string dev_id, string boxHwInfId )
Usage:
Optional arguments may be empty strings (""), but must be set.
hwId = ParserDB:insertHardware(position, modellName, description, serialNumber, hwRevision, memorySize, bootfile, version, dev_id, boxHwInfId)
hPos | Mandatory | Position: Either "box" for the chassis itself, or the module identifier, or power supply position, or... The position for a chassis must be "box" |
hModell | Mandatory | Model name or Part number |
hDescription | Optional | Description |
hChassisSN | Optional | Serial Number |
hRevision | Optional | HW Revision number |
hMem | Optional | Memory size |
hBootfile | Optional | Bootfile |
hVersion | Optional | SW Version |
dev_id | Mandatory | Device ID; The hardware will be attached to the given device. |
boxHwInfId | Mandatory | Hardware ID of the chassis; Keep empty ("") when adding the chassis itself; Use the HW ID of the chassis when adding modules, power supplies or SFPs... |
insertHSRP: Add HSRP information to DB
string insertHSRP( string intfName, string grp, string priority, string state, string active, string standby, string virtualIP, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertHSRP(intfName, grp, priority, state, active, standby, virtualIP, dev_id)
intfName | Mandatory | Interface Name |
grp | Optional | Group# |
priority | Optional | Priority |
state | Optional | State |
active | Optional | Active Node |
standby | Optional | Standby Node |
virtualIP | Mandatory | Virtual IP Address |
dev_id | Mandatory | Device ID |
insertInterface: Adds a new interface to the DB; Returns the Interface ID
string insertInterfaceStruct( intfSets *iSets )
Usage:
hwId = ParserDB:insertInterface(iSets)
iSets | Mandatory | Name of the intfSets structure with the interface info |
insertIntfN1k: Attach VM-Ware information to a virtual switchport.
insertIntfN1k( string actModule, string owner, string portProfile, string intf_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertIntfN1k(actModule, owner, portProfile, intf_id)
actModule | Mandatory | Active on Module -> Virtual Ethernet Module # where this interface is active |
owner | Optional | Owner (VM where this interface is attached to) |
portProfile | Optional | Port Profile -> VMWare Port Profile |
intf_id | Mandatory | Interface ID |
insertIntfStats: Adds interface statistics to an interface.
insertIntfStats( intfStats *iStats )
Usage:
ParserDB:insertIntfStats(iStats)
iStats | Mandatory | Name of the intfStats structure with the interface counter info |
insertLic: Add license information; Returns true when successful, otherwise false.
bool insertLic( string lName, string lStatus, string lType, string lNextBoot, string lCluster, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertLic(licName, licStat, licTape, licNextBoot, licCluster, dev_id)
lName | Mandatory | License Name |
lStatus | Optional | License Status |
lType | Optional | License Type |
lNextBoot | Optional | License upon next boot |
lCluster | Optional | Cluster License |
dev_id | Mandatory | Device ID; The license will be attached to the given device. |
insertNeighbor: Add ARP or CAM table entry to the DB. The entry is bound to the interface where the neighor is seen.
insertNeighbor( string intf_id, string maca, string ipa, string self )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertNeighbor(intf_id, macAddress, ipAddress, self)
intf_id | Mandatory | Interface ID where the neighbor is found |
maca | Mandatory | MAC Address of the neighbor; Use ParserDB:macAddChange() to normalize the MAC address format. |
ipa | Optional | IP Address of the neighbor |
self | Optional | Own IP? -> Set to "1" if the IP address is owned by the device itself, or leave empty ("") if it's some neighbors IP |
insertOspfIntf: Add OSPF interface related information.
insertOspfIntf( string area, string nwType, string cost, string processID, string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertOspfIntf(area, nwType, cost, processID, intfName, dev_id)
area | Mandatory | Area |
nwType | Optional | Network Type |
cost | Optional | Cost |
processID | Mandatory | OSPF Process ID |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
dev_id | Mandatory | Device ID |
insertOspfProcess: Add OSPF process information to DB.
insertOspfProcess( string routerID, string processID, string vrf, string spfExecutions, string spfLastRun, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertOspfProcess(routerID, processID, vrf, spfExecutions, spfLastRun, dev_id)
routerID | Mandatory | OSPF Router-ID |
processID | Mandatory | OSPF Process ID. |
vrf | Optional | vrf Name |
spfExecutions | Optional | Number of SPF executions |
spfLastRun | Optional | Time of last SPF run |
dev_id | Mandatory | Device ID |
insertPhone: Add IP phone details to an IP phone device.
insertPhone( string voiceVlan, string cm1, string cm2, string dscpSig, string dscpConf, string dscpCall, string defGW, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertPhone(voiceVlan, cm1, cm2, dscpSig, dscpConf, dscpCall, defGW, dev_id)
voiceVlan | Optional | Voice VLAN |
cm1 | Optional | CallManager 1 IP |
cm2 | Optional | CallManager 2 IP |
dscpSig | Optional | DSCP for Signalling |
dscpConf | Optional | DSCP for Config |
dscpCall | Optional | DSCP for RDP |
defGW | Optional | Default Gateway |
dev_id | Mandatory | Device ID of the IP phone to which this information should be attached to |
insertPoeDev: Add device related PoE information.
insertPoeDev( string poeStatus, string poeCurrent, string poeMax, string poeRemaining, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertPoeDev(poeStatus, poeCurrent, poeMax, poeRemaining, dev_id)
poeStatus | Mandatory | POE Status | |
poeCurrent | Optional | current PoE usage for the whole device | |
poeMax | Optional | Maximum PoE output of the device | |
poeRemaining | Mandatory | Available PoE output | |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
insertPoeIntf: Add interface related PoE information.
insertPoeIntf( string poeStatus, string poeWatt, string poeWattmax, string poeDevice, string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertPoeIntf(poeStatus, poeWatt, poeWattmax, poeDevice, intfName, dev_id)
poeStatus | Mandatory | POE Status |
poeWatt | Mandatory | current POE usage |
poeWattmax | Optional | maximum POE Output |
poeDevice | Optional | POE end device |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
insertRoute: Add IPv4 routes
insertRoute( string prot, string ip, string prefix, string nh, string intf, string type, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertRoute(protocol, ip, prefix, nextHop, intf, type, dev_id)
prot | Mandatory | Routing Protocol |
ip | Mandatory | Network Address |
prefix | Mandatory | Subnet Mask: Mask is needed in /Prefix format; If in SubnetMask format, then use ParserDB:maskToBits() function to change format |
nh | Mandatory | Next Hop |
intf | Mandatory | Interface Name: Use ParserDB:intfNameChange() to normalize the Interface name |
type | Optional | Type, for future use, Leave empty ("") |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
insertRpGlobal: Add global Routing Protocol information
insertRpGlobal( string bgpAS, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertRpNeighbor(bgpAS, dev_id)
bgpAS | Mandatory | BGP AS number |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
insertRpNeighbor: Add a Routing Protocol Neighbor
insertRpNeighbor( string rp, string neighborID, string neighborIntfIP, string uptime, string neighborState, string neighborStateChanges, string neighborAS, string intfName, string dev_id )
Usage:
Optional arguments may be empty strings (""), but must be set.
ParserDB:insertRpNeighbor(rp, neighborID, neighborIntfIP, uptime, neighborState, neighborStateChanges, neighborAS, intfName, dev_id)
rp | Mandatory | Routing Protocol |
neighborID | Mandatory | Neighbor ID |
neighborIntfIP | Mandatory | Neighbor Interface IP |
uptime | Optional | Neighbor Uptime |
neighborState | Mandatory | Neighbor State |
neighborStateChanges | Optional | # Neighbor State Changes |
neighborAS | Optional | Neighbor AS# |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
insertSnmp: Add SNMP Location to a device
insertSnmp( string snmpLoc, string dev_id )
Usage:
ParserDB:insertSnmp(snmpLoc, dev_id)
snmpLoc | Mandatory | SNMP Location |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
insertSnoopingDev: Add device-specific IP DHCP Snooping information
insertSnoopingDev( string dhcpSnoopState, string dhcpSnoopVlans, string dhcpSnoop82, string dev_id )
Usage:
ParserDB:insertSnoopingDev(dhcpSnoopState, dhcpSnoopVlans, dhcpSnoop82, dev_id)
dhcpSnoopState | Mandatory | Global DHCP Snooping Status |
dhcpSnoopVlans | Optional | DHCP Snooping VLANs |
dhcpSnoop82 | Optional | DHCP Option 82 Status |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
insertSnoopingIntf: Add IP DHCP Snooping Interface information
insertSnoopingIntf( string dhcpSnoopingTrust, string intfName, string dev_id )
Usage:
ParserDB:insertSnoopingIntf(dhcpSnoopingTrust, intfName, dev_id)
dhcpSnoopingTrust | Mandatory | DHCP Snooping Trust? |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
insertSTPInstance: Add a new STP instance; Vlans and interfaces will can be bound to this instance later; Returns the Instance ID
string insertSTPInstance(string stpPrio, string stpRootPort)
Usage:
ParserDB:insertSTPInstance(stpPrio, stpRootPort)
stpPrio | Mandatory | Local STP Priority for this instance |
stpRootPort | Mandatory | STP Root Port for this instance |
insertSTPStatus: Add the current STP status of an interface; This may be VLAN related
insertSTPStatus( string dev_id, string intfName, string stpIntfStatus, string designatedRootID, string designatedBridgeID, string stpTransitionCount, string vlanid, bool intVlan, string statsOnly )
Usage:
ParserDB:insertSTPStatus(dev_id, intfName, stpIntfStatus, designatedRootID, designatedBridgeID, stpTransitionCount, vlanid, intVlan)
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
stpIntfStatus | Mandatory | STP Port-Status |
designatedRootID | Mandatory | Root ID; Use ParserDB:macAddChange() to normalize the MAC address format. |
designatedBridgeID | Mandatory | Designated Bridge ID; Use ParserDB:macAddChange() to normalize the MAC address format. |
stpTransitionCount | Optional | STP Transition Count |
vlanid | Optional | VLAN ID, Optional if intVlan set to "false" For MST use the following Values:
|
intVlan | Mandatory | If the STP status shall be attached to an interface, VLAN or MST Instance, this option must be set to "true". |
statsOnly | Optional | Default = "0"; Is entry only for statistic purposes? 0...NO; 1...YES |
insertVlan: Add a VLAN to the DB and attach an STP instance to it; Returns the DB vlan_id
string insertVlan( string vlanNr, string dev_id, string stpInstance )
Usage:
vlan_id = ParserDB:insertVlan(vlanNr, dev_id, stpInstance)
vlanNr | Mandatory | VLAN ID |
dev_id | Mandatory | Device ID of the device to which this information should be attached to |
stpIntance | Mandatory | STP Instance ID; Leave empty if not applicable |
insertVrf: Add a vrf; Returns the DB vrf_id
string insertVrf( string vrfName, string rd, string rtI, string rtE )
Usage:
vrf_id = ParserDB:insertVrf(vrfName, rd, importTarget, exportTarget)
vrfName | Mandatory | VRF Name |
rd | Mandatory | RD |
rtI | Optional | Import Route Target |
rtE | Optional | Export Route Target |
insertVrfLink: Attach a vrf to an interface and device.
insertVrfLink( string intfName, string dev_id, string vrf_id )
Usage:
ParserDB:insertVrfLink(intfName, dev_id, vrf_id)
intfName | Mandatory | Interface Name; Use ParserDB:intfNameChange() to normalize the Interface name. |
dev_id | Mandatory | DB Device ID |
vrf_id | Optional | DB VRF ID |
intfNameChange: Interface Name Normalizer.
string intfNameChange( string intfName )
Usage:
intfName = ParserDB:intfNameChange(intfName)
intfName | Mandatory | Interface Name; It is very important to normalize the interface names to have the same name across all show output. |
intfPhlCheck: To set the Interface Type (physical or logical). This is needed for neighborship calculation to make sure that no physical interface is attached to a logical interface. The value is needed to insert an interface to the DB.
intfPhlCheck( string intfName, string intfSpeed )
Usage:
phl = ParserDB:intfPhlCheck(intfName, intfSpeed)
intfName | Mandatory | Normalized Interface Name |
intfSpeed | Mandatory | Interface Speed |
intfTypeCheck: To set the Interface Type in terms of Speed, Subinterface, Port-Channel... This is needed to make sure only interfaces with the same type (i.e. both of type GE) are connected to each other. The value is needed to insert an interface to the DB.
intfTypeCheck( string intfName, string intfSpeed )
Usage:
type = ParserDB:intfTypeCheck(intfName, intfSpeed)
intfName | Mandatory | Normalized Interface Name |
intfSpeed | Mandatory | Interface Speed |
insertSubnet: To insert IP subnets to the DB and attach it to an interface.
insertSubnet( string intfip, string intfmask, string intf_id )
Usage:
ParserDB:insertSubnet(interfaceIP, interfaceSubnetMask, intf_id)
intfip | Mandatory | IP Address |
intfmask | Mandatory | Subnet Mask in /Bit format; Use ParserDB:maskToBits() function to convert from dotted decimal to /Bit format. |
intf_id | Mandatory | Interface ID |
macAddChange: MAC address normalizer - returns the MAC address in "abcd.ef12.3456" format, which is needed for wktools to calculate neighborships.
string macAddChange( string macAddress )
Usage:
macAddress = ParserDB:macAddChange(macAddress)
macAddress | Mandatory | MAC address |
markNeighbor: To mark entries in the DB neighbor table (MAC & IP addresses of th device itself). This helps neighborship calculation.
markNeighbor( string dev_id )
Usage:
ParserDB:markNeighbor(dev_id)
dev_id | Mandatory | Device ID |
markVethMember: Add Interface ID of the associated physical interface to an Veth interface.
markVethMember( string dev_id, string boundToIntf, string intf_id )
Usage:
ParserDB:markVethMember(dev_id, boundToIntf, intf_id)
dev_id | Mandatory | Device ID |
boundToIntf | Mandatory | Interface Name of the physical Interface |
intf_id | Mandatory | Interface ID of the Veth Interface |
markVPC: Add global vPC information (or similar for Non-Cisco devices).
markVPC( string dev_id, string vpcDomId, string vpcLink, string vpcId )
Usage:
ParserDB:markVPC(dev_id, vpcDomId, vpcLink, vpcId)
dev_id | Mandatory | Device ID |
vpcDomId | Mandatory | vPC Domain ID |
vpcLink | Mandatory | vPC Peer Link - Interface Name |
vpcId | Mandatory | vPC ID of the Peer Link |
markVSL: Mark VSL interfaces.
markVSL( string intf_id )
Usage:
ParserDB:markVSL(intf_id)
intf_id | Mandatory | Interface ID of the interface to mark |
maskToBits: Convert SubnetMask from dotted decimal to /Bit format
string maskToBits( string subnetMask )
Usage:
subnetMask = ParserDB:maskToBits(subnetMask)
subnetMask | Mandatory | Subnet Mask to convert |
nextHopIntfCheck: Get Interface ID for IP address - This may be helpful when only the IP address is known, but the associated interface is missing.
string nextHopIntfCheck( string ipaddr, string dev_id )
Usage:
iID = ParserDB:nextHopIntfCheck(ipaddr, dev_id)
ipaddr | Mandatory | IP Address |
dev_id | Mandatory | Device ID |
updateChannelMember: Mark Member Interfaces with Interface ID from Port-Channel Interface
updateChannelMember( string ch_intf_id, string chMem, string dev_id )
Usage:
ParserDB:updateChannelMember(ch_intf_id, chMem, dev_id)
ch_intf_id | Mandatory | Interface ID of the Port-Channel Interface |
chMem | Mandatory | String with all Member Interfaces, separated with comma (",") or SPACE. |
dev_id | Mandatory | Device ID |
updateHardware: Updates Hardware-related information of a device/module/component to the DB. Updates only positions not empty (""). Hardware must be inserted with insertHardware() function and may be updated later with updateHardware()
updateHardware( string hModell, string hDescription, string hChassisSN, string hRevision, string hMem, string hBootfile, string hVersion, string hwinfo_id )
Usage:
ParserDB:updateHardware(hModell, hDescription, hChassisSN, hRevision, hMem, hBootfile, hVersion, hwinfo_id)
hModell | Mandatory | Model name or Part number |
hDescription | Optional | Description |
hChassisSN | Optional | Serial Number |
hRevision | Optional | HW Revision number |
hMem | Optional | Memory size |
hBootfile | Optional | Bootfile |
hVersion | Optional | SW Version |
hwInfo_id | Mandatory | HW Info ID; Returned by insertHardware() |
updateIntfL2Info: To insert switchport-related interface information to the DB.
updateIntfL2Info( string l2AdminMode, string l2Mode, string l2encap, string dtp, string nativeAccess, string voiceVlan, string opPrivVlan, string allowedVlan, string intf_id )
Usage:
ParserDB:updateIntfL2Info(l2AdminMode, l2Mode, l2encap, dtp, nativeAccess, voiceVlan, opPrivVlan, allowedVlan, intf_id)
l2AdminMode | Mandatory | L2 Admin Mode |
l2Mode | Mandatory | L2 Operational Mode |
l2encap | Mandatory | L2 Encapsulation |
dtp | Mandatory | DTP Status |
nativeAccess | Mandatory | Native and Access Vlan Id (Depends on Operational Mode) |
voiceVlan | Mandatory | Voice Vlan ID |
opPrivVlan | Mandatory | Private VLAN Status |
allowedVlan | Mandatory | Allowed VLANs (Trunk) |
intf_id | Mandatory | Interface ID |
updateSTP: Add device-specific STP information
updateSTP( string stpBridgeID, string stpProtocol, string dev_id )
Usage:
ParserDB:updateSTP(stpBridgeID, stpProtocol, dev_id)
stpBridgeID | Mandatory | STP Bridge ID (Needs Normalization -> macAddChange() |
stpProtocol | Mandatory | STP Protocol |
dev_id | Mandatory | Device ID |
updateSubInterfaces: Add Interface ID of physical interface to subinterface DB entry.
updateSubInterfaces( string intf_id, string mintf_id, string dev_id )
Usage:
ParserDB:updateSubInterfaces(intf_id, mintf_id, dev_id)
intf_id | Mandatory | SubInterface Interface ID |
mintf_id | Mandatory | Physical Interface ID |
dev_id | Mandatory | Device ID |
5. Example: Lua Parser for HP ProCurve devices
A small sample script for HP ProCurve devices will show the usage of the Lua API. The script is added to all further wktools releases. Please send changes or new scripts to wktools@spoerr.org to add them to the sample list.
Notice: The script is only used as Proof of Concept and contains little error handling and minimum testing was done!
-- HP Procurve Parser for wktools -- For reference and documentation -- !! This script contains only minimum error handling !! -- -- wktools provides the ParserDB object for all function calls. -- Print string: "ParserDB:printString(string)" -- -- !!! This script is only working when using this show command sequence exactly as it is: -- show version -- show system -- show interfaces config -- show interfaces brief -- show interfaces all -- show trunks -- show vlan -- show ip -- show arp -- show mac-address -- show spanning-tree -- show cdp neighbor detail -- show lldp info rem all -- show ip route -- show ip ospf neighbor -- show module -- show interfaces transceiver -- show flash -- show power-over-ethernet -- show power-over-ethernet brief -- -- Trim Whitespace function function trim(s) return s:gsub("^%s+", ""):gsub("%s+$", "") end -- Load String to parse; The file was already loaded by wktools data = ParserDB:getStringToParse() -- Get Positions for all interesting show commands pos01, pos010 = data:find("show version.-show system") pos02, pos020 = data:find("show system.-show interfaces config") pos03, pos030 = data:find("show interfaces config.-show interfaces brief") pos04, pos040 = data:find("show interfaces brief.-show interfaces all") pos05, pos050 = data:find("show interfaces all.-show trunks") pos06, pos060 = data:find("show trunks.-show vlan") pos07, pos070 = data:find("show vlan.-show ip") pos08, pos080 = data:find("show ip.-show arp") pos09, pos090 = data:find("show arp.-show mac%-address") pos10, pos100 = data:find("show mac%-address.-show spanning%-tree") pos11, pos110 = data:find("show spanning%-tree.-show cdp neighbor detail") pos12, pos120 = data:find("show cdp neighbor detail.-show lldp info rem all") pos13, pos130 = data:find("show lldp info rem all.-show ip route.") pos14, pos140 = data:find("show ip route.-show ip ospf neighbor") pos15, pos150 = data:find("show ip ospf neighbor.-show module") pos16, pos160 = data:find("show module.-show interfaces transceiver") pos17, pos170 = data:find("show interfaces transceiver.-show power%-over%-ethernet") pos18, pos180 = data:find("show power%-over%-ethernet.-show power%-over%-ethernet brief") pos19, pos190 = data:find("show power%-over%-ethernet brief.*") if pos01 ~= nil then pos01, pos010 = data:find("Image stamp:.*Boot Image:") end -- Position pos04 after table header of "show interfaces brief" table if pos04 ~= nil then postemp, pos04 = data:find("%- %+ %-.-\n", pos04) end -- Position pos06 after table header of "show trunks" table if pos06 ~= nil then postemp, pos06 = data:find("%- %+ %-.-\n", pos06) end -- Position pos07 after table header of "show vlan" table if pos07 ~= nil then postemp, pos07 = data:find("%- %+ %-.-\n", pos07) end -- Position pos08 after table header of "show ip" table if pos08 ~= nil then postemp, pos08 = data:find("%- %+ %-.-\n", pos08) end -- Position pos14 after table header of "show ip route" table if pos14 ~= nil then postemp, pos14 = data:find("%-%-%-.-\n", pos14) end -- Position pos09 after table header of "show arp" table if pos09 ~= nil then postemp, pos09 = data:find("%-%-%-.-\n", pos09) end -- Position pos10 after table header of "show mac-address" table if pos10 ~= nil then postemp, pos10 = data:find("%-%-%-.-\n", pos10) end -- Position pos17 after table header of "show interfaces transceiver" table if pos17 ~= nil then postemp, pos17 = data:find("%-%-%-.-\n", pos17) end -- Extract the needed show data to work with it later on ver = data:sub(pos01, pos010) -- OK sys = data:sub(pos02, pos020) -- OK icon = data:sub(pos03, pos030) -- Parser not included ibrief = data:sub(pos04, pos040) -- OK iall = data:sub(pos05, pos050) -- OK trunk = data:sub(pos06, pos060) -- OK vlan = data:sub(pos07, pos070) -- OK ip = data:sub(pos08, pos080) -- OK arp = data:sub(pos09, pos090) -- OK mac = data:sub(pos10, pos100) -- OK stp = data:sub(pos11, pos110) -- OK cdp = data:sub(pos12, pos120) -- OK - Some devices are not included due to lack of needed data lldp = data:sub(pos13, pos130) -- OK - Some devices are not included due to lack of needed data iproute = data:sub(pos14, pos140) -- OK ospf = data:sub(pos15, pos150) -- Parser not included module = data:sub(pos16, pos160) -- OK itrans = data:sub(pos17, pos170) -- OK poe = data:sub(pos18, pos180) -- OK poebrief = data:sub(pos19, pos190) -- OK -------------------------------------------------------------------------------------------------------------- -- "show version" Parser -- Image File ParserDB:printString("show version & show system\r\n") apos1, apos2 = ver:find("/%g*") bootimage = ver:sub(apos1, apos2) -- Version apos1, apos2 = ver:find("%u%.%g*") version = ver:sub(apos1, apos2) -- "show system" Parser -- Hostname apos1, apos2 = sys:find("System Name : ") apos1, apos2 = sys:find("%g*", apos2+1) hostname = sys:sub(apos1, apos2) -- SW Version apos1, apos2 = sys:find("Software revision : ") apos1, apos2 = sys:find("%g*", apos2+1) version = sys:sub(apos1, apos2) -- S/N apos1, apos2 = sys:find("Serial Number : ") apos1, apos2 = sys:find("%g*", apos2+1) sn = sys:sub(apos1, apos2) -- Base MAC apos1, apos2 = sys:find("Base MAC Addr : ") apos1, apos2 = sys:find("%g*", apos2+1) basemac = sys:sub(apos1, apos2) -- MAC Address Normalization in case format is not like aaaa.bbbb.cccc basemac = ParserDB:macAddChange(basemac) -- SNMP Location apos1, apos2 = sys:find("System Location :") apos1, apos2 = sys:find("%g*", apos2+2) location = sys:sub(apos1, apos2) -- Insert Device -- Set the following values for type and deviceType -- 1 Router -- 2 Switch -- 3 Firewall -- 4 AccessPoint -- 8 L3 Switch -- 6 VoiceGateway -- 11 Phone -- 12 End-system -- 13 ATA -- 14 Camera dev_id = ParserDB:insertDevice(hostname, "2", "2", "") ParserDB:insertSnmp(location, dev_id) -------------------------------------------------------------------------------------------------------------- function split(inputstr, sep) if sep == nil then sep = "%s" end t={} ; i=1 for str in string.gmatch(inputstr, "([^"..sep.."]+)") do t[i] = str i = i + 1 end return t end -------------------------------------------------------------------------------------------------------------- -- "show interfaces brief" && "show interfaces all " Parser -- "show interfaces config" is not needed at the moment ParserDB:printString("show interfaces brief & show interfaces all\r\n") function readIntfAll(intfName) ipos1, ipos2 = iall:find("for port " .. intfName .. ".-Utilization Tx.-\n") currentInt = iall:sub(ipos1, ipos2) -- Interface Name/Description ipos1, ipos2 = currentInt:find("Name :") ipos1, ipos2 = currentInt:find("[%g ]-", ipos2+2) intfDescription = currentInt:sub(ipos1, ipos2) -- MAC Address if available macAddress = "" ipos1, ipos2 = currentInt:find("MAC Address : ") if ipos1 ~= nil then ipos1, ipos2 = currentInt:find("%g*", ipos2+1) macAddress = currentInt:sub(ipos1, ipos2) end -- Errors ipos1, ipos2 = currentInt:find("FCS Rx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eFcs = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Alignment Rx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eAlign = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Runts Rx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eRunts = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Drops Tx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eDrops = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Collisions Tx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eColl = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Late Colln Tx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eLateColl = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Giants Rx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eGiants = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Excessive Colln : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eExcessColl = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Total Rx Errors : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eRxTotal = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Deferred Tx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eDefer = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Discard Rx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eDiscard = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Out Queue Len : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eOutQueue = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Unknown Protos : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eUnknown = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Utilization Rx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eRxUtil = currentInt:sub(ipos1, ipos2) ipos1, ipos2 = currentInt:find("Utilization Tx : ") ipos1, ipos2 = currentInt:find("[%d ]*", ipos2+1) local eTxUtil = currentInt:sub(ipos1, ipos2) return currentInt, intfDescription, macAddress, eFcs, eAlign, eRunts, eDrops, eColl, eLateColl, eGiants, eExcessColl, eRxTotal, eDefer, eDiscard, eOutQueue, eUnknown, eRxUtil, eTxUtil end for line in ibrief:gmatch(".-\n") do -- 1) Split line and save the following values: Port, Type, Enabled, Status, Mode, -- 2) Find Port in "show interfaces all" and read the following data: Name, MAC Address, Err Counter -- 3) Write Interface into DB if #line > 10 then local tble = split(line, "%s") local intfName = tble[1] local intfType, intfMode, intfEna, intfStatus, speed, duplex if tble[2] == "|" then -- Type and Mode empty intfEna = tble[4] intfStatus = tble[5] intfMode = "" speed = "" duplex = "" intfType = "" else intfEna = tble[5] intfStatus = tble[6] intfMode = tble[7] p1, p2 = intfMode:find("D") speed = intfMode:sub(0, p2-2) duplex = intfMode:sub(p2-1, #intfMode) intfType = tble[2] end iSets = intfSets() p1 = intfName:find("%-") if p1 ~= nil then intfName = intfName:sub(1, p1-1) end -- Read Details for this interface: currentInt, intfDescription, macAddress, eFcs, eAlign, eRunts, eDrops, eColl, eLateColl, eGiants, eExcessColl, eRxTotal, eDefer, eDiscard, eOutQueue, eUnknown, eRxUtil, eTxUtil = readIntfAll(intfName) -- Interface Normalizers: -- intfNameChange to shorten the Interface Name if needed/possible -- intfTypeCheck to unify the Interface operational speed/type -- intfPhlCheck to check whether the interface is a phyical or logical interface iSets.intfName = ParserDB:intfNameChange(intfName) iSets.intfType = ParserDB:intfTypeCheck(intfName, intfMode) iSets.phl = ParserDB:intfPhlCheck(intfName, intfMode) iSets.nameif = "" iSets.macAddress = ParserDB:macAddChange(macAddress) iSets.ipAddress = "" iSets.subnetMask = "" iSets.duplex = duplex iSets.speed = speed iSets.status = intfStatus iSets.description = intfDescription iSets.l2l3 = "L2" iSets.dev_id = dev_id -- Insert Interface to DB intf_id = ParserDB:insertInterface(iSets) -- Insert Interface Statistics to DB errLvl = tonumber(eFcs) + tonumber(eUnknown) + tonumber(eRunts) + tonumber(eGiants) + tonumber(eColl) + tonumber(eLateColl) + tonumber(eDefer) + tonumber(eAlign) + tonumber(eDrops) + tonumber(eExcessColl) + tonumber(eDiscard) + tonumber(eOutQueue) iLoad = tonumber(eRxUtil)*1,25 + tonumber(eTxUtil)*1,25 iStats = intfStats() iStats.errLvl = trim(tostring(errLvl)) iStats.lastClear = "" iStats.loadLvl = trim(tostring(iLoad)) iStats.iCrc = trim(eFcs) iStats.iFrame = trim(eUnknown) iStats.iOverrun = "" iStats.iIgnored = "" iStats.iWatchdog = "" iStats.iPause = "" iStats.iDribbleCondition = "" iStats.ibuffer = "" iStats.l2decodeDrops = trim(eDrops) iStats.runts = trim(eRunts) iStats.giants = trim(eGiants) iStats.throttles = "" iStats.ierrors = trim(eRxTotal) iStats.underrun = "" iStats.oerrors = "" iStats.oCollisions = trim(eColl) iStats.oBabbles = "" iStats.oLateColl = trim(eLateColl) iStats.oDeferred = trim(eDefer) iStats.oLostCarrier = "" iStats.oNoCarrier = "" iStats.oPauseOutput = "" iStats.oBufferSwapped = "" iStats.resets = "" iStats.obuffer = "" iStats.lastInput = "" iStats.intf_id = intf_id ParserDB:insertIntfStats(iStats) end end -------------------------------------------------------------------------------------------------------------- -- "show trunks" Parser ParserDB:printString("show trunks\r\n") trks = {} trunkIntfId = "" for line in trunk:gmatch(".-\n") do -- 1) Split line and save the following values: Port, Name, Group -- 2) Find intf_id's for Ports -- 3) Write Trunk Interface to DB -- 4) Mark Interfaces in DB if #line > 10 then local tble = split(line, "%s") local intfName = tble[1] local intfDescription, group if tble[4] == "|" then -- Type and Mode empty group = tble[5] intfDescription = "" else group = tble[6] intfDescription = tble[3] end if trks[group] == nil then trks[group] = true iSets = intfSets() iSets.intfName = ParserDB:intfNameChange(group) iSets.intfType = ParserDB:intfTypeCheck(group, "") iSets.phl = ParserDB:intfPhlCheck(group, "") iSets.nameif = "" iSets.macAddress = "" iSets.ipAddress = "" iSets.subnetMask = "" iSets.duplex = "" iSets.speed = "" iSets.status = "Up" iSets.description = intfDescription iSets.l2l3 = "L2" iSets.dev_id = dev_id trunkIntfId = ParserDB:insertInterface(iSets) end ParserDB:updateChannelMember(trunkIntfId, intfName, dev_id) end end -------------------------------------------------------------------------------------------------------------- -- "show vlan" && "show ip" Parser ParserDB:printString("show vlan & show ip\r\n") function readVlanDetails(vlanName) local vpos1, vpos2 = vlan:find("%d-%s-" .. vlanName .. ".-|") if vpos1 ~= nil then local vline = vlan:sub(vpos1, vpos2) local vtble = split(vline, "%s") return vtble[2], vtble[1] else return "", "" end end for line in ip:gmatch(".-\n") do -- Lookup Vlan-Nr, Vlan-Name in "show vlan" for all Lines in "show ip table" -- The connection between the two tables is the VLAN Name if #line > 10 then str3 = line:sub(3, 3) -- Ignore Lines with table headers if str3 ~= "-" then local tble = split(line, "%s") -- Secondary IP addresses are only written into the Subnet Table (DB) -- Ignore Table headers if ((tble[5] ~= "IP") and (tble[3] ~= nil)) then if tble[1] == "|" then -- Handle Secondary IP addresses l3intf_id = l3intf_id -- Interface ID is taken from last time ipa = tble[3] -- Change Subnetmask to /Bit format mask = ParserDB:maskToBits(tble[4]) -- Insert Subnet into Subnet Table (DB) ParserDB:insertSubnet(ipa, mask, l3intf_id) else -- Handle Primary IP addresses vName = tble[1] -- Delete ... at the end of the VLAN Name in "show ip" output vName = vName:gsub("%.%.%.", "") -- Add the escape character % to the special characters (-.%+*()[]^$); Otherwise they would be used as Patterns vName = vName:gsub("[%-%.%%%+%*%(%)%[%]%^%$]", "%%%0") if tble[3] == "Disabled" then ipa = "" mask = "" else ipa = tble[4] -- Change Subnetmask to /Bit format mask = ParserDB:maskToBits(tble[5]) end vlanName, vlanNr = readVlanDetails(vName) -- Fill DB Interface Table with L3 Interface Details if IP is available if ipa ~= "" then iSets = intfSets() if vlanNr ~= "" then iName = "Vlan" .. vlanNr iNameIf = vlanName iDescr = vlanName else iName = vName iNameIf = "" iDescr = "" end iSets.intfName = ParserDB:intfNameChange(iName) iSets.intfType = ParserDB:intfTypeCheck(iName, "") iSets.phl = ParserDB:intfPhlCheck(iName, "") iSets.nameif = iNameIf iSets.macAddress = "" iSets.ipAddress = ipa iSets.subnetMask = mask iSets.duplex = "" iSets.speed = "" iSets.status = "Up" iSets.description = iDescr iSets.l2l3 = "L3" iSets.dev_id = dev_id l3intf_id = ParserDB:insertInterface(iSets) -- Insert Subnet into Subnet Table (DB) ParserDB:insertSubnet(ipa, mask, l3intf_id) end -- Fill DB VLAN Table; STP Instance not available, so leave the option blank if vlanName ~= "" then ParserDB:insertVlan(vlanNr, dev_id, "") end end end end end end -------------------------------------------------------------------------------------------------------------- ParserDB:printString("show ip route\r\n") -- "show ip route" Parser for line in iproute:gmatch(".-\n") do -- Split Routing Table -- Normalize Subnetmask -- Ignore 127.0.0.x networks -- Insert into DB Routing Table if #line > 10 then local rtble = split(line, "%s/") local subnet = rtble[1] -- Mask is needed in /Prefix format; If in SubnetMask format, then use ParserDB:maskToBits function to change format local mask = rtble[2] local gateway = rtble[3] local vlan = rtble[4] local rProt local pos = vlan:find("%d") if pos == nil then rProt = rtble[4] vlan = "" else rProt = rtble[5] end -- Discard 127.0.0.x IPs pos = subnet:find("127%.0%.0%.%d-") if (pos == nil) and (rProt ~= "connected") then -- Insert Route to Routing Table; Keep type field empty, as it is optional at the moment -- Ignore Connected Routes -- If interface name is not available, then leave it empty local interface = "" if vlan ~= "" then interface = "Vlan" .. vlan end ParserDB:insertRoute(rProt, subnet, mask, gateway, interface, "", dev_id) end end end -------------------------------------------------------------------------------------------------------------- -- "show arp" Parser ParserDB:printString("show arp\r\n") for line in arp:gmatch(".-\n") do -- Lookup Vlan-Nr, Vlan-Name in "show vlan" for all Lines in "show ip table" -- The connection between the two tables is the VLAN Name if #line > 10 then local atble = split(line, "%s") local ipAddress = atble[1] local macAddress = ParserDB:macAddChange(atble[2]) local port = atble[4] -- Problem: HP uses the physical switchport (L2) in the ARP table; But it should be the logical port (L3) instead; -- -> Port ID must be read from Subnet Table local i_id = ParserDB:nextHopIntfCheck(ipAddress, dev_id) -- Insert ARP entry to neighbor table (DB) ParserDB:insertNeighbor(i_id, macAddress, ipAddress, "") end end -------------------------------------------------------------------------------------------------------------- -- "show mac-address" Parser ParserDB:printString("show mac-address\r\n") for line in mac:gmatch(".-\n") do -- Split entries, normalize MAC Address and insert into DB neighbor Table if #line > 10 then local mtble = split(line, "%s") local macAddress = ParserDB:macAddChange(mtble[1]) -- Don't forget to always use intfNameChange to normalize the Interface Names local port = ParserDB:intfNameChange(mtble[2]) local vlan = mtble[3] -- First the Interface ID is needed iID = ParserDB:getIntfID(dev_id, port, true) -- Then the MAC address can be written into DB; Leave IP Address and Self empty when only adding CAM entries ParserDB:insertNeighbor(iID, macAddress, "", "") end end -------------------------------------------------------------------------------------------------------------- -- "show spanning-tree" Parser -- 1) Global STP infos -- STP Protocol ParserDB:printString("show spanning-tree\r\n") apos1, apos2 = stp:find("%(.-%)") stpProtocol = stp:sub(apos1+1, apos2-1) apos1, apos2 = stp:find("Force Version :") apos1, apos2 = stp:find("%g*", apos2+2) stpProtocol = stpProtocol .. "/" .. stp:sub(apos1, apos2) -- Switch MAC Address apos1, apos2 = stp:find("Switch MAC Address : ") apos1, apos2 = stp:find("%g*", apos2+1) switchSTPMac = stp:sub(apos1, apos2) switchSTPMac = ParserDB:macAddChange(switchSTPMac) -- Insert Switch MAC and STP Protocol to device table ParserDB:updateSTP(switchSTPMac, stpProtocol, dev_id) -- Switch Priority apos1, apos2 = stp:find("Switch Priority%s*: ") apos1, apos2 = stp:find("%g*", apos2+1) switchSTPPrio = stp:sub(apos1, apos2) -- Root MAC Address (for MST only CST Root) apos1, apos2 = stp:find("Root MAC Address : ") apos1, apos2 = stp:find("%g*", apos2+1) rootMac = stp:sub(apos1, apos2) -- Normalize MAC address rootMac = ParserDB:macAddChange(rootMac) -- Root Priority (for MST only CST Root) apos1, apos2 = stp:find("Root Priority%s*: ") apos1, apos2 = stp:find("%g*", apos2+1) rootPrio = stp:sub(apos1, apos2) -- Root Port (for MST only CST Root) apos1, apos2 = stp:find("Root Port%s*: ") apos1, apos2 = stp:find("[%g ]*", apos2+1) rootPort = stp:sub(apos1, apos2) if rootPort == "This switch is root" then rootPort = "" else -- Normalize Interface Name rootPort = ParserDB:intfNameChange(rootPort) end -- Insert STP Instance stpInstance = ParserDB:insertSTPInstance(switchSTPPrio, rootPort) -- Insert Dummy VLAN 9999; This VLAN marks the CST ParserDB:insertVlan("9999", dev_id, stpInstance) -- 2) Interface related STP infos tpos, apos1 = stp:find("%- %+ %-.-\n", apos1) stpIntf = stp:sub(apos1, #stp) for line in stpIntf:gmatch(".-\n") do -- Split entries, normalize MAC Address and insert into DB stp_status Table if #line > 10 then local stble = split(line, "%s|") -- Only insert STP Status for Non-Edge Ports if ((stble[6] ~= nil) and (stble[9] == "No")) then -- OK local port = stble[1] port = ParserDB:intfNameChange(port) local stpStatus = stble[5] local designatedBridge = stble[6] designatedBridge = ParserDB:macAddChange(designatedBridge) -- It is very important to set STP Transition Count to "0" instead to "" ParserDB:insertSTPStatus(dev_id, port, stpStatus, designatedBridge, designatedBridge, "0", "9999", true) end end end -------------------------------------------------------------------------------------------------------------- -- "show module" Parser -- 1) Chassis Info ParserDB:printString("show module\r\n") apos1, apos2 = module:find("Status and Counters %- Module Information.-Slot Module Description") chassis = module:sub(apos1, apos2) apos1, apos2 = chassis:find("Chassis: ") apos1, apos2 = chassis:find("%g*%s%g*", apos2+1) if apos1 ~= nil then chassisType = chassis:sub(apos1, apos2) apos1, apos2 = chassis:find("Serial Number:%s*") apos1, apos2 = chassis:find("%g*", apos2+1) chassisSN = chassis:sub(apos1, apos2) position = "box" -- Insert Chassis information and save id; Important: Always use "box" for Chassis position because of wktools internal special handling chassis_id = ParserDB:insertHardware(position, chassisType, "", chassisSN, "", "", bootimage, version, dev_id, "") end apos1, apos2 = chassis:find("Management Module: ") if apos1 ~= nil then moduleDescr = "Management Module" apos1, apos2 = chassis:find("%g*", apos2+1) moduleType = chassis:sub(apos1, apos2) apos1, apos2 = chassis:find("Serial Number:%s*", apos2) apos1, apos2 = chassis:find("%g*", apos2+1) moduleSN = chassis:sub(apos1, apos2) position = "MM" -- Attach modules to the chassis by passing the DB id of the cahssis... ParserDB:insertHardware(position, moduleType, moduleDescr, moduleSN, "", "", "", "", dev_id, chassis_id) end -- 2) Module Info apos1, apos2 = module:find("%-%-%-%-.-show interfaces transceiver") ptemp, apos1 = module:find(".-\n", apos1) modules = module:sub(apos1, apos2) for line in modules:gmatch(".-\n") do -- Split entries, if #line > 77 then position = trim(line:sub(1, 7)) moduleType = trim(line:sub(8, 16)) if moduleType:find("ProCurve") ~= nil then moduleType = trim(line:sub(8, 23)) moduleDescr = trim(line:sub(24, 46)) else moduleDescr = trim(line:sub(17, 46)) end moduleSN = trim(line:sub(47, 61)) hwVersion = trim(line:sub(77, #line)) -- Attach modules to the chassis by passing the DB id of the cahssis... ParserDB:insertHardware(position, moduleType, moduleDescr, moduleSN, hwVersion, "", "", "", dev_id, chassis_id) end end -------------------------------------------------------------------------------------------------------------- -- "show interfaces transceiver" Parser ParserDB:printString("show interfaces transceiver\r\n") for line in itrans:gmatch(".-\n") do -- Split entries and insert into HW Table if #line > 10 then local ittble = split(line, "%s|") if ittble[5] ~= nil then position = ittble[1] moduleType = ittble[3] moduleDescr = ittble[2] .. "; Part#: " .. ittble[5] moduleSN = ittble[4] hwVersion = "" ParserDB:insertHardware(position, moduleType, moduleDescr, moduleSN, hwVersion, "", "", "", dev_id, chassis_id) end end end -------------------------------------------------------------------------------------------------------------- -- "show cdp neighbor detail" Parser ParserDB:printString("show cdp neighbor detail\r\n") apos1 = 0 apos2 = 0 while true do apos1, apos2 = cdp:find("Local Port .-Version :.-\n", apos2) if apos1 == nil then break end cdpNeighbor = cdp:sub(apos1, apos2) local cpos1, cpos2 = cdpNeighbor:find("Device ID : ") cpos1, cpos2 = cdpNeighbor:find("[%g ]*", cpos2+1) deviceID = cdpNeighbor:sub(cpos1, cpos2) -- Skip HP Procurve Devices since CDP information is not sufficient; These devices will be discovered with "show lldp..." tpos1 = deviceID:find("%g%g %g%g %g%g %g%g %g%g %g%g") if tpos1 == nil then cpos1, cpos2 = cdpNeighbor:find("Port : ") cpos1, cpos2 = cdpNeighbor:find("%g*", cpos2+1) localPort = cdpNeighbor:sub(cpos1, cpos2) localPort = ParserDB:intfNameChange(localPort) cpos1, cpos2 = cdpNeighbor:find("Address : ") cpos1, cpos2 = cdpNeighbor:find("[%g]*", cpos2+1) ipAddress = cdpNeighbor:sub(cpos1, cpos2) cpos1, cpos2 = cdpNeighbor:find("Platform : ") cpos1, cpos2 = cdpNeighbor:find("[%g ]*", cpos2+1) platform = cdpNeighbor:sub(cpos1, cpos2) cpos1, cpos2 = cdpNeighbor:find("Capability : ") cpos1, cpos2 = cdpNeighbor:find("[%g ]*", cpos2+1) capability = cdpNeighbor:sub(cpos1, cpos2) -- Set the following values for type and deviceType -- 1 Router -- 2 Switch -- 3 Firewall -- 4 AccessPoint -- 8 L3 Switch -- 6 VoiceGateway -- 11 Phone -- 12 End-system -- 13 ATA -- 14 Camera -- 99 Unknown if capability == "Switch" then nType = "2" elseif capability == "Router Switch" then nType = "8" else nType = "99" end cpos1, cpos2 = cdpNeighbor:find("Device Port : ") cpos1, cpos2 = cdpNeighbor:find("[%g ]*", cpos2+1) remotePort = cdpNeighbor:sub(cpos1, cpos2) remotePort = ParserDB:intfNameChange(remotePort) cpos1, cpos2 = cdpNeighbor:find("Version : ") cpos1, cpos2 = cdpNeighbor:find("[%g ]*", cpos2+1) version = cdpNeighbor:sub(cpos1, cpos2) -- Add neighbor to CDP table ParserDB:insertCDP(hostname, deviceID, deviceID, localPort, ipAddress,remotePort, nType, platform, version, dev_id) end end -------------------------------------------------------------------------------------------------------------- -- "show lldp..." Parser ParserDB:printString("show lldp...\r\n") apos1 = 0 apos2 = 0 while true do apos3 = apos2 apos1, apos2 = lldp:find("Local Port.-%-%-%-%-", apos2) if apos1 == nil then apos1, apos2 = lldp:find("Local Port", apos3) if apos1 == nil then break else apos2 = #lldp end end lldpNeighbor = lldp:sub(apos1, apos2) local cpos1, cpos2 = lldpNeighbor:find("SysName : ") if cpos1 ~= nil then cpos1, cpos2 = lldpNeighbor:find("[%g ]*", cpos2+1) deviceID = lldpNeighbor:sub(cpos1, cpos2) else deviceID = "" end cpos1, cpos2 = lldpNeighbor:find("ChassisId : ") cpos1, cpos2 = lldpNeighbor:find("[%g ]*", cpos2+1) chassisID = lldpNeighbor:sub(cpos1, cpos2) if deviceID == "" then deviceID = chassisID alternateDeviceID = deviceID else -- Concatenate deviceID and chassisID -- This is for switches with Default Hostname to keep them apart alternateDeviceID = deviceID .. "." .. chassisID:gsub(" ", "") end tpos1 = deviceID:find("%g%g %g%g %g%g %g%g %g%g %g%g") if tpos1 == nil then cpos1, cpos2 = lldpNeighbor:find("Local Port : ") cpos1, cpos2 = lldpNeighbor:find("%g*", cpos2+1) localPort = lldpNeighbor:sub(cpos1, cpos2) localPort = ParserDB:intfNameChange(localPort) cpos1, cpos2 = lldpNeighbor:find("Address : ") cpos1, cpos2 = lldpNeighbor:find("[%g]*", cpos2+1) ipAddress = lldpNeighbor:sub(cpos1, cpos2) cpos1, cpos2 = lldpNeighbor:find("System Descr : ") cpos1, cpos2 = lldpNeighbor:find("[%g ]*", cpos2+1) platform = lldpNeighbor:sub(cpos1, cpos2) cpos1, cpos2 = lldpNeighbor:find("System Capabilities Enabled : ") if cpos1 ~= nil then cpos1, cpos2 = lldpNeighbor:find("[%g ]*", cpos2+1) capability = lldpNeighbor:sub(cpos1, cpos2) else capability = "" end -- Set the following values for type and deviceType -- 1 Router -- 2 Switch -- 3 Firewall -- 4 AccessPoint -- 8 L3 Switch -- 6 VoiceGateway -- 11 Phone -- 12 End-system -- 13 ATA -- 14 Camera -- 99 Unknown if capability == "bridge" then nType = "2" elseif capability == "bridge, router" then nType = "8" else nType = "12" end cpos1, cpos2 = lldpNeighbor:find("PortId : ") cpos1, cpos2 = lldpNeighbor:find("[%g ]*", cpos2+1) remotePort = lldpNeighbor:sub(cpos1, cpos2) remotePort = ParserDB:intfNameChange(remotePort) version = "" -- Add neighbor to CDP table ParserDB:insertCDP(hostname, deviceID, alternateDeviceID, localPort, ipAddress,remotePort, nType, platform, version, dev_id) end end -------------------------------------------------------------------------------------------------------------- -- "show power-over-ethernet" Parser ParserDB:printString("show power-over-ethernet\r\n") apos1, apos2 = poe:find("Total Available Power :") if apos1 ~= nil then -- Total PoE apos1, apos2 = poe:find("[%g ]*", apos2+1) poeTotal = trim(poe:sub(apos1, apos2)) -- Used PoE apos1, apos2 = poe:find("Total used Power :") apos1, apos2 = poe:find("[%g ]*", apos2+1) poeUsed = trim(poe:sub(apos1, apos2)) -- Remaining PoE apos1, apos2 = poe:find("Total Remaining Power :") apos1, apos2 = poe:find("[%g ]*", apos2+1) poeRemain = trim(poe:sub(apos1, apos2)) ParserDB:insertPoeDev("ON", poeUsed, poeTotal, poeRemain, dev_id) end -------------------------------------------------------------------------------------------------------------- -- "show power-over-ethernet" Parser ParserDB:printString("show power-over-ethernet brief\r\n") for line in poebrief:gmatch(".-\n") do -- Split entries and insert into Intf Table if #line > 10 then local potble = split(line, "%s") if potble[11] ~= nil then port = potble[1] poeCurrent = potble[8] poeMax = potble[6] poeStat = potble[3] ParserDB:insertPoeIntf(poeStat, poeCurrent, poeMax, "", port, dev_id) end end end -------------------------------------------------------------------------------------------------------------- -- Global -- ParserDB:markNeighbor(dev_id)
wktools Version 4 Documentation |