Использование pySNMP для написания агента SNMP (для OpenNMS)

Я пытаюсь написать агент SNMP python, который я могу встроить в свое приложение python, чтобы приложение можно было удаленно контролировать с помощью OpenNMS. OpenNMS ожидает, что агент реализует HOST-RESOURCES-MIB запрос двух полей hrSWRunNameи hrSWRunStatus.

Я взял пример pysnmp за основу своего кода и отредактировал его так, как считал нужным. Результирующий код выглядит следующим образом:

import logging

from pysnmp import debug
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.proto.api import v2c
from pysnmp.smi import builder, instrum, exval


# debug.setLogger(debug.Debug('all'))

formatting = '[%(asctime)s-%(levelname)s]-(%(module)s) %(message)s'
logging.basicConfig(level=logging.DEBUG, format=formatting, )

logging.info("Starting....")

# Create SNMP engine
snmpEngine = engine.SnmpEngine()

# Transport setup

# UDP over IPv4
config.addTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openServerMode(('localhost', 12345))
)

# SNMPv2c setup

# SecurityName <-> CommunityName mapping.
config.addV1System(snmpEngine, 'my-area', 'public')

# Allow read MIB access for this user / securityModels at VACM
config.addVacmUser(snmpEngine,
                   2,
                   'my-area',
                   'noAuthNoPriv',
                   (1, 3, 6, 1, 2, 1),
                   (1, 3, 6, 1, 2, 1))


# Create an SNMP context
snmpContext = context.SnmpContext(snmpEngine)

logging.debug('Loading HOST-RESOURCES-MIB module...'),
mibBuilder = builder.MibBuilder().loadModules('HOST-RESOURCES-MIB')
logging.debug('done')

logging.debug('Building MIB tree...'),
mibInstrum = instrum.MibInstrumController(mibBuilder)
logging.debug('done')

logging.debug('Building table entry index from human-friendly representation...')
# see http://www.oidview.com/mibs/0/HOST-RESOURCES-MIB.html
hostRunTable, = mibBuilder.importSymbols('HOST-RESOURCES-MIB', 'hrSWRunEntry')
instanceId = hostRunTable.getInstIdFromIndices(1)
logging.debug('done')


# The following shows the OID name mapping
#
# hrSWRunTable          1.3.6.1.2.1.25.4.2          <TABLE>
# hrSWRunEntry          1.3.6.1.2.1.25.4.2.1        <SEQUENCE>
# hrSWRunIndex          1.3.6.1.2.1.25.4.2.1.1      <Integer32>
# hrSWRunName           1.3.6.1.2.1.25.4.2.1.2      <InternationalDisplayString> 64 Char
# hrSWRunID             1.3.6.1.2.1.25.4.2.1.3      <ProductID>
# hrSWRunPath           1.3.6.1.2.1.25.4.2.1.4      <InternationalDisplayString> 128 octets
# hrSWRunParameters     1.3.6.1.2.1.25.4.2.1.5      <InternationalDisplayString> 128 octets
# hrSWRunType           1.3.6.1.2.1.25.4.2.1.6      <INTEGER>
# hrSWRunStatus         1.3.6.1.2.1.25.4.2.1.7      <INTEGER>  <<===== This is the key variable used by Opennms


# http://docs.opennms.org/opennms/releases/18.0.1/guide-admin/guide-admin.html#_hostresourceswrunmonitor)


logging.debug('Create/update HOST-RESOURCES-MIB::hrSWRunTable table row:')
varBinds = mibInstrum.writeVars((
                                 (hostRunTable.name + (1,) + instanceId, 1),
                                 (hostRunTable.name + (2,) + instanceId, 'AppName'), # <=== Must match OpenNMS service-name variable
                                 (hostRunTable.name + (3,) + instanceId,  {0,0}), #  
                                 (hostRunTable.name + (4,) + instanceId, 'All is well'),
                                 (hostRunTable.name + (5,) + instanceId, 'If this was not the case it would say so here'),
                                 (hostRunTable.name + (6,) + instanceId, 4),# Values are ==> unknown(1), operatingSystem(2), deviceDriver(3), application(4)     
                                 (hostRunTable.name + (7,) + instanceId, 1) #<<=== This is the status number OpenNMS looks at Values are ==> running(1), runnable(2), notRunnable(3), invalid(4)
                                 ))

for oid, val in varBinds:
    print('%s = %s' % ('.'.join([str(x) for x in oid]), val.prettyPrint()))
logging.debug('done')

