Commandline Tool for exporting Cisco hardware inventory via SNMP

This tool exports every hardware asset from an Cisco device with a serial number. You can export the list as table or CSV.

Download: https://gist.github.com/lanbugs/4dbed5e0e8a7d5b6d29c4ea9b9e93bb2

>python cisco_inventory.py -h
usage: cisco_inventory.py [-h] -H HOST -v SNMP_VERSION [-C SNMP_COMMUNITY]
                          [-u SNMP_USER] [-A SNMP_AUTH] [-a SNMP_AUTH_METHOD]
                          [-X SNMP_PRIVACY] [-x SNMP_PRIVACY_METHOD]
                          [-L SNMP_SECURITY] [--csv]

Cisco inventory grabber Version 0.1 Written by Maximilian Thoma 2018

optional arguments:
  -h, --help            show this help message and exit
  -H HOST               WLC IP address
  -v SNMP_VERSION       SNMP version, valid are 2 or 3
  -C SNMP_COMMUNITY     SNMP Community (only v2)
  -u SNMP_USER          SNMP user (v3)
  -A SNMP_AUTH          SNMP auth password (v3)
  -a SNMP_AUTH_METHOD   SNMP auth method, valid are MD5 or SHA (v3)
  -X SNMP_PRIVACY       SNMP privacy password (v3)
  -x SNMP_PRIVACY_METHOD
                        SNMP privacy method, valid are AES or DES (v3)
  -L SNMP_SECURITY      SNMP security level, valid are no_auth_or_privacy,
                        auth_without_privacy or auth_with_privacy (v3)
  --csv                 Result should be CSV

Demo;

>python cisco_inventory.py -H 10.10.10.33 -v 3 -u snmpuser -A snmpauth -a MD5 -X snmpencr -x DES -L auth_with_privacy
| Description                                            | Class       | Name                                   | HWRev   | FWRev       | SWRev      | Serial           | Manufactor          | Model          | FRU?   |
|--------------------------------------------------------+-------------+----------------------------------------+---------+-------------+------------+------------------+---------------------+----------------+--------|
| 1000BaseSX                                             | -           | GigabitEthernet1/4/12                  | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseSX                                             | -           | GigabitEthernet1/4/11                  | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseSX                                             | -           | GigabitEthernet1/4/10                  | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseSX                                             | -           | GigabitEthernet1/4/11                  | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseSX                                             | -           | GigabitEthernet1/3/8                   | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseSX                                             | -           | GigabitEthernet1/3/9                   | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseSX                                             | -           | GigabitEthernet1/3/6                   | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseSX                                             | -           | GigabitEthernet1/3/7                   | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseSX                                             | -           | GigabitEthernet2/3/10                  | V01     |             |            | FNS11111111      | CISCO               | GLC-SX-MMD     | true   |
| 1000BaseX (SFP) with 12 SFP Ports Jumbo Frame Support  | module      | Switch1 Linecard 4 (virtual slot 4)    | V02     |             |            | FNS11111111      | Cisco               | WS-X4612-SFP-E | true   |
| 1000BaseX (SFP) with 12 SFP Ports Jumbo Frame Support  | module      | Switch1 Linecard 3 (virtual slot 3)    | V02     |             |            | FNS11111111      | Cisco               | WS-X4612-SFP-E | true   |
| Cisco Systems, Inc. WS-C4506-E 6 slot switch           | chassis     | Switch1 System                         | V03     |             |            | FNS11111111      | Cisco               | WS-C4506-E     | false  |
| FanTray                                                | fan         | Switch2 FanTray 1                      | V04     |             |            | FNS11111111      | Cisco               | WS-X4596-E     | true   |
| Power Supply ( AC 1400W )                              | powerSupply | Switch2 Power Supply 1                 | V04     |             |            | FNS11111111      | Cisco Systems, Inc. | PWR-C45-1400AC | true   |
| Power Supply ( AC 1400W )                              | powerSupply | Switch2 Power Supply 2                 | V04     |             |            | FNS11111111      | Cisco Systems, Inc. | PWR-C45-1400AC | true   |
| SFP-10Gbase-SR                                         | -           | TenGigabitEthernet1/1/1                | V03     |             |            | FNS11111111      | CISCO-FINISAR       | SFP-10G-SR     | true   |
| SFP-10Gbase-SR                                         | -           | TenGigabitEthernet1/1/2                | V03     |             |            | FNS11111111      | CISCO-FINISAR       | SFP-10G-SR     | true   |
| Sup 7L-E 10GE (SFP+), 1000BaseX (SFP) with 4 SFP Ports | module      | Switch1 Supervisor 1 (virtual slot 1)  | V01     | 15.0(1r)SG3 | 03.06.03.E | FNS11111111      | Cisco               | WS-X45-SUP7L-E | true   |

 

Script:

#!/usr/bin/env python

# Need following pip packages
# - easysnmp
# - tabulate

# Checkout blog article to tool
# https://lanbugs.de/netzwerktechnik/hersteller/cisco/commandline-tool-for-exporting-cisco-hardware-inventory-via-snmp/


from easysnmp import Session
import argparse
from tabulate import tabulate
from operator import itemgetter
from pprint import pprint

