Imported Upstream version 2.7.1
This commit is contained in:
parent
a1fa151fc7
commit
0121794af9
451 changed files with 41339 additions and 10887 deletions
287
docs/snmp-subdrivers.txt
Normal file
287
docs/snmp-subdrivers.txt
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
How to make a new subdriver to support another SNMP device
|
||||
----------------------------------------------------------
|
||||
|
||||
Overall concept
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The SNMP protocol allow for a common way to interact with devices over
|
||||
the network.
|
||||
|
||||
The NUT "snmp-ups" driver is a meta-driver that handles many SNMP devices,
|
||||
such as UPS and PDU. It consists of a core driver that handles most of the
|
||||
work of talking to the SNMP agent, and several sub-drivers to handle
|
||||
specific device manufacturers. Adding support for a new SNMP device is
|
||||
easy, because it requires only the creation of a new sub-driver.
|
||||
|
||||
SNMP data Tree
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
From the point of view of writing an SNMP subdriver, an SNMP device
|
||||
consists of a bunch of variables, called OIDs (for Object IDentifiers).
|
||||
Some OIDs (such as the current input voltage) are read-only, whereas
|
||||
others (such as the beeper enabled/disabled/muted status) can be read and
|
||||
written. OID are grouped together and arranged in a hierarchical tree
|
||||
shape, similar to directories in a file system. OID components are
|
||||
separated by ".", and can be expressed in numeric or textual form.
|
||||
For example:
|
||||
|
||||
.iso.org.dod.internet.mgmt.mib-2.system.sysObjectID
|
||||
|
||||
is equivalent to:
|
||||
|
||||
.1.3.6.1.2.1.1.2.0
|
||||
|
||||
Here is an excerpt tree, showing only two OIDs, sysDescr and sysObjectID:
|
||||
|
||||
.iso
|
||||
.org
|
||||
.dod
|
||||
.internet
|
||||
.mgmt
|
||||
.mib-2
|
||||
.system
|
||||
.sysDescr.0 = STRING: Dell UPS Tower 1920W HV
|
||||
.sysObjectID.0 = OID: .iso.org.dod.internet.private.enterprises.674.10902.2
|
||||
(...)
|
||||
.upsMIB
|
||||
.upsObjects
|
||||
.upsIdent
|
||||
.upsIdentModel = STRING: "Dell UPS Tower 1920W HV"
|
||||
(...)
|
||||
.private
|
||||
.enterprises
|
||||
.674
|
||||
.10902
|
||||
.2
|
||||
.100
|
||||
.1.0 = STRING: "Dell UPS Tower 1920W HV"
|
||||
(...)
|
||||
|
||||
As you can see in the above example, the device name is exposed three times,
|
||||
through three different MIBs:
|
||||
|
||||
- Generic MIB-II (RFC 1213):
|
||||
|
||||
.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = STRING: Dell UPS Tower 1920W HV
|
||||
.1.3.6.1.2.1.1.1.0 = STRING: Dell UPS Tower 1920W HV
|
||||
|
||||
- UPS MIB (RFC 1628):
|
||||
|
||||
.iso.org.dod.internet.mgmt.mib-2.upsMIB.upsObjects.upsIdent.upsIdentModel = STRING: "Dell UPS Tower 1920W HV"
|
||||
.1.3.6.1.2.1.33.1.1.2.0 = STRING: "Dell UPS Tower 1920W HV"
|
||||
|
||||
- DELL SNMP UPS MIB:
|
||||
|
||||
.iso.org.dod.internet.private.enterprises.674.10902.2.100.1.0 = STRING: "Dell UPS Tower 1920W HV"
|
||||
|
||||
But only the two last can serve useful data for NUT.
|
||||
|
||||
An highly interesting OID is *sysObjectID*: its value is an OID that refers to
|
||||
the main MIB of the device. In the above example, the device points us at the
|
||||
Dell UPS MIB. *sysObjectID*, also called "sysOID" is used by snmp-ups to find
|
||||
the right mapping structure.
|
||||
|
||||
For more information on SNMP, refer to the
|
||||
link:http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol[Wikipedia]
|
||||
article, or browse the Internet.
|
||||
|
||||
|
||||
To be able to convert values, NUT SNMP subdrivers need to provide:
|
||||
|
||||
- manufacturer-specific sysOID, to determine which lookup structure applies
|
||||
to which devices,
|
||||
- a mapping of SNMP variables to NUT variables,
|
||||
- a mapping of SNMP values to NUT values.
|
||||
|
||||
Moreover, subdrivers might have to provide additional functionality,
|
||||
such as custom implementations of specific instant commands (load.off,
|
||||
shutdown.restart), and conversions of manufacturer specific data
|
||||
formats. At the time of writing this document, snmp-ups doesn't provide
|
||||
such mechanisms (only formatting ones), but it is planned in a future release.
|
||||
|
||||
|
||||
Creating a subdriver
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In order to create a subdriver, you will need the following:
|
||||
|
||||
- the "MIB definition file. This file has a ".mib" extension, and is
|
||||
generally available on the accompanying disc, or on the manufacturer
|
||||
website. It should either be placed in a system directory
|
||||
(/usr/share/mibs/ or equivalent), or pointed using *-M* option,
|
||||
|
||||
- a network access to the device
|
||||
- OR information dumps.
|
||||
|
||||
|
||||
You can create an initial "stub" subdriver for your device by using the helper
|
||||
script *scripts/subdriver/gen-snmp-subdriver.sh*. Note that this only creates
|
||||
a "stub" which MUST be customized to be useful (see CUSTOMIZATION below).
|
||||
|
||||
You have two options to run gen-snmp-subdriver.sh:
|
||||
|
||||
mode 1: get SNMP data from a real agent
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This method requires to have a network access to the device, in order to
|
||||
automatically retrieve the needed information.
|
||||
|
||||
You have to specify the following paramaters:
|
||||
|
||||
- *-H* host address: is the SNMP host IP address or name
|
||||
- *-c* community: is the SNMP v1 community name (default: public)"
|
||||
|
||||
For example:
|
||||
|
||||
$ gen-snmp-subdriver.sh -H W.X.Y.Z -c foobar -n <MIB name>.mib
|
||||
|
||||
mode 2: get data from files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This method does not require direct access to the device, at least
|
||||
not for the one using gen-snmp-subdriver.sh.
|
||||
|
||||
The following SNMP data need to be dumped first:
|
||||
|
||||
- sysOID value: for example '.1.3.6.1.4.1.705.1'
|
||||
- a numeric SNMP walk (OIDs in dotted numeric format) of the tree
|
||||
pointed by sysOID. For example:
|
||||
|
||||
snmpwalk -On -c foobar W.X.Y.Z .1.3.6.1.4.1.705.1 > snmpwalk-On.log
|
||||
|
||||
- a textual SNMP walk (OIDs in string format) of the tree pointed by
|
||||
sysOID. For example:
|
||||
|
||||
snmpwalk -Os -c foobar W.X.Y.Z .1.3.6.1.4.1.705.1 > snmpwalk-Os.log
|
||||
|
||||
NOTE: if the OID are only partially resolved (i.e, there are still parts
|
||||
expressed in numeric form), then try using *-M* to point your .mib file.
|
||||
|
||||
Then call the script using:
|
||||
|
||||
$ gen-snmp-subdriver.sh -s <sysOID value> <numeric SNMP walk> <string SNMP walk>
|
||||
|
||||
For example:
|
||||
|
||||
$ gen-snmp-subdriver.sh -s .1.3.6.1.4.1.705.1 snmpwalk-On.log snmpwalk-Os.log
|
||||
|
||||
This script prompts you for a name for the subdriver if you don't provide it
|
||||
with *-n*. Use only letters and digits, and use natural capitalization such
|
||||
as "Camel" (not "camel" or "CAMEL", apart if it natural). The script may
|
||||
prompt you for additional information.
|
||||
|
||||
Integrating the subdriver with snmp-ups
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Beside of the mandatory customization, there are a few things that you have
|
||||
to do, as mentioned at the end of the script:
|
||||
|
||||
- edit drivers/snmp-ups.h and add #include "<HFILE>.h", where <HFILE> is the
|
||||
name of the header file, with the *.h* extension,
|
||||
- edit drivers/snmp-ups.c and bump DRIVER_VERSION by adding "0.01".
|
||||
- also add "&<LDRIVER>" to snmp-ups.c:mib2nut[] list, where <LDRIVER> is the
|
||||
lower case driver name
|
||||
- add "<LDRIVER>-mib.c" to snmp_ups_SOURCES in drivers/Makefile.am
|
||||
- add "<LDRIVER>-mib.h" to dist_noinst_HEADERS in drivers/Makefile.am
|
||||
- copy "<LDRIVER>-mib.c" and "<LDRIVER>-mib.h" to ../drivers/
|
||||
- finally call the following, from the top level directory, to test
|
||||
compilation:
|
||||
|
||||
$ autoreconf && configure && make
|
||||
|
||||
|
||||
You can already start experimenting with the new subdriver; but all data
|
||||
will be prefixed by "unmapped.". You will now have to customize it.
|
||||
|
||||
|
||||
CUSTOMIZATION
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
The initially generated subdriver code is only a stub (mainly a big C
|
||||
structure to be precise), and will not implement any useful functionality
|
||||
(in particular, it will be unable to shut down the UPS). In the beginning,
|
||||
it simply attempts to monitor some UPS variables. To make this driver useful,
|
||||
you must examine the NUT variables of the form "unmapped.*" in the
|
||||
hid_info_t data structure, and map them to actual NUT variables and
|
||||
instant commands. There are currently no step-by-step instructions for
|
||||
how to do this. Please look at the files to see how the currently implemented
|
||||
subdrivers are written.:
|
||||
|
||||
- apc-mib.c/h
|
||||
- baytech-mib.c/h
|
||||
- bestpower-mib.c/h
|
||||
- compaq-mib.c/h
|
||||
- cyberpower-mib.c/h
|
||||
- eaton-mib.c/h
|
||||
- ietf-mib.c/h
|
||||
- mge-mib.c/h
|
||||
- netvision-mib.c/h
|
||||
- powerware-mib.c/h
|
||||
- raritan-pdu-mib.c
|
||||
|
||||
To help you, above each entry in <LDRIVER>-mib.c, there is a comment that
|
||||
displays the textual OID name. For example, the following entry:
|
||||
|
||||
/* upsMIB.upsObjects.upsIdent.upsIdentModel = STRING: "Dell UPS Tower 1920W HV" */
|
||||
{ "unmapped.upsidentmodel", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2254.2.4.1.1.0", NULL, SU_FLAG_OK, NULL },
|
||||
|
||||
Many time, only the first field will need to be modified, to map to an actual
|
||||
NUT variable name.
|
||||
|
||||
Check the <<nut-names,NUT command and variable naming scheme>> section first
|
||||
to find a name that matches the OID name (closest fit). If nothing matches,
|
||||
contact the upsdev list, and we'll figure it out.
|
||||
|
||||
In the above example, the right NUT variable is obviously "device.model".
|
||||
|
||||
The MIB definition file (.mib) also contains some description of these OIDs,
|
||||
along with the possible enumerated values.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
FIXME:
|
||||
|
||||
Shutting down the UPS
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It is desireable to support shutting down the UPS. Usually (for
|
||||
devices that follow the HID Power Device Class specification), this
|
||||
requires sending the UPS two commands. One for shutting down the UPS
|
||||
(with an 'offdelay') and one for restarting it (with an 'ondelay'),
|
||||
where offdelay < ondelay. The two NUT commands for which this is
|
||||
relevant, are 'shutdown.return' and 'shutdown.stayoff'.
|
||||
|
||||
Since the one-to-one mapping above doesn't allow sending two HID
|
||||
commands to the UPS in response to sending one NUT command to the
|
||||
driver, this is handled by the driver. In order to make this work,
|
||||
you need to define the following four NUT values:
|
||||
|
||||
ups.delay.start (variable, R/W)
|
||||
ups.delay.shutdown (variable, R/W)
|
||||
load.off.delay (command)
|
||||
load.on.delay (command)
|
||||
|
||||
If the UPS supports it, the following variables can be used to show
|
||||
the countdown to start/shutdown:
|
||||
|
||||
ups.timer.start (variable, R/O)
|
||||
ups.timer.shutdown (variable, R/O)
|
||||
|
||||
The `load.on` and `load.off` commands will be defined implicitly by
|
||||
the driver (using a delay value of '0'). Define these commands
|
||||
yourself, if your UPS requires a different value to switch on/off
|
||||
the load without delay.
|
||||
|
||||
Note that the driver expects the `load.off.delay` and `load.on.delay`
|
||||
to follow the HID Power Device Class specification, which means that
|
||||
the `load.on.delay` command should NOT switch on the load in the
|
||||
absence of mains power. If your UPS switches on the load regardless of
|
||||
the mains status, DO NOT define this command. You probably want to
|
||||
define the `shutdown.return` and/or `shutdown.stayoff` commands in
|
||||
that case. Commands defined in the subdriver will take precedence over
|
||||
the ones that are composed in the driver.
|
||||
|
||||
When running the driver with the '-k' flag, it will first attempt to
|
||||
send a `shutdown.return` command and if that fails, will fallback to
|
||||
`shutdown.reboot`.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Loading…
Add table
Add a link
Reference in a new issue