logging.debug('Read whole MIB (table walk)')
oid, val = (), None
while True:
    oid, val = mibInstrum.readNextVars(((oid, val),))[0]
    if exval.endOfMib.isSameTypeWith(val):
        break
    print('%s = %s' % ('.'.join([str(x) for x in oid]), val.prettyPrint()))
logging.debug('done')

# logging.debug('Unloading MIB modules...'),
# mibBuilder.unloadModules()
# logging.debug('done')


# --- end of  table population ---

# Register SNMP Applications at the SNMP engine for particular SNMP context
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)

# Register an imaginary never-ending job to keep I/O dispatcher running forever
snmpEngine.transportDispatcher.jobStarted(1)

# Run I/O dispatcher which would receive queries and send responses
try:
    snmpEngine.transportDispatcher.runDispatcher()
except:
    snmpEngine.transportDispatcher.closeDispatcher()
    raise

Код работает без ошибок. varBinds и обход таблицы MIB показывают, чего, по моему мнению, мне следует ожидать:

[2016-12-29 16:42:49,323-INFO]-(SNMPAgent) Starting....
[2016-12-29 16:42:49,470-DEBUG]-(SNMPAgent) Loading HOST-RESOURCES-MIB module...
[2016-12-29 16:42:49,631-DEBUG]-(SNMPAgent) done
[2016-12-29 16:42:49,631-DEBUG]-(SNMPAgent) Building MIB tree...
[2016-12-29 16:42:49,631-DEBUG]-(SNMPAgent) done
[2016-12-29 16:42:49,631-DEBUG]-(SNMPAgent) Building table entry index from human-friendly representation...
[2016-12-29 16:42:49,631-DEBUG]-(SNMPAgent) done
[2016-12-29 16:42:49,632-DEBUG]-(SNMPAgent) Create/update HOST-RESOURCES-MIB::hrSWRunTable table row:
1.3.6.1.2.1.25.4.2.1.1.1 = 1
[2016-12-29 16:42:49,651-DEBUG]-(SNMPAgent) done
1.3.6.1.2.1.25.4.2.1.2.1 = TradeLoader
1.3.6.1.2.1.25.4.2.1.3.1 = 0
1.3.6.1.2.1.25.4.2.1.4.1 = All is well
1.3.6.1.2.1.25.4.2.1.5.1 = If this was not the case it would say so here
1.3.6.1.2.1.25.4.2.1.6.1 = 'application'
1.3.6.1.2.1.25.4.2.1.7.1 = 'running'
[2016-12-29 16:42:49,651-DEBUG]-(SNMPAgent) Read whole MIB (table walk)
1.3.6.1.2.1.25.4.2.1.1.1 = 1
1.3.6.1.2.1.25.4.2.1.2.1 = TradeLoader
1.3.6.1.2.1.25.4.2.1.3.1 = 0
1.3.6.1.2.1.25.4.2.1.4.1 = All is well
1.3.6.1.2.1.25.4.2.1.5.1 = If this was not the case it would say so here
1.3.6.1.2.1.25.4.2.1.6.1 = 'application'
1.3.6.1.2.1.25.4.2.1.7.1 = 'running'
1.3.6.1.2.1.25.5.1.1.1.1 = <no value>
1.3.6.1.2.1.25.5.1.1.2.1 = <no value>
[2016-12-29 16:42:53,490-DEBUG]-(SNMPAgent) done

Наконец, диспетчер запускается.

Проблема в том, что когда я пытаюсь запросить агент, ничего не происходит. Я не получаю ответа. Я просмотрел свой код, и одна очевидная вещь в нем заключается в том, что я явно не связываю snmpEngine с моей созданной MIB. Должен ли я это сделать?

Любое понимание будет принято, поскольку я изо всех сил пытаюсь понять, куда идти в данный момент.


person Richard B    schedule 29.12.2016    source источник


Ответы (2)


Я думал, что просто опубликую ответ на свой вопрос, так как мне потребовалось так много времени, чтобы понять, как делать то, что мне нужно. Надеюсь, кто-то еще найдет это полезным. Следующий код позволяет мне заполнить любую MIB, известную pysnmp, а затем сделать MIB доступной для сети в качестве агента SNMP V2.

import logging

from pysnmp import debug
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.proto.api import v2c
from pysnmp.smi import builder, instrum, exval

# Uncomment this to turn pysnmp debugging on
#debug.setLogger(debug.Debug('all'))

formatting = '[%(asctime)s-%(levelname)s]-(%(module)s) %(message)s'
logging.basicConfig(level=logging.DEBUG, format=formatting, )

