杰瑞科技汇

Python MIBBrowser如何高效管理MIB信息?

Of course! Let's dive into the world of Python MIB Browsers. This is a fantastic use case for Python, as it can automate network device monitoring, configuration, and data collection in ways that graphical tools cannot.

Python MIBBrowser如何高效管理MIB信息?-图1
(图片来源网络,侵删)

A "MIB Browser" in Python isn't a single, pre-built application like the ones from ManageEngine or iReasoning. Instead, it's a custom script or application you build using Python libraries that interact with SNMP agents (your network devices).

Here’s a complete guide covering:

  1. Core Concepts: What a MIB Browser does and why you'd use Python.
  2. Essential Python Libraries: The tools you'll need.
  3. Step-by-Step Guide: Building a simple MIB browser from scratch.
  4. Advanced Features: Going beyond simple lookups.
  5. Complete Code Example: A runnable script to get you started.
  6. GUI Options: For those who want a graphical interface.

Core Concepts: What is a MIB Browser?

A MIB (Management Information Base) is a database of managed objects on a network device (like a router, switch, or server). Each object has a:

  • Numeric OID (Object Identifier): A unique, hierarchical string of numbers (e.g., 3.6.1.2.1.1.1.0).
  • Human-readable Name: A name defined in the MIB file (e.g., sysDescr.0).
  • Data Type & Description: Information about what the value represents (e.g., an Octet String containing the device's description).

A MIB Browser is a tool that lets you:

Python MIBBrowser如何高效管理MIB信息?-图2
(图片来源网络,侵删)
  • Browse the MIB tree to discover available objects.
  • Translate numeric OIDs to their human-readable names and vice-versa.
  • Query a device using SNMP to get the current value of an object.
  • Set the value of an object on a device (using SNMP SET).

Why use Python?

  • Automation: Script repetitive tasks, like checking the CPU usage of 100 switches every 5 minutes.
  • Integration: Seamlessly pull SNMP data into other systems (e.g., a database, a web dashboard, or a monitoring platform like Prometheus).
  • Customization: Build a tool that is perfectly tailored to your specific needs, without the bloat of a general-purpose GUI application.
  • Cost: It's free!

Essential Python Libraries

You'll primarily need two libraries:

  1. PySNMP: The most powerful and feature-rich SNMP library for Python. It's a suite of libraries (pysnmp-hlapi is the high-level API we'll use) that supports SNMPv1, v2c, and v3. It's the industry standard.
  2. pysmi (and its dependencies): This library is responsible for parsing MIB files. It translates human-readable MIB names into numeric OIDs and vice-versa. It's a dependency for a more advanced workflow.

Installation: Open your terminal or command prompt and install them:

pip install pysnmp pysmi pyasn1-modules

Step-by-Step Guide: Building a Simple MIB Browser

Let's build a script that can:

  1. Resolve a MIB name (e.g., sysDescr) to its full OID.
  2. Query a device for the value of that OID.

Step 1: Resolve a MIB Name to an OID

Before you can query a device, you need to know the OID for the object you want. The pysmi library can help us find this.

from pysmi import getMibBuilder
from pysmi.reader import FileReader
from pysmi.writer import Dumper
from pysmi.searcher import PyFileSearcher
from pysmi.parser import SmiParser
# This is a one-time setup to ensure pysmi can find MIB files.
# It tells pysmi where to look for .my and .mib files.
# On Linux/macOS, MIBs are often in /usr/share/snmp/mibs
# On Windows, they might be in C:\usr\share\snmp\mibs or similar.
# You can also download MIBs from sites like iana.org or ietf.org
# and place them in a local directory.
builder = getMibBuilder()
builder.addSources(PyFileSearcher('/usr/share/snmp/mibs')) # Adjust path if needed
# To make sure the MIBs are compiled, you can run this once.
# It will create .py files in the pysmi/mibs directory.
try:
    builder.loadModules('SNMPv2-MIB', 'IF-MIB') # Load some common MIBs
except Exception as e:
    print(f"Could not load MIB modules, this might be okay for OID lookup: {e}")
# Now, let's resolve a MIB name
mib_name = 'sysDescr'
try:
    # The getOidBySymbol function does the magic
    oid = builder.getOidBySymbol(f'SNMPv2-MIB::{mib_name}')
    print(f"MIB Name: {mib_name}")
    print(f"Resolved OID: {'.'.join(map(str, oid))}")
