1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
|
#!/usr/bin/env python3
#
# python-netsnmpagent simple example agent
#
# Copyright (c) 2013-2016 Pieter Hollants <pieter@hollants.com>
# Licensed under the GNU Lesser Public License (LGPL) version 3
#
#
# This is an example of a simple SNMP sub-agent using the AgentX protocol
# to connect to a master agent (snmpd), extending its MIB with the
# information from the included SIMPLE-MIB.txt.
#
# Use the included script run_simple_agent.sh to test this example.
#
# Alternatively, if you want to test with your system-wide snmpd instance,
# it must have as minimal configuration:
#
# rocommunity <rosecret> 127.0.0.1
# master agentx
#
# snmpd must be started first, then this agent must be started as root
# (because of the AgentX socket under /var/run/agentx/master), eg. via "sudo".
#
# Then, from a separate console and from inside the python-netsnmpagent
# directory, you can run eg.:
#
# snmpwalk -v 2c -c <rosecret> -M+. localhost SIMPLE-MIB::simpleMIB
#
# If you wish to test setting values as well, your snmpd.conf needs a
# line like this:
#
# rwcommunity <rwsecret> 127.0.0.1
#
# Then you can try something like:
#
# snmpset -v 2c -c <rwsecret> -M+. localhost \
# SIMPLE-MIB::simpleInteger i 0
#
import sys, os, signal
import optparse
import pprint
# Make sure we use the local copy, not a system-wide one
sys.path.insert(0, os.path.dirname(os.getcwd()))
import netsnmpagent
prgname = sys.argv[0]
# Process command line arguments
parser = optparse.OptionParser()
parser.add_option(
"-m",
"--mastersocket",
dest="mastersocket",
help="Sets the transport specification for the master agent's AgentX socket",
default="/var/run/agentx/master"
)
parser.add_option(
"-p",
"--persistencedir",
dest="persistencedir",
help="Sets the path to the persistence directory",
default="/var/lib/net-snmp"
)
(options, args) = parser.parse_args()
# Get terminal width for usage with pprint
rows, columns = os.popen("stty size", "r").read().split()
# First, create an instance of the netsnmpAgent class. We specify the
# fully-qualified path to SIMPLE-MIB.txt ourselves here, so that you
# don't have to copy the MIB to /usr/share/snmp/mibs.
try:
agent = netsnmpagent.netsnmpAgent(
AgentName = "SimpleAgent",
MasterSocket = options.mastersocket,
PersistenceDir = options.persistencedir,
MIBFiles = [ os.path.abspath(os.path.dirname(sys.argv[0])) +
"/SIMPLE-MIB.txt" ]
)
except netsnmpagent.netsnmpAgentException as e:
print("{0}: {1}".format(prgname, e))
sys.exit(1)
# Then we create all SNMP scalar variables we're willing to serve.
simpleInteger = agent.Integer32(
oidstr = "SIMPLE-MIB::simpleInteger"
)
simpleIntegerContext1 = agent.Integer32(
oidstr = "SIMPLE-MIB::simpleInteger",
context = "context1",
initval = 200,
)
simpleIntegerRO = agent.Integer32(
oidstr = "SIMPLE-MIB::simpleIntegerRO",
writable = False
)
simpleUnsigned = agent.Unsigned32(
oidstr = "SIMPLE-MIB::simpleUnsigned"
)
simpleUnsignedRO = agent.Unsigned32(
oidstr = "SIMPLE-MIB::simpleUnsignedRO",
writable = False
)
simpleCounter32 = agent.Counter32(
oidstr = "SIMPLE-MIB::simpleCounter32"
)
simpleCounter32Context2 = agent.Counter32(
oidstr = "SIMPLE-MIB::simpleCounter32",
context = "context2",
initval = pow(2,32) - 10, # To rule out endianness bugs
)
simpleCounter64 = agent.Counter64(
oidstr = "SIMPLE-MIB::simpleCounter64"
)
simpleCounter64Context2 = agent.Counter64(
oidstr = "SIMPLE-MIB::simpleCounter64",
context = "context2",
initval = pow(2,64) - 10, # To rule out endianness bugs
)
simpleTimeTicks = agent.TimeTicks(
oidstr = "SIMPLE-MIB::simpleTimeTicks"
)
simpleIpAddress = agent.IpAddress(
oidstr = "SIMPLE-MIB::simpleIpAddress",
initval = "127.0.0.1"
)
simpleOctetString = agent.OctetString(
oidstr = "SIMPLE-MIB::simpleOctetString",
initval = "Hello World"
)
simpleDisplayString = agent.DisplayString(
oidstr = "SIMPLE-MIB::simpleDisplayString",
initval = "Nice to meet you"
)
# Create the first table
firstTable = agent.Table(
oidstr = "SIMPLE-MIB::firstTable",
indexes = [
agent.DisplayString()
],
columns = [
(2, agent.DisplayString("Unknown place")),
(3, agent.Integer32(0))
],
counterobj = agent.Unsigned32(
oidstr = "SIMPLE-MIB::firstTableNumber"
)
)
# Add the first table row
firstTableRow1 = firstTable.addRow([agent.DisplayString("aa")])
firstTableRow1.setRowCell(2, agent.DisplayString("Prague"))
firstTableRow1.setRowCell(3, agent.Integer32(20))
# Add the second table row
firstTableRow2 = firstTable.addRow([agent.DisplayString("ab")])
firstTableRow2.setRowCell(2, agent.DisplayString("Barcelona"))
firstTableRow2.setRowCell(3, agent.Integer32(28))
# Add the third table row
firstTableRow3 = firstTable.addRow([agent.DisplayString("bb")])
firstTableRow3.setRowCell(3, agent.Integer32(18))
# Create the second table
secondTable = agent.Table(
oidstr = "SIMPLE-MIB::secondTable",
indexes = [
agent.Integer32()
],
columns = [
(2, agent.DisplayString("Unknown interface")),
(3, agent.Unsigned32())
],
counterobj = agent.Unsigned32(
oidstr = "SIMPLE-MIB::secondTableNumber"
)
)
# Add the first table row
secondTableRow1 = secondTable.addRow([agent.Integer32(1)])
secondTableRow1.setRowCell(2, agent.DisplayString("foo0"))
secondTableRow1.setRowCell(3, agent.Unsigned32(5030))
# Add the second table row
secondTableRow2 = secondTable.addRow([agent.Integer32(2)])
secondTableRow2.setRowCell(2, agent.DisplayString("foo1"))
secondTableRow2.setRowCell(3, agent.Unsigned32(12842))
# Create the third table
thirdTable = agent.Table(
oidstr = "SIMPLE-MIB::thirdTable",
indexes = [
agent.IpAddress()
],
columns = [
(2, agent.DisplayString("Broadcast")),
(3, agent.IpAddress("192.168.0.255"))
],
counterobj = agent.Unsigned32(
oidstr = "SIMPLE-MIB::thirdTableNumber"
)
)
# Add the first table row
thirdTableRow1 = thirdTable.addRow([agent.IpAddress("192.168.0.1")])
thirdTableRow1.setRowCell(2, agent.DisplayString("Host 1"))
thirdTableRow1.setRowCell(3, agent.IpAddress("192.168.0.1"))
# Add the second table row
thirdTableRow2 = thirdTable.addRow([agent.IpAddress("192.168.0.2")])
thirdTableRow2.setRowCell(2, agent.DisplayString("Host 2"))
thirdTableRow2.setRowCell(3, agent.IpAddress("192.168.0.2"))
# Add the third table row
thirdTableRow3 = thirdTable.addRow([agent.IpAddress("192.168.0.3")])
# Finally, we tell the agent to "start". This actually connects the
# agent to the master agent.
try:
agent.start()
except netsnmpagent.netsnmpAgentException as e:
print("{0}: {1}".format(prgname, e))
sys.exit(1)
print("{0}: AgentX connection to snmpd established.".format(prgname))
# Helper function that dumps the state of all registered SNMP variables
def DumpRegistered():
for context in agent.getContexts():
print("{0}: Registered SNMP objects in Context \"{1}\": ".format(prgname, context))
vars = agent.getRegistered(context)
pprint.pprint(vars, width=columns)
print
DumpRegistered()
# Install a signal handler that terminates our simple agent when
# CTRL-C is pressed or a KILL signal is received
def TermHandler(signum, frame):
global loop
loop = False
signal.signal(signal.SIGINT, TermHandler)
signal.signal(signal.SIGTERM, TermHandler)
# Install a signal handler that dumps the state of all registered values
# when SIGHUP is received
def HupHandler(signum, frame):
DumpRegistered()
signal.signal(signal.SIGHUP, HupHandler)
# The simple agent's main loop. We loop endlessly until our signal
# handler above changes the "loop" variable.
print("{0}: Serving SNMP requests, send SIGHUP to dump SNMP object state, press ^C to terminate...".format(prgname))
loop = True
while (loop):
# Block and process SNMP requests, if available
agent.check_and_process()
# Since we didn't give simpleCounter, simpleCounter64 and simpleTimeTicks
# a real meaning in the SIMPLE-MIB, we can basically do with them whatever
# we want. Here, we just increase them, although in different manners.
simpleCounter32.update(simpleCounter32.value() + 2)
simpleCounter64.update(simpleCounter64.value() + 4294967294)
simpleTimeTicks.update(simpleTimeTicks.value() + 1)
# With counters, you can also call increment() on them
simpleCounter32Context2.increment() # By 1
simpleCounter64Context2.increment(5) # By 5
print("{0}: Terminating.".format(prgname))
agent.shutdown()
|