logging.info("Starting....")

# Create SNMP engine
snmpEngine = engine.SnmpEngine()

# Transport setup

# UDP over IPv4
config.addTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openServerMode(('0.0.0.0', 12345))
)

# SNMPv2c setup

# SecurityName <-> CommunityName mapping.
config.addV1System(snmpEngine, 'my-area', 'public')

# Allow read MIB access for this user / securityModels at VACM
# Limit access to just the custom MIB. Widen if need be
config.addVacmUser(snmpEngine,
                   2,
                   'my-area',
                   'noAuthNoPriv',
                   (1, 3, 6, 1, 2, 1, 25, 4),
                   (1, 3, 6, 1, 2, 1, 25, 4))


# Create an SNMP context and ensure the custom MIB is loaded
# Your system must have this MIB installed otherwise pysnmp 
# can't load it! 
snmpContext = context.SnmpContext(snmpEngine)
logging.debug('Loading HOST-RESOURCES-MIB module...'),
mibBuilder = snmpContext.getMibInstrum().getMibBuilder()
mibBuilder.loadModules('HOST-RESOURCES-MIB')
mibInstrum = snmpContext.getMibInstrum()
logging.debug('done')

logging.debug('Building table entry index from human-friendly representation...')
# see http://www.oidview.com/mibs/0/HOST-RESOURCES-MIB.html
hostRunTable, = mibBuilder.importSymbols('HOST-RESOURCES-MIB', 'hrSWRunEntry')
instanceId = hostRunTable.getInstIdFromIndices(1)
logging.debug('done')


# The following shows the OID name mapping
#
# hrSWRunTable          1.3.6.1.2.1.25.4.2          <TABLE>
# hrSWRunEntry          1.3.6.1.2.1.25.4.2.1        <SEQUENCE>
# hrSWRunIndex          1.3.6.1.2.1.25.4.2.1.1      <Integer32>
# hrSWRunName           1.3.6.1.2.1.25.4.2.1.2      <InternationalDisplayString> 64 Char
# hrSWRunID             1.3.6.1.2.1.25.4.2.1.3      <ProductID>
# hrSWRunPath           1.3.6.1.2.1.25.4.2.1.4      <InternationalDisplayString> 128 octets
# hrSWRunParameters     1.3.6.1.2.1.25.4.2.1.5      <InternationalDisplayString> 128 octets
# hrSWRunType           1.3.6.1.2.1.25.4.2.1.6      <INTEGER>
# hrSWRunStatus         1.3.6.1.2.1.25.4.2.1.7      <INTEGER>  <<===== This is the key variable used by Opennms

# We are going to use OpenNMS as the SNMP manager. OpenNMS will poll this agent to check on its status. The manual 
# states:
#
# "This monitor tests the running state of one or more processes. It does this using SNMP and by inspecting the 
# hrSwRunTable of the HOST-RESOURCES-MIB. The test is done by matching a given process as hrSWRunName against
# the numeric value of the hrSWRunStatus". hrSWRunName is matched against the process name defined in the OpenNMS
# config file under the heading "service-name". hrSWRunStatus is set to whatever your desired status is. OpenNMS 
# will compare this value against the config file variable run-level. If hrSWRunStatus > run-level the process
# will be marked as having problems. for the complete page see: 
# http://docs.opennms.org/opennms/releases/18.0.1/guide-admin/guide-admin.html#_hostresourceswrunmonitor)


# I have made up an enterprise MIB for us. The number is moot as it's not going to go anywhere but the code needs 
# something valid.
# The enterprise MIB I have chosen is
enterpriseMib = (1, 3, 6, 1, 4, 1, 50000, 0)

logging.debug('Create/update HOST-RESOURCES-MIB::hrSWRunTable table row:')
varBinds = mibInstrum.writeVars((
                                 (hostRunTable.name + (1,) + instanceId, 1),
                                 (hostRunTable.name + (2,) + instanceId, 'TradeLoader'), # <=== Must match OpenNMS service-name variable
                                 (hostRunTable.name + (3,) + instanceId,  enterpriseMib), #  
                                 (hostRunTable.name + (4,) + instanceId, 'All is well'),
                                 (hostRunTable.name + (5,) + instanceId, 'If this was not the case it would say so here'),
                                 (hostRunTable.name + (6,) + instanceId, 4),# Values are ==> unknown(1), operatingSystem(2), deviceDriver(3), application(4)     
                                 (hostRunTable.name + (7,) + instanceId, 1) #<<=== This is the status number OpenNMS looks at Values are ==> running(1), runnable(2), notRunnable(3), invalid(4)
                                 ))