except Exception as e:
    print(f"Error resolving OID for {mib_name}: {e}")

Step 2: Query a Device for an OID Value

Now that we have the OID (3.6.1.2.1.1.1.0 for sysDescr.0), let's query a device. We'll use the high-level API (hlapi) from pysnmp.

You'll need the IP address of a device that responds to SNMP queries (a public one like demo.snmplabs.com is perfect for testing).

from pysnmp.hlapi import *
# --- SNMP Parameters ---
target_ip = 'demo.snmplabs.com' # A public test server
community_string = 'public'      # SNMPv2c community string (like a password)
oid_to_query = '1.3.6.1.2.1.1.1.0' # sysDescr.0
# The hlapi uses a generator-based approach
# (snmpEngine, errorIndication, errorStatus, errorIndex, varBinds) = next(...)
# for (errorIndication, errorStatus, errorIndex, varBinds) in ...:
# This is a clean way to handle SNMP responses
# Perform the SNMP GET operation
for (errorIndication, errorStatus, errorIndex, varBinds) in nextCmd(
    SnmpEngine(),
    CommunityData(community_string),
    UdpTransportTarget((target_ip, 161)),
    ContextData(),
    ObjectType(ObjectIdentity(oid_to_query))
):
    if errorIndication:
        print(f"Error Indication: {errorIndication}")
        break
    elif errorStatus:
        print(f"Error Status: {errorStatus.prettyPrint()}")
        if errorIndex:
            print(f"Error Index: {errorIndex.prettyPrint()}")
        break
    else:
        # varBinds is a list of tuples, like [(oid, value)]
        for varBind in varBinds:
            print(f"OID: {varBind[0]}")
            print(f"Value: {varBind[1]}")
            print(f"Human-readable OID: {varBind[0].prettyPrint()}")

Complete Code Example (Putting it all together)

This script combines the steps above into a single, reusable function. It also handles errors gracefully.

import sys
from pysmi import getMibBuilder
from pysmi.reader import FileReader
from pysmi.searcher import PyFileSearcher
from pysnmp.hlapi import *
# --- MIB Loading (do this once at the start) ---
# This tells pysmi where to find MIB files.
# You may need to adjust this path or download MIBs to a local folder.
MIB_PATHS = ['/usr/share/snmp/mibs', './mibs'] # Add a local 'mibs' folder if you have one
def setup_mib_builder():
    """Initializes the MIB builder and loads common MIBs."""
    builder = getMibBuilder()
    for path in MIB_PATHS:
        try:
            builder.addSources(PyFileSearcher(path))
        except Exception:
            # Silently ignore paths that don't exist
            pass
    # Pre-compile some common MIBs to speed up lookups
    try:
        builder.loadModules('SNMPv2-MIB', 'IF-MIB', 'IP-MIB', 'TCP-MIB')
    except Exception as e:
        print(f"Warning: Could not pre-load MIBs. Lookups might be slower. Error: {e}")
    return builder
MIB_BUILDER = setup_mib_builder()
def resolve_oid(mib_name):
    """Resolves a MIB name (e.g., 'sysDescr') to its OID string."""
    try:
        # Ensure the input is in the format 'MIB-NAME::object-name'
        if '::' not in mib_name:
            # Assume it's a common object from SNMPv2-MIB
            oid_tuple = MIB_BUILDER.getOidBySymbol(f'SNMPv2-MIB::{mib_name}')
        else:
            oid_tuple = MIB_BUILDER.getOidBySymbol(mib_name)
        return '.'.join(map(str, oid_tuple))
    except Exception as e:
        print(f"[ERROR] Could not resolve OID for '{mib_name}': {e}")
        return None
