1NUT configuration management with Augeas 2======================================== 3 4Introduction 5------------ 6 7Configuration has long been one of the two main NUT weaknesses. This is 8mostly due to the framework nature of NUT, and its many components and 9features, which make NUT configuration a very complex task. 10 11In order to address this point, NUT now provides configuration tools and 12manipulation abstraction, to anybody who want to manipulate NUT configuration, 13through Augeas lenses and modules. 14 15From link:http://augeas.net[Augeas homepage]: 16 17"Augeas is a configuration editing tool. It parses configuration files in their 18native formats and transforms them into a tree. Configuration changes are made 19by manipulating this tree and saving it back into native config files." 20 21In other words, Augeas is the dreamed Registry, with all the advantages 22(such as a uniform interface and tools), and the added bonus of being 23free/libre open source software and letting liberty on configuration file 24format. 25 26Requirements 27------------ 28 29To be able to use Augeas with NUT, you will need to install Augeas, 30and also the NUT provided lenses, which describe NUT configuration 31files format. 32 33Augeas 34~~~~~~ 35 36Having link:http://augeas.net[Augeas] installed. 37You will need at least version 0.5.1 (prior versions may work too, reports 38are welcome). 39 40As an example, on Debian and derivatives, do the following: 41 42 $ apt-get install augeas-lenses augeas-tools 43 44And optionally: 45 46 $ apt-get install libaugeas0 libaugeas-dev python-augeas 47 48On RedHat and derivatives, you have to install the packages 'augeas' and 49'augeas-libs'. 50 51[[augeas_user]] 52 53NUT lenses and modules for Augeas 54~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 55 56These are the *.aug files in the present directory. 57 58You can either install the files to the right location on your system, 59generally in '/usr/share/augeas/lenses/', or use these from NUT 60source directory ('nut/scripts/augeas'). The latter is to be preferred for 61the time being. 62 63 64Create a test sandbox 65--------------------- 66 67NOTE: for now, it's easier to include an existing /etc/nut/ directory. 68 69 $ export AUGEAS_ROOT=./augeas-sandbox 70 $ mkdir $AUGEAS_ROOT 71 $ sudo cp -pr /etc/nut $AUGEAS_ROOT 72 $ sudo chown -R $(id -nu):$(id -ng) $AUGEAS_ROOT 73 74 75Start testing and using 76----------------------- 77 78Augeas provides many tools and 79link:http://augeas.net/download.html[languages bindings] (Python, Perl, 80Java, PHP, Ruby, ...), still with the same simple logic. 81 82This chapter will only illustrate some of these. Refer to the language 83binding's help and link:http://augeas.net/docs/index.html[Augeas documentation] 84for more information. 85 86 87Shell 88~~~~~ 89 90Start an augeas shell using: 91 92 $ augtool -b 93 94NOTE: if you have not installed NUT lenses, add '-I/path/to/nut/scripts/augeas'. 95 96From there, you can perform different actions like: 97 98- list existing nut related files: 99 100 augtool> ls /files/etc/nut/ 101 nut.conf/ = (none) 102 upsd.users/ = (none) 103 upsmon.conf = (none) 104 ups.conf/ = (none) 105 upsd.conf/ = (none 106+ 107or using: 108+ 109 augtool> match /files/etc/nut/* 110 /files/etc/nut/nut.conf = (none) 111 /files/etc/nut/upsd.users = (none) 112 /files/etc/nut/upsmon.conf = (none) 113 /files/etc/nut/ups.conf = (none) 114 /files/etc/nut/upsd.conf = (none) 115 116NOTE: if you don't see anything, you may search for error messages by using: 117+ 118 augtool> ls /augeas/files/etc/nut/*/errors 119and 120 augtool> get /augeas/files/etc/nut/ups.conf/error/message 121 /augeas/files/etc/nut/ups.conf/error/message = Permission denied 122 123- create a new device entry (in ups.conf), called 'augtest': 124 125 augtool> set /files/etc/nut/ups.conf/augtest/driver dummy-ups 126 augtool> set /files/etc/nut/ups.conf/augtest/port auto 127 augtool> save 128 129- list the devices using the 'usbhid-ups' driver: 130 131 augtool> match /files/etc/nut/ups.conf/*/driver dummy-ups 132 133 134C 135~ 136 137A library is available for C programs, along with pkg-config support. 138 139You can get the compilation and link flags using the following code 140in your configure script or Makefile: 141 142 CFLAGS="`pkg-config --silence-errors --cflags augeas`" 143 LDFLAGS="`pkg-config --silence-errors --libs augeas`" 144 145Here is an code sample using this library for NUT configuration: 146 147-------------------------------------------------------------------------------- 148augeas *a = aug_init(NULL, NULL, AUG_NONE); 149ret = aug_match(a, "/files/etc/nut/*", &matches_p); 150ret = aug_set(a, "/files/etc/nut/ups.conf/augtest/driver", "dummy-ups"); 151ret = aug_set(a, "/files/etc/nut/ups.conf/augtest/port", "auto"); 152ret = aug_save(a); 153-------------------------------------------------------------------------------- 154 155Python 156~~~~~~ 157 158The `augeas` class abstracts access to the configuration files. 159 160 $ python 161 Python 2.5.1 (r251:54863, Apr 8 2008, 01:19:33) 162 [GCC 4.3.0 20080404 (Red Hat 4.3.0-6)] on linux2 163 Type "help", "copyright", "credits" or "license" for more information. 164 >>> import augeas 165 >>> a = augeas.augeas() 166 >>> a.match("/files/etc/nut/*") 167 ['/files/etc/nut/upsd.users', '/files/etc/nut/upsmon.conf', '/files/etc/nut/ups.conf', '/files/etc/nut/upsd.conf'] 168 >>> a.set("/files/etc/nut/ups.conf/augtest/driver", "dummy-ups") 169 True 170 >>> a.set("/files/etc/nut/ups.conf/augtest/port", "auto") 171 True 172 >>> a.save() 173 True 174 >>> 175 176 $ grep -A 2 augtest /etc/nut/ups.conf 177 [augtest] 178 driver=dummy-ups 179 port=auto 180 181 182Perl 183~~~~ 184 185The Perl binding is available through CPAN and packages. 186 187 use Config::Augeas; 188 189 my $aug = Config::Augeas->new( root => $aug_root ) ; 190 191 my @a = $aug->match("/files/etc/nut/*") ; 192 my $nb = $aug->count_match("/files/etc/nut/*") ; 193 194 $aug->set("/files/etc/nut/ups.conf/augtest/driver", "dummy-ups") ; 195 $aug->set("/files/etc/nut/ups.conf/augtest/port", "auto") ; 196 197 $aug->save ; 198 199 200Test the conformity testing module 201~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 202 203Existing configuration files can be tested for conformity. To do so, use: 204 205 $ augparse -I ./ ./test_nut.aug 206 207 208Complete configuration wizard example 209------------------------------------- 210 211Here is a Python example that generate a complete and usable standalone configuration: 212 213-------------------------------------------------------------------------------- 214import augeas 215 216device_name="dev1" 217driver_name="usbhid-ups" 218port_name="auto" 219 220a = augeas.augeas() 221 222# Generate nut.conf 223a.set("/files/etc/nut/nut.conf/MODE", "standalone") 224 225# Generate ups.conf 226# FIXME: chroot, driverpath? 227a.set(("/files/etc/nut/ups.conf/%s/driver" % device_name), driver_name) 228a.set(("/files/etc/nut/ups.conf/%s/port" % device_name), port_name) 229 230# Generate upsd.conf 231a.set("/files/etc/nut/upsd.conf/#comment[1]", "just to touch the file!") 232 233# Generate upsd.users 234user = "admin" 235a.set(("/files/etc/nut/upsd.users/%s/password" % user), "dummypass") 236a.set(("/files/etc/nut/upsd.users/%s/actions/SET" % user), "") 237# FIXME: instcmds lens should be fixed, as per the above rule 238a.set(("/files/etc/nut/upsd.users/%s/instcmds" % user), "ALL") 239 240monuser = "monuser" 241monpasswd = "******" 242a.set(("/files/etc/nut/upsd.users/%s/password" % monuser), monpasswd) 243a.set(("/files/etc/nut/upsd.users/%s/upsmon" % monuser), "primary") 244 245# Generate upsmon.conf 246a.set("/files/etc/nut/upsmon.conf/MONITOR/system/upsname", device_name) 247# Note: we prefer to omit localhost, not to be bound to a specific 248# entry in /etc/hosts, and thus be more generic 249#a.set("/files/etc/nut/upsmon.conf/MONITOR/system/hostname", "localhost") 250a.set("/files/etc/nut/upsmon.conf/MONITOR/powervalue", "1") 251a.set("/files/etc/nut/upsmon.conf/MONITOR/username", monuser) 252a.set("/files/etc/nut/upsmon.conf/MONITOR/password", monpasswd) 253a.set("/files/etc/nut/upsmon.conf/MONITOR/type", "primary") 254 255# FIXME: glitch on the generated content 256a.set("/files/etc/nut/upsmon.conf/SHUTDOWNCMD", "/sbin/shutdown -h +0") 257 258# save config 259a.save() 260a.close() 261-------------------------------------------------------------------------------- 262