def main():
    ####
    # ARGS
    ####
    description = """
    Cisco inventory grabber\nVersion 0.1\nWritten by Maximilian Thoma 2018
    """

    aparser = argparse.ArgumentParser(description=description)
    aparser.add_argument('-H', dest='host', help='WLC IP address', required=True)
    aparser.add_argument('-v', dest='snmp_version', help='SNMP version, valid are 2 or 3', required=True)
    aparser.add_argument('-C', dest='snmp_community', help='SNMP Community (only v2)')
    aparser.add_argument('-u', dest='snmp_user', help='SNMP user (v3)')
    aparser.add_argument('-A', dest='snmp_auth', help='SNMP auth password (v3)')
    aparser.add_argument('-a', dest='snmp_auth_method', help='SNMP auth method, valid are MD5 or SHA (v3)')
    aparser.add_argument('-X', dest='snmp_privacy', help='SNMP privacy password (v3)')
    aparser.add_argument('-x', dest='snmp_privacy_method', help='SNMP privacy method, valid are AES or DES (v3)')
    aparser.add_argument('-L', dest='snmp_security',
                         help='SNMP security level, valid are no_auth_or_privacy, auth_without_privacy or auth_with_privacy (v3)')
    aparser.add_argument('--csv', dest='csv', help='Result should be CSV', action='store_true')
    args = aparser.parse_args()

    ####
    # Setup SNMP connection
    ####

    if args.snmp_version == "2":
        try:
            snmp = Session(hostname=args.host, version=2, use_numeric=True)

        except Exception as e:
            print e

    if args.snmp_version == "3":
        try:
            snmp = Session(
                hostname=args.host,
                version=3,
                security_level=args.snmp_security,
                security_username=args.snmp_user,
                auth_protocol=args.snmp_auth_method,
                auth_password=args.snmp_auth,
                privacy_protocol=args.snmp_privacy_method,
                privacy_password=args.snmp_privacy,
                use_numeric=True
            )

        except Exception as e:
            print e

    ####
    # Init Data Buffer
    ####

    inventory = {}
    inv_print = []

    ####
    # SNMP Walk inventory
    ####

    port = {
    0: "-",
    1: "other",
    2: "unknown",
    3: "chassis",
    4: "backplane",
    5: "container",
    6: "powerSupply",
    7: "fan",
    8: "sensor",
    9: "module",
    10: "port",
    11: "stack",
    12: "cpu"
    
    }

    ## Get inventory
    result_ids = snmp.walk(".1.3.6.1.2.1.47.1.1.1.1")

    def stripper(string):
        if "NoneType" not in str(type(string)):
            return string.strip()
        else:
            return string


    for r in result_ids:
        
        if r.oid_index in inventory:
            element_id = r.oid.replace(".1.3.6.1.2.1.47.1.1.1.1.","")

            if element_id == "16": # fru
                fru = "true" if "1" in r.value else "false"
                inventory[r.oid_index][element_id] = fru

            elif element_id == "5": # class
                classx = port[int(r.value)] if len(r.value) is 1 else port[0]
                inventory[r.oid_index][element_id] = classx

            else: # everything else
                inventory[r.oid_index][element_id] = r.value
            
        else:
            element_id = r.oid.replace(".1.3.6.1.2.1.47.1.1.1.1.","")
            inventory[r.oid_index] = {}
            inventory[r.oid_index][element_id] = r.value
        
    
    
    for elements, values in inventory.iteritems():
        
        if len(values['11']) >= 1:        
            #print elements
            
            #2 entPhysicalDescr
            #3 entPhysicalVendorType
            #4 entPhysicalContainedIn
            #5 entPhysicalClass
            #6 entPhysicalParentRelPos
            #7 entPhysicalName
            #8 entPhysicalHardwareRev
            #9 entPhysicalFirmwareRev
            #10 entPhysicalSoftwareRev
            #11 entPhysicalSerialNum
            #12 entPhysicalMfgName
            #13 entPhysicalModelName
            #14 entPhysicalAlias
            #15 entPhysicalAssetID
            #16 entPhysicalIsFRU
            
            inv_print.append([stripper(values.get('2')),
                              stripper(values.get('5')),
                              stripper(values.get('7')),
                              stripper(values.get('8')),
                              stripper(values.get('9')),
                              stripper(values.get('10')),
                              stripper(values.get('11')),
                              stripper(values.get('12')),
                              stripper(values.get('13')),
                              stripper(values.get('16'))])



    ####
    # Sort table
    ####

    inv = sorted(inv_print, key=itemgetter(0))

    ####
    # Result
    ####

    if args.csv is True:

        print 'Description;Class;Name;HWRev;FWRev;SWRev;Serial;Manufactor;Model;FRU?'
        
        for line in inv:
            print ';'.join(str(l) for l in line)

    else:
        print tabulate(inv, headers=['Description', 'Class', 'Name', 'HWRev', 'FWRev', 'SWRev', 'Serial', 'Manufactor', 'Model', 'FRU?'], tablefmt="orgtbl")


if __name__ == "__main__":
    main()

 

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

Wir benutzen Cookies um die Nutzerfreundlichkeit der Webseite zu verbessen. Durch Deinen Besuch stimmst Du dem zu.