def snmp_get(target_ip, community, oid_or_name, port=161, timeout=1, retries=3):
    """
    Performs an SNMP GET operation on a target device.
    Can accept either a numeric OID string or a MIB name.
    """
    # If a MIB name is provided, resolve it to an OID
    if not oid_or_name.startswith('.'):
        oid_str = resolve_oid(oid_or_name)
        if not oid_str:
            return None
    else:
        oid_str = oid_or_name
    print(f"--- Querying {target_ip} for OID: {oid_str} ---")
    error_indication, error_status, error_index, var_binds = next(
        getCmd(
            SnmpEngine(),
            CommunityData(community),
            UdpTransportTarget((target_ip, port), timeout=timeout, retries=retries),
            ContextData(),
            ObjectType(ObjectIdentity(oid_str))
        )
    )
    if error_indication:
        print(f"  Error Indication: {error_indication}")
        return None
    elif error_status:
        print(f"  Error Status: {error_status.prettyPrint()}")
        if error_index:
            print(f"  Error Index: {error_index.prettyPrint()}")
        return None
    else:
        for var_bind in var_binds:
            # Get the human-readable name of the OID
            oid_name = var_bind[0].prettyPrint()
            value = var_bind[1]
            print(f"  Success!")
            print(f"    OID: {var_bind[0]}")
            print(f"    Name: {oid_name}")
            print(f"    Value: {value}")
            return value
    return None
if __name__ == "__main__":
    # --- Example Usage ---
    DEVICE_IP = 'demo.snmplabs.com'
    COMMUNITY = 'public'
    # Example 1: Query by MIB name
    snmp_get(DEVICE_IP, COMMUNITY, 'sysDescr')
    print("\n" + "="*40 + "\n")
    # Example 2: Query by numeric OID
    snmp_get(DEVICE_IP, COMMUNITY, '1.3.6.1.2.1.1.5.0') # sysName.0
    print("\n" + "="*40 + "\n")
    # Example 3: Query a more complex object from a different MIB
    # This will fail if the IF-MIB is not loaded and parsed correctly
    snmp_get(DEVICE_IP, COMMUNITY, 'ifNumber')

Advanced Features

Once you have the basics, you can expand your script significantly:

  • SNMP Walk: Instead of getting a single OID, you can "walk" a branch of the MIB tree to get all OIDs and their values under a certain point. This is how network monitoring tools discover all interfaces on a switch.

    from pysnmp.hlapi import *
    # Walk the system group (OID 1.3.6.1.2.1.1)
    for (errorIndication, errorStatus, errorIndex, varBinds) in nextCmd(
        SnmpEngine(),
        CommunityData('public'),
        UdpTransportTarget(('demo.snmplabs.com', 161)),
        ContextData(),
        ObjectType(ObjectIdentity('1.3.6.1.2.1.1')), # The starting point for the walk
        lexicographicMode=False # Important for walking tables
    ):
        # ... error handling and printing is the same as GET ...
  • SNMP SET: You can change values on a device if you have the correct permissions. This is used for things like re-naming an interface or changing a VLAN.

    from pysnmp.hlapi import *
    # Set the sysContact string
    errorIndication, errorStatus, errorIndex, varBinds = next(
        setCmd(
            SnmpEngine(),
            CommunityData('private'), # Needs write access
            UdpTransportTarget(('demo.snmplabs.com', 161)),
            ContextData(),
            ObjectType(ObjectIdentity('1.3.6.1.2.1.1.4.0'), 'My Admin <admin@example.com>')
        )
    )
  • SNMPv3: For secure environments, you'll use SNMPv3, which provides authentication and encryption. The hlapi makes this straightforward by using UsmUserData instead of CommunityData.

    from pysnmp.hlapi import *
    # SNMPv3 Example
    for (errorIndication, errorStatus, errorIndex, varBinds) in nextCmd(
        SnmpEngine(),
        UsmUserData('user', 'authkey123', 'privkey456'), # User, AuthKey, PrivKey
        UdpTransportTarget(('192.168.1.1', 161)),
        ContextData(),
        ObjectType(ObjectIdentity('sysDescr.0')),
        lexicographicMode=False
    ):
        # ... handle response ...

GUI Options

If you want a graphical interface for your script, you can use a library like Tkinter (built-in) or PyQt/PySide.

A simple Tkinter app would have:

  • An entry field for the IP address.
  • An entry field for the community string.
  • A dropdown or entry field for the MIB name/OID.
  • A "Get" button.
  • A text area to display the results.

This approach gives you the power and flexibility of Python with the user-friendliness of a GUI.

分享:
扫描分享到社交APP
上一篇
下一篇