# --- end of  table population ---
logging.debug('Confirm that the data has been set by reading whole MIB (table walk)')
oid, val = (), None
while True:
    oid, val = mibInstrum.readNextVars(((oid, val),))[0]
    if exval.endOfMib.isSameTypeWith(val):
        break
    print('%s = %s' % ('.'.join([str(x) for x in oid]), val.prettyPrint()))
logging.debug('done')

# Register SNMP Applications at the SNMP engine for particular SNMP context
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)

# Register an imaginary never-ending job to keep I/O dispatcher running forever
snmpEngine.transportDispatcher.jobStarted(1)

# Run I/O dispatcher which would receive queries and send responses
try:
    snmpEngine.transportDispatcher.runDispatcher()
except:
    snmpEngine.transportDispatcher.closeDispatcher()
    raise

Сообщения регистратора показывают

[2017-01-09 16:30:15,401-INFO]-(SNMPAgent) Starting.... [2017-01-09 16:30:15,490-DEBUG]-(SNMPAgent) Loading HOST-RESOURCES-MIB module... [2017-01-09 16:30:15,513-DEBUG]-(SNMPAgent) done [2017-01-09 16:30:15,513-DEBUG]-(SNMPAgent) Building table entry index from human-friendly representation... [2017-01-09 16:30:15,515-DEBUG]-(SNMPAgent) done [2017-01-09 16:30:15,515-DEBUG]-(SNMPAgent) Create/update HOST-RESOURCES-MIB::hrSWRunTable table row: [2017-01-09 16:30:15,536-DEBUG]-(SNMPAgent) Confirm that the data has been set by reading whole MIB (table walk)
1.3.6.1.2.1.25.4.2.1.1.1 = 1
1.3.6.1.2.1.25.4.2.1.2.1 = TradeLoader
1.3.6.1.2.1.25.4.2.1.3.1 = 1.3.6.1.4.1.50000.0
1.3.6.1.2.1.25.4.2.1.4.1 = All is well
1.3.6.1.2.1.25.4.2.1.5.1 = If this was not the case it would say so here
1.3.6.1.2.1.25.4.2.1.6.1 = 'application'
1.3.6.1.2.1.25.4.2.1.7.1 = 'running'
1.3.6.1.2.1.25.5.1.1.1.1 = <no value>
1.3.6.1.2.1.25.5.1.1.2.1 = <no value>
1.3.6.1.6.3.10.2.1.1.0 = 0x80004fb805049c06c8
1.3.6.1.6.3.10.2.1.2.0 = 2
1.3.6.1.6.3.10.2.1.3.0 = 0
1.3.6.1.6.3.10.2.1.4.0 = 65507
1.3.6.1.6.3.16.1.1.1.1.0 = 
1.3.6.1.6.3.16.1.2.1.1.2.7.109.121.45.97.114.101.97 = 2
1.3.6.1.6.3.16.1.2.1.2.2.7.109.121.45.97.114.101.97 = my-area
1.3.6.1.6.3.16.1.2.1.3.2.7.109.121.45.97.114.101.97 = v-1203634843-2
1.3.6.1.6.3.16.1.2.1.4.2.7.109.121.45.97.114.101.97 = 'nonVolatile'
1.3.6.1.6.3.16.1.2.1.5.2.7.109.121.45.97.114.101.97 = 'active'
1.3.6.1.6.3.16.1.4.1.1.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = 
1.3.6.1.6.3.16.1.4.1.2.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = 2
1.3.6.1.6.3.16.1.4.1.3.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = 'noAuthNoPriv'
1.3.6.1.6.3.16.1.4.1.4.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = 'exact'
1.3.6.1.6.3.16.1.4.1.5.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = rv-1203634843-2
1.3.6.1.6.3.16.1.4.1.6.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = wv-1203634843-2
1.3.6.1.6.3.16.1.4.1.7.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = nv-1203634843-2
1.3.6.1.6.3.16.1.4.1.8.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = 'nonVolatile'
1.3.6.1.6.3.16.1.4.1.9.14.118.45.49.50.48.51.54.51.52.56.52.51.45.50.0.2.1 = 'active'
1.3.6.1.6.3.16.1.5.2.1.1.15.114.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= rv-1203634843-2
1.3.6.1.6.3.16.1.5.2.1.1.15.119.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= wv-1203634843-2
1.3.6.1.6.3.16.1.5.2.1.2.15.114.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 1.3.6.1.2.1.25.4
1.3.6.1.6.3.16.1.5.2.1.2.15.119.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 1.3.6.1.2.1.25.4
1.3.6.1.6.3.16.1.5.2.1.3.15.114.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 
1.3.6.1.6.3.16.1.5.2.1.3.15.119.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 
1.3.6.1.6.3.16.1.5.2.1.4.15.114.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 'included'
1.3.6.1.6.3.16.1.5.2.1.4.15.119.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 'included'
1.3.6.1.6.3.16.1.5.2.1.5.15.114.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 'nonVolatile'
1.3.6.1.6.3.16.1.5.2.1.5.15.119.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 'nonVolatile'
1.3.6.1.6.3.16.1.5.2.1.6.15.114.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 'active'
1.3.6.1.6.3.16.1.5.2.1.6.15.119.118.45.49.50.48.51.54.51.52.56.52.51.45.50.11.1.3.6.1.2.1.25.4
= 'active'
1.3.6.1.6.3.18.1.1.1.1.109.121.45.97.114.101.97 = my-area
1.3.6.1.6.3.18.1.1.1.2.109.121.45.97.114.101.97 = public
1.3.6.1.6.3.18.1.1.1.3.109.121.45.97.114.101.97 = my-area
1.3.6.1.6.3.18.1.1.1.4.109.121.45.97.114.101.97 = 0x80004fb805049c06c8
1.3.6.1.6.3.18.1.1.1.5.109.121.45.97.114.101.97 = 
1.3.6.1.6.3.18.1.1.1.6.109.121.45.97.114.101.97 = 
1.3.6.1.6.3.18.1.1.1.7.109.121.45.97.114.101.97 = 'nonVolatile'
1.3.6.1.6.3.18.1.1.1.8.109.121.45.97.114.101.97 = 'active' [2017-01-09 16:30:15,683-DEBUG]-(SNMPAgent) done

И агент может быть запрошен, чтобы показать результаты следующим образом:

snmpwalk -v 2c -c public -n my-context 0.0.0.0:12345 1.3.6

HOST-RESOURCES-MIB::hrSWRunIndex.1 = INTEGER: 1
HOST-RESOURCES-MIB::hrSWRunName.1 = STRING: "TradeLoader"
HOST-RESOURCES-MIB::hrSWRunID.1 = OID: SNMPv2-SMI::enterprises.50000.0
HOST-RESOURCES-MIB::hrSWRunPath.1 = STRING: "All is well"
HOST-RESOURCES-MIB::hrSWRunParameters.1 = STRING: "If this was not the case it would say so here"
HOST-RESOURCES-MIB::hrSWRunType.1 = INTEGER: application(4)
HOST-RESOURCES-MIB::hrSWRunStatus.1 = INTEGER: running(1)
HOST-RESOURCES-MIB::hrSWRunStatus.1 = No more variables left in this MIB View (It is past the end of the MIB tree)
person Richard B    schedule 09.01.2017

Ты говоришь

Проблема в том, что когда я пытаюсь запросить агент, ничего не происходит. я не получаю ответа

Похоже 2 проблемы:

а) localhost разрешается в петлевой адрес 127.0.0.1 в моей системе, так что вы можете получить к нему доступ только из той же системы, что и ваш агент.

б) вы регистрируетесь как SNMP версии 2 в addVacmUser, поэтому вы не можете получить доступ с V1

После этого:

% snmpwalk -v 2c -c public 127.0.0.1:12345
SNMPv2-MIB::sysDescr.0 = STRING: PySNMP engine version 4.3.2, Python 2.7.5 (default, Nov  3 2014, 14:33:39)  [GCC 4.8.3 20140911 (Red Hat 4.8.3-7)]
SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.20408
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysContact.0 = STRING: 
...

хотя нет объектов HOST-RESOURCE-MIB. Это еще одна проблема.

person Gambit Support    schedule 05.01.2017
comment
Очевидно, что если вы измените localhost на 0.0.0.0 (INADDR_ANY), вы сможете получить доступ из другой системы. - person Gambit Support; 06.01.2017
comment
Спасибо за этот ответ. Причина, по которой я использовал localhost, заключается в том, что я провожу тестирование с агентом и менеджером на одной машине. Я не верю, что это приводит к проблемам, или я ошибаюсь? Ваша вторая проблема меня немного смущает, поскольку я не пытаюсь получить доступ к агенту с помощью SNMP V1 (и я не верю, что мой пример тоже) - person Richard B; 08.01.2017