1 How to make a new subdriver to support another SNMP device
2 ----------------------------------------------------------
7 The SNMP protocol allow for a common way to interact with devices over
10 The NUT "snmp-ups" driver is a meta-driver that handles many SNMP devices,
11 such as UPS and PDU. It consists of a core driver that handles most of the
12 work of talking to the SNMP agent, and several sub-drivers to handle
13 specific device manufacturers. Adding support for a new SNMP device is
14 easy, because it requires only the creation of a new sub-driver.
19 From the point of view of writing an SNMP subdriver, an SNMP device
20 consists of a bunch of variables, called OIDs (for Object IDentifiers).
21 Some OIDs (such as the current input voltage) are read-only, whereas
22 others (such as the beeper enabled/disabled/muted status) can be read and
23 written. OID are grouped together and arranged in a hierarchical tree
24 shape, similar to directories in a file system. OID components are
25 separated by ".", and can be expressed in numeric or textual form.
28 .iso.org.dod.internet.mgmt.mib-2.system.sysObjectID
34 Here is an excerpt tree, showing only two OIDs, sysDescr and sysObjectID:
43 .sysDescr.0 = STRING: Dell UPS Tower 1920W HV
44 .sysObjectID.0 = OID: .iso.org.dod.internet.private.enterprises.674.10902.2
49 .upsIdentModel = STRING: "Dell UPS Tower 1920W HV"
57 .1.0 = STRING: "Dell UPS Tower 1920W HV"
60 As you can see in the above example, the device name is exposed three times,
61 through three different MIBs:
63 - Generic MIB-II (RFC 1213):
65 .iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = STRING: Dell UPS Tower 1920W HV
66 .1.3.6.1.2.1.1.1.0 = STRING: Dell UPS Tower 1920W HV
70 .iso.org.dod.internet.mgmt.mib-2.upsMIB.upsObjects.upsIdent.upsIdentModel = STRING: "Dell UPS Tower 1920W HV"
71 .1.3.6.1.2.1.33.1.1.2.0 = STRING: "Dell UPS Tower 1920W HV"
75 .iso.org.dod.internet.private.enterprises.674.10902.2.100.1.0 = STRING: "Dell UPS Tower 1920W HV"
77 But only the two last can serve useful data for NUT.
79 An highly interesting OID is *sysObjectID*: its value is an OID that refers to
80 the main MIB of the device. In the above example, the device points us at the
81 Dell UPS MIB. *sysObjectID*, also called "sysOID" is used by snmp-ups to find
82 the right mapping structure.
84 For more information on SNMP, refer to the
85 link:http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol[Wikipedia]
86 article, or browse the Internet.
89 To be able to convert values, NUT SNMP subdrivers need to provide:
91 - manufacturer-specific sysOID, to determine which lookup structure applies
93 - a mapping of SNMP variables to NUT variables,
94 - a mapping of SNMP values to NUT values.
96 Moreover, subdrivers might have to provide additional functionality,
97 such as custom implementations of specific instant commands (load.off,
98 shutdown.restart), and conversions of manufacturer specific data
99 formats. At the time of writing this document, snmp-ups doesn't provide
100 such mechanisms (only formatting ones), but it is planned in a future release.
106 In order to create a subdriver, you will need the following:
108 - the "MIB definition file. This file has a ".mib" extension, and is
109 generally available on the accompanying disc, or on the manufacturer
110 website. It should either be placed in a system directory
111 (/usr/share/mibs/ or equivalent), or pointed using *-M* option,
113 - a network access to the device
114 - OR information dumps.
117 You can create an initial "stub" subdriver for your device by using the helper
118 script *scripts/subdriver/gen-snmp-subdriver.sh*. Note that this only creates
119 a "stub" which MUST be customized to be useful (see CUSTOMIZATION below).
121 You have two options to run gen-snmp-subdriver.sh:
123 mode 1: get SNMP data from a real agent
124 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
126 This method requires to have a network access to the device, in order to
127 automatically retrieve the needed information.
129 You have to specify the following paramaters:
131 - *-H* host address: is the SNMP host IP address or name
132 - *-c* community: is the SNMP v1 community name (default: public)"
136 $ gen-snmp-subdriver.sh -H W.X.Y.Z -c foobar -n <MIB name>.mib
138 mode 2: get data from files
139 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
141 This method does not require direct access to the device, at least
142 not for the one using gen-snmp-subdriver.sh.
144 The following SNMP data need to be dumped first:
146 - sysOID value: for example '.1.3.6.1.4.1.705.1'
147 - a numeric SNMP walk (OIDs in dotted numeric format) of the tree
148 pointed by sysOID. For example:
150 snmpwalk -On -c foobar W.X.Y.Z .1.3.6.1.4.1.705.1 > snmpwalk-On.log
152 - a textual SNMP walk (OIDs in string format) of the tree pointed by
155 snmpwalk -Os -c foobar W.X.Y.Z .1.3.6.1.4.1.705.1 > snmpwalk-Os.log
157 NOTE: if the OID are only partially resolved (i.e, there are still parts
158 expressed in numeric form), then try using *-M* to point your .mib file.
160 Then call the script using:
162 $ gen-snmp-subdriver.sh -s <sysOID value> <numeric SNMP walk> <string SNMP walk>
166 $ gen-snmp-subdriver.sh -s .1.3.6.1.4.1.705.1 snmpwalk-On.log snmpwalk-Os.log
168 This script prompts you for a name for the subdriver if you don't provide it
169 with *-n*. Use only letters and digits, and use natural capitalization such
170 as "Camel" (not "camel" or "CAMEL", apart if it natural). The script may
171 prompt you for additional information.
173 Integrating the subdriver with snmp-ups
174 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
176 Beside of the mandatory customization, there are a few things that you have
177 to do, as mentioned at the end of the script:
179 - edit drivers/snmp-ups.h and add #include "<HFILE>.h", where <HFILE> is the
180 name of the header file, with the *.h* extension,
181 - edit drivers/snmp-ups.c and bump DRIVER_VERSION by adding "0.01".
182 - also add "&<LDRIVER>" to snmp-ups.c:mib2nut[] list, where <LDRIVER> is the
183 lower case driver name
184 - add "<LDRIVER>-mib.c" to snmp_ups_SOURCES in drivers/Makefile.am
185 - add "<LDRIVER>-mib.h" to dist_noinst_HEADERS in drivers/Makefile.am
186 - copy "<LDRIVER>-mib.c" and "<LDRIVER>-mib.h" to ../drivers/
187 - finally call the following, from the top level directory, to test
190 $ autoreconf && configure && make
193 You can already start experimenting with the new subdriver; but all data
194 will be prefixed by "unmapped.". You will now have to customize it.
200 The initially generated subdriver code is only a stub (mainly a big C
201 structure to be precise), and will not implement any useful functionality
202 (in particular, it will be unable to shut down the UPS). In the beginning,
203 it simply attempts to monitor some UPS variables. To make this driver useful,
204 you must examine the NUT variables of the form "unmapped.*" in the
205 hid_info_t data structure, and map them to actual NUT variables and
206 instant commands. There are currently no step-by-step instructions for
207 how to do this. Please look at the files to see how the currently implemented
208 subdrivers are written.:
222 To help you, above each entry in <LDRIVER>-mib.c, there is a comment that
223 displays the textual OID name. For example, the following entry:
225 /* upsMIB.upsObjects.upsIdent.upsIdentModel = STRING: "Dell UPS Tower 1920W HV" */
226 { "unmapped.upsidentmodel", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2254.2.4.1.1.0", NULL, SU_FLAG_OK, NULL },
228 Many time, only the first field will need to be modified, to map to an actual
231 Check the <<nut-names,NUT command and variable naming scheme>> section first
232 to find a name that matches the OID name (closest fit). If nothing matches,
233 contact the upsdev list, and we'll figure it out.
235 In the above example, the right NUT variable is obviously "device.model".
237 The MIB definition file (.mib) also contains some description of these OIDs,
238 along with the possible enumerated values.
240 ////////////////////////////////////////////////////////////////////////////////
243 Shutting down the UPS
244 ~~~~~~~~~~~~~~~~~~~~~
246 It is desireable to support shutting down the UPS. Usually (for
247 devices that follow the HID Power Device Class specification), this
248 requires sending the UPS two commands. One for shutting down the UPS
249 (with an 'offdelay') and one for restarting it (with an 'ondelay'),
250 where offdelay < ondelay. The two NUT commands for which this is
251 relevant, are 'shutdown.return' and 'shutdown.stayoff'.
253 Since the one-to-one mapping above doesn't allow sending two HID
254 commands to the UPS in response to sending one NUT command to the
255 driver, this is handled by the driver. In order to make this work,
256 you need to define the following four NUT values:
258 ups.delay.start (variable, R/W)
259 ups.delay.shutdown (variable, R/W)
260 load.off.delay (command)
261 load.on.delay (command)
263 If the UPS supports it, the following variables can be used to show
264 the countdown to start/shutdown:
266 ups.timer.start (variable, R/O)
267 ups.timer.shutdown (variable, R/O)
269 The `load.on` and `load.off` commands will be defined implicitly by
270 the driver (using a delay value of '0'). Define these commands
271 yourself, if your UPS requires a different value to switch on/off
272 the load without delay.
274 Note that the driver expects the `load.off.delay` and `load.on.delay`
275 to follow the HID Power Device Class specification, which means that
276 the `load.on.delay` command should NOT switch on the load in the
277 absence of mains power. If your UPS switches on the load regardless of
278 the mains status, DO NOT define this command. You probably want to
279 define the `shutdown.return` and/or `shutdown.stayoff` commands in
280 that case. Commands defined in the subdriver will take precedence over
281 the ones that are composed in the driver.
283 When running the driver with the '-k' flag, it will first attempt to
284 send a `shutdown.return` command and if that fails, will fallback to
287 ////////////////////////////////////////////////////////////////////////////////