261 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			261 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
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
 | 
						|
 | 
						|
And optionaly:
 | 
						|
 | 
						|
	$ 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
 | 
						|
 | 
						|
 | 
						|
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()
 | 
						|
--------------------------------------------------------------------------------
 |