2011-01-26 11:35:08 +02:00
|
|
|
NUT configuration management with Augeas
|
|
|
|
========================================
|
|
|
|
|
|
|
|
Introduction
|
|
|
|
------------
|
|
|
|
|
|
|
|
Configuration has long been one of the two main NUT weaknesses. This is
|
|
|
|
mostly due to the framework nature of NUT, and its many components and
|
|
|
|
features, which make NUT configuration a very complex task.
|
|
|
|
|
|
|
|
In order to address this point, NUT now provides configuration tools and
|
|
|
|
manipulation abstraction, to anybody who want to manipulate NUT configuration,
|
|
|
|
through Augeas lenses and modules.
|
|
|
|
|
|
|
|
From link:http://augeas.net[Augeas homepage]:
|
|
|
|
|
|
|
|
"Augeas is a configuration editing tool. It parses configuration files in their
|
|
|
|
native formats and transforms them into a tree. Configuration changes are made
|
|
|
|
by manipulating this tree and saving it back into native config files."
|
|
|
|
|
|
|
|
In other words, Augeas is the dreamed Registry, with all the advantages
|
|
|
|
(such as a uniform interface and tools), and the added bonus of being
|
|
|
|
free/libre open source software and letting liberty on configuration file
|
|
|
|
format.
|
|
|
|
|
|
|
|
Requirements
|
|
|
|
------------
|
|
|
|
|
|
|
|
To be able to use Augeas with NUT, you will need to install Augeas,
|
|
|
|
and also the NUT provided lenses, which describe NUT configuration
|
|
|
|
files format.
|
|
|
|
|
|
|
|
Augeas
|
|
|
|
~~~~~~
|
|
|
|
|
|
|
|
Having link:http://augeas.net[Augeas] installed.
|
|
|
|
You will need at least version 0.5.1 (prior versions may work too, reports
|
|
|
|
are welcome).
|
|
|
|
|
|
|
|
As an example, on Debian and derivatives, do the following:
|
|
|
|
|
|
|
|
$ apt-get install augeas-lenses augeas-tools
|
|
|
|
|
2016-07-18 03:11:41 +03:00
|
|
|
And optionally:
|
2011-01-26 11:35:08 +02:00
|
|
|
|
|
|
|
$ apt-get install libaugeas0 libaugeas-dev python-augeas
|
|
|
|
|
|
|
|
On RedHat and derivatives, you have to install the packages 'augeas' and
|
|
|
|
'augeas-libs'.
|
|
|
|
|
|
|
|
[[augeas_user]]
|
|
|
|
|
|
|
|
NUT lenses and modules for Augeas
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
These are the *.aug files in the present directory.
|
|
|
|
|
|
|
|
You can either install the files to the right location on your system,
|
|
|
|
generally in '/usr/share/augeas/lenses/', or use these from NUT
|
|
|
|
source directory ('nut/scripts/augeas'). The latter is to be prefered for
|
|
|
|
the time being.
|
|
|
|
|
|
|
|
|
|
|
|
Create a test sandbox
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
NOTE: for now, it's easier to include an existing /etc/nut/ directory.
|
|
|
|
|
|
|
|
$ export AUGEAS_ROOT=./augeas-sandbox
|
|
|
|
$ mkdir $AUGEAS_ROOT
|
|
|
|
$ sudo cp -pr /etc/nut $AUGEAS_ROOT
|
|
|
|
$ sudo chown -R $(id -nu):$(id -ng) $AUGEAS_ROOT
|
|
|
|
|
|
|
|
|
|
|
|
Start testing and using
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
Augeas provides many tools and
|
|
|
|
link:http://augeas.net/download.html[languages bindings] (Python, Perl,
|
|
|
|
Java, PHP, Ruby, ...), still with the same simple logic.
|
|
|
|
|
|
|
|
This chapter will only illustrate some of these. Refer to the language
|
|
|
|
binding's help and link:http://augeas.net/docs/index.html[Augeas documentation]
|
|
|
|
for more information.
|
|
|
|
|
|
|
|
|
|
|
|
Shell
|
|
|
|
~~~~~
|
|
|
|
|
|
|
|
Start an augeas shell using:
|
|
|
|
|
|
|
|
$ augtool -b
|
|
|
|
|
|
|
|
NOTE: if you have not installed NUT lenses, add '-I/path/to/nut/scripts/augeas'.
|
|
|
|
|
|
|
|
From there, you can perform different actions like:
|
|
|
|
|
|
|
|
- list existing nut related files:
|
|
|
|
|
|
|
|
augtool> ls /files/etc/nut/
|
|
|
|
nut.conf/ = (none)
|
|
|
|
upsd.users/ = (none)
|
|
|
|
upsmon.conf = (none)
|
|
|
|
ups.conf/ = (none)
|
|
|
|
upsd.conf/ = (none
|
|
|
|
+
|
|
|
|
or using:
|
|
|
|
+
|
|
|
|
augtool> match /files/etc/nut/*
|
|
|
|
/files/etc/nut/nut.conf = (none)
|
|
|
|
/files/etc/nut/upsd.users = (none)
|
|
|
|
/files/etc/nut/upsmon.conf = (none)
|
|
|
|
/files/etc/nut/ups.conf = (none)
|
|
|
|
/files/etc/nut/upsd.conf = (none)
|
|
|
|
|
|
|
|
NOTE: if you don't see anything, you may search for error messages by using:
|
|
|
|
+
|
|
|
|
augtool> ls /augeas/files/etc/nut/*/errors
|
|
|
|
and
|
|
|
|
augtool> get /augeas/files/etc/nut/ups.conf/error/message
|
|
|
|
/augeas/files/etc/nut/ups.conf/error/message = Permission denied
|
|
|
|
|
|
|
|
- create a new device entry (in ups.conf), called 'augtest':
|
|
|
|
|
|
|
|
augtool> set /files/etc/nut/ups.conf/augtest/driver dummy-ups
|
|
|
|
augtool> set /files/etc/nut/ups.conf/augtest/port auto
|
|
|
|
augtool> save
|
|
|
|
|
|
|
|
- list the devices using the 'usbhid-ups' driver:
|
|
|
|
|
|
|
|
augtool> match /files/etc/nut/ups.conf/*/driver dummy-ups
|
|
|
|
|
|
|
|
|
|
|
|
C
|
|
|
|
~
|
|
|
|
|
|
|
|
A library is available for C programs, along with pkg-config support.
|
|
|
|
|
|
|
|
You can get the compilation and link flags using the following code
|
|
|
|
in your configure script or Makefile:
|
|
|
|
|
|
|
|
CFLAGS="`pkg-config --silence-errors --cflags augeas`"
|
|
|
|
LDFLAGS="`pkg-config --silence-errors --libs augeas`"
|
|
|
|
|
|
|
|
Here is an code sample using this library for NUT configuration:
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
augeas *a = aug_init(NULL, NULL, AUG_NONE);
|
|
|
|
ret = aug_match(a, "/files/etc/nut/*", &matches_p);
|
|
|
|
ret = aug_set(a, "/files/etc/nut/ups.conf/augtest/driver", "dummy-ups");
|
|
|
|
ret = aug_set(a, "/files/etc/nut/ups.conf/augtest/port", "auto");
|
|
|
|
ret = aug_save(a);
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Python
|
|
|
|
~~~~~~
|
|
|
|
|
|
|
|
The `augeas` class abstracts access to the configuration files.
|
|
|
|
|
|
|
|
$ python
|
|
|
|
Python 2.5.1 (r251:54863, Apr 8 2008, 01:19:33)
|
|
|
|
[GCC 4.3.0 20080404 (Red Hat 4.3.0-6)] on linux2
|
|
|
|
Type "help", "copyright", "credits" or "license" for more information.
|
|
|
|
>>> import augeas
|
|
|
|
>>> a = augeas.augeas()
|
|
|
|
>>> a.match("/files/etc/nut/*")
|
|
|
|
['/files/etc/nut/upsd.users', '/files/etc/nut/upsmon.conf', '/files/etc/nut/ups.conf', '/files/etc/nut/upsd.conf']
|
|
|
|
>>> a.set("/files/etc/nut/ups.conf/augtest/driver", "dummy-ups")
|
|
|
|
True
|
|
|
|
>>> a.set("/files/etc/nut/ups.conf/augtest/port", "auto")
|
|
|
|
True
|
|
|
|
>>> a.save()
|
|
|
|
True
|
|
|
|
>>>
|
|
|
|
|
|
|
|
$ grep -A 2 augtest /etc/nut/ups.conf
|
|
|
|
[augtest]
|
|
|
|
driver=dummy-ups
|
|
|
|
port=auto
|
|
|
|
|
|
|
|
|
|
|
|
Perl
|
|
|
|
~~~~
|
|
|
|
|
|
|
|
The Perl binding is available through CPAN and packages.
|
|
|
|
|
|
|
|
use Config::Augeas;
|
|
|
|
|
|
|
|
my $aug = Config::Augeas->new( root => $aug_root ) ;
|
|
|
|
|
|
|
|
my @a = $aug->match("/files/etc/nut/*") ;
|
|
|
|
my $nb = $aug->count_match("/files/etc/nut/*") ;
|
|
|
|
|
|
|
|
$aug->set("/files/etc/nut/ups.conf/augtest/driver", "dummy-ups") ;
|
|
|
|
$aug->set("/files/etc/nut/ups.conf/augtest/port", "auto") ;
|
|
|
|
|
|
|
|
$aug->save ;
|
|
|
|
|
|
|
|
|
|
|
|
Test the conformity testing module
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Existing configuration files can be tested for conformity. To do so, use:
|
|
|
|
|
|
|
|
$ augparse -I ./ ./test_nut.aug
|
2011-09-29 21:14:46 +03:00
|
|
|
|
|
|
|
|
|
|
|
Complete configuration wizard example
|
|
|
|
-------------------------------------
|
|
|
|
|
|
|
|
Here is a Python example that generate a complete and usable standalone configuration:
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import augeas
|
|
|
|
|
|
|
|
device_name="dev1"
|
|
|
|
driver_name="usbhid-ups"
|
|
|
|
port_name="auto"
|
|
|
|
|
|
|
|
a = augeas.augeas()
|
|
|
|
|
|
|
|
# Generate nut.conf
|
|
|
|
a.set("/files/etc/nut/nut.conf/MODE", "standalone")
|
|
|
|
|
|
|
|
# Generate ups.conf
|
|
|
|
# FIXME: chroot, driverpath?
|
|
|
|
a.set(("/files/etc/nut/ups.conf/%s/driver" % device_name), driver_name)
|
|
|
|
a.set(("/files/etc/nut/ups.conf/%s/port" % device_name), port_name)
|
|
|
|
|
|
|
|
# Generate upsd.conf
|
|
|
|
a.set("/files/etc/nut/upsd.conf/#comment[1]", "just to touch the file!")
|
|
|
|
|
|
|
|
# Generate upsd.users
|
|
|
|
user = "admin"
|
|
|
|
a.set(("/files/etc/nut/upsd.users/%s/password" % user), "dummypass")
|
|
|
|
a.set(("/files/etc/nut/upsd.users/%s/actions/SET" % user), "")
|
|
|
|
# FIXME: instcmds lens should be fixed, as per the above rule
|
|
|
|
a.set(("/files/etc/nut/upsd.users/%s/instcmds" % user), "ALL")
|
|
|
|
|
|
|
|
monuser = "monuser"
|
|
|
|
monpasswd = "******"
|
|
|
|
a.set(("/files/etc/nut/upsd.users/%s/password" % monuser), monpasswd)
|
|
|
|
a.set(("/files/etc/nut/upsd.users/%s/upsmon" % monuser), "master")
|
|
|
|
|
|
|
|
# Generate upsmon.conf
|
|
|
|
a.set("/files/etc/nut/upsmon.conf/MONITOR/system/upsname", device_name)
|
|
|
|
# Note: we prefer to omit localhost, not to be bound to a specific
|
|
|
|
# entry in /etc/hosts, and thus be more generic
|
|
|
|
#a.set("/files/etc/nut/upsmon.conf/MONITOR/system/hostname", "localhost")
|
|
|
|
a.set("/files/etc/nut/upsmon.conf/MONITOR/powervalue", "1")
|
|
|
|
a.set("/files/etc/nut/upsmon.conf/MONITOR/username", monuser)
|
|
|
|
a.set("/files/etc/nut/upsmon.conf/MONITOR/password", monpasswd)
|
|
|
|
a.set("/files/etc/nut/upsmon.conf/MONITOR/type", "master")
|
|
|
|
|
|
|
|
# FIXME: glitch on the generated content
|
|
|
|
a.set("/files/etc/nut/upsmon.conf/SHUTDOWNCMD", "/sbin/shutdown -h +0")
|
|
|
|
|
|
|
|
# save config
|
|
|
|
a.save()
|
|
|
|
a.close()
|
|
|
|
--------------------------------------------------------------------------------
|