Extending OpenNebula with hooks

Action on the Hook

Following Up on Events

The basic principle is, if an OpenNebula user wants to know about changes on a virtual machine, a host, the configured networks, users, groups, or images, they can add their own scripts to the execution sequence. You store your tools in the /var/lib/one/remotes/hooks directory (for Debian, /var/lib/opennebula/remotes/hooks).

To define the events for which you need a response, the cloud administrator identifies the triggering object and event in Table 1 or Table 2 and enters it in /etc/one/oned.conf. For example, Listing 1 registers the shell script from Listing 2 to measure VM uptimes.

Table 1

Virtual Machine Events

Event When It Occurs
CREATE After OpenNebula has created a new VM
RUNNING Once the VM is actually running
SHUTDOWN After someone has terminated the VM
STOP Once someone has stopped the VM or OpenNebula is migrating a VM from one host to another
DONE After a VM has been permanently stopped
UNKNOWN When a VM changes to an unknown state
FAILED When a VM changes to a failed state
CUSTOM When a user-definable event occurs

Table 2

Events for Other Objects

Event When It Occurs
Host
CREATE After OpenNebula adds a host to its management system
ERROR When a VM detects an error condition
DISABLE When a host leaves the cluster
Network, User, Group, or Image
CREATE When someone creates the object
REMOVE When someone removes the object

Listing 1

Excerpt from /etc/one/oned.conf

01 VM_HOOK = [
02     name      = "vm_switchon",
03     on        = "RUNNING",
04     command   = "account.sh",
05     arguments = "on $ID" ]
06
07 VM_HOOK = [
08     name      = "vm_switchoff",
09     on        = "STOP",
10     command   = "account.sh",
11     arguments = "off $ID" ]
12 [...]

Listing 2

/var/lib/one/remotes/hooks/acccount.sh

01 #!/bin/bash
02
03 ACCOUNTING=/var/log/one/accounting.log
04
05 case "$1" in
06     "on"|"off")
07         mode=$1
08         shift
09         ;;
10      *)
11         echo "$0 error: wrong mode." >&2
12         exit 1
13         ;;
14 esac
15
16 if [ "$1" = "" ]
17 then
18     echo "$0 error: ID missing." >&2
19 fi
20
21 id=$1
22 shift
23
24 echo "$id $(date +%s) $mode" >> $ACCOUNTING

The VM_HOOK construct can appear more than once in the configuration. The on parameter defines the event to which OpenNebula responds (Listing 1, lines 3 and 9). The command entries specify the script to be called; arguments defines a string containing its call parameters. As connoisseurs will immediately see from the syntax, the IaaS management system itself is written in Ruby, but in terms of scripting languages, admins have a choice.

The shell script in Listing 2 checks (lines 5 to 9) for a running VM and then (in line 24) records the Unix epoch timestamp, along with the VM ID, in a configurable logfile. With an Awk script that reads logfiles and parses values, you could easily discover the total uptime of each VM and pass the results on to billing software, a department, or a customer of the IaaS cloud, for example.

The $TEMPLATE Variable

The example passes parameters only in a very simple way. To discover more information about the affected resources, users can pass the content of the $TEMPLATE variable to the script. It uses a kind of XML dialect to store a wide variety of details about the VM, the network, or the storage system. To avoid having to line up the big guns in the form of an external XML parser, the developers provide a tool that divides the content into handy key-value pairs and filters the results. For example, the following bash snippet:

X=/var/lib/one/remotes/datastore/xpath.rb
mem=$($X -b $template HOST_SHARE/MAX_MEM)

returns the contents of the <HOST_SHARE><MAX_MEM> container below the root node. This is the field to which OpenNebula sends the value for total available memory on the virtualization host; Listing 3 shows an example with a number of values.

Listing 3

Content of the $TEMPLATE Variable

01 <HOST>
02   <ID>1</ID>
03   <NAME>one-sandbox</NAME>
04   <STATE>2</STATE>
05   <IM_MAD>kvm</IM_MAD>
06   <VM_MAD>qemu</VM_MAD>
07   <VN_MAD>dummy</VN_MAD>
08   <LAST_MON_TIME>1377716985</LAST_MON_TIME>
09   <CLUSTER_ID>-1</CLUSTER_ID>
10   <CLUSTER/>
11   <HOST_SHARE>
12     <DISK_USAGE>0</DISK_USAGE>
13     <MEM_USAGE>65536</MEM_USAGE>
14     <CPU_USAGE>10</CPU_USAGE>
15     <MAX_DISK>0</MAX_DISK>
16     <MAX_MEM>502568</MAX_MEM>
17     <MAX_CPU>100</MAX_CPU>
18     <FREE_DISK>0</FREE_DISK>
19     <FREE_MEM>259512</FREE_MEM>
20     <FREE_CPU>87</FREE_CPU>
21     <USED_DISK>0</USED_DISK>
22     <USED_MEM>243056</USED_MEM>
23     <USED_CPU>12</USED_CPU>
24     <RUNNING_VMS>1</RUNNING_VMS>
25   </HOST_SHARE>
26   <VMS>
27     <ID>16</ID>
28   </VMS>
29   <TEMPLATE>
30     <ARCH><![CDATA[x86_64]]></ARCH>
31     [...]
32   </TEMPLATE>
33 </HOST>

Monitoring as the Main Application

This simple interface provides a variety of options: If you are prepared to take a detour, in the form of polling logfiles or status files, you can tie in an existing availability monitoring system like Nagios or Zabbix. Alternatively, OpenNebula itself includes a simple performance monitoring system in the form of Ganglia [10] that lets the system administrator keep an eye on important system parameters, such as CPU load or free memory.

If you hook into the CREATE event of a VM, you can install the monitoring agent software via configuration management, or you can roll out a complete application using a continuous integration trigger. Puppet, Chef, and Jenkins offer interfaces for this, and administrators can control them using wget or curl.

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs



Support Our Work

ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.

Learn More”>
	</a>

<hr>		    
			</div>
		    		</div>

		<div class=