Chapter 16. Extending VDSM with Hooks

This chapter describes how to extend VDSM with event-driven hooks. Extending VDSM with hooks is an experimental technology, and this chapter is intended for experienced developers. Note that at this time hooks are not able to run on Red Hat Enterprise Virtualization Hypervisors, they must only be used on Red Hat Enterprise Linux hosts. By setting custom properties on virtual machines it is possible to pass additional parameters, specific to a given virtual machine, to the hook scripts.
VDSM
The VDSM service is used by the Red Hat Enterprise Virtualization Manager to manage Red Hat Enterprise Virtualization Hypervisors and Red Hat Enterprise Linux hosts. VDSM manages and monitors the host's storage, memory and network resources. It also co-ordinates virtual machine creation, statistics gathering, log collection and other host administration tasks. VDSM is run as a daemon on each hypervisor host managed by Red Hat Enterprise Virtualization Manager. It answers XML-RPC calls from clients. The Red Hat Enterprise Virtualization Manager functions as a VDSM client.
VDSM Hooks
VDSM is extensible via hooks. Hooks are scripts executed on the host when key events occur. When a supported event occurs VDSM runs any executable hook scripts in /usr/libexec/vdsm/hooks/nn_event-name/ on the host in alphanumeric order. By convention each hook script is assigned a two digit number, included at the front of the file name, to ensure that the order in which the scripts will be run in is clear. You are able to create hook scripts in any programming language, Python will however be used for the examples contained in this chapter.
Note that all scripts defined on the host for the event are executed. If you require that a given hook is only executed for a subset of the virtual machines which run on the host then you must ensure that the hook script itself handles this requirement by evaluating the Custom Properties associated with the virtual machine. This is further described in Section 16.1, “Environment”.

Warning VDSM hooks may cause data loss

VDSM hooks can interfere with the operation of Red Hat Enterprise Virtualization. A bug in a VDSM hook has the potential to cause virtual machine crashes and loss of data. VDSM hooks should be implemented with caution and tested rigorously. The Hooks API is new and subject to significant change in the future.

Table 16.1. Supported VDSM Events

Name Description
before_vm_start Before VM start.
after_vm_start After VM start.
before_vm_cont Before VM continue.
after_vm_cont After VM continue.
before_vm_pause Before VM pause.
after_vm_pause After VM pause.
before_vm_hibernate Before VM hibernate.
after_vm_hibernate After VM hibernate.
before_vm_dehibernate Before VM de-hibernate.
after_vm_dehibernate After VM de-hibernate.
before_vm_migrate_source Before VM migration, run on the source hypervisor host from which the migration is occurring.
after_vm_migrate_source After VM migration, run on the source hypervisor host from which the migration is occurring.
before_vm_migrate_destination Before VM migration, run on the destination hypervisor host to which the migration is occurring.
after_vm_migrate_destination After VM migration, run on the destination hypervisor host to which the migration is occurring.
after_vm_destroy After VM destruction.
before_vdsm_start Before VDSM is started on the hypervisor host. before_vdsm_start hooks are executed as the user root, and do not inherit the environment of the VDSM process.
after_vdsm_stop After VDSM is stopped on the hypervisor host. after_vdsm_stop hooks are executed as the user root, and do not inherit the environment of the VDSM process.

16.1. Environment

Most hook scripts are run as the vdsm user and inherit the environment of the VDSM process. The exceptions are hook scripts triggered by the before_vdsm_start and after_vdsm_stop events. Hook scripts triggered by these events run as the root user and do not inherit the environment of the VDSM process.

16.1.1. Domain XML

When hook scripts are started the _hook_domxml variable is appended to the environment. This variable contains the path of the libvirt domain XML representation of the relevant virtual machine. The libvirt domain XML format is used by VDSM to define virtual machines. Details on the libvirt domain XML format can be found at http://libvirt.org/formatdomain.html. The uuid of the virtual machine may be deduced from the domain XML, but it is also available as the environment variable vmId.

Important

The before_migration_destination and before_dehibernation hooks currently receive the XML of the domain from the source host. The XML of the domain at the destination will have various differences.

16.1.2. Custom Properties

Red Hat Enterprise Virtualization Manager also allows specification of custom properties for each virtual machine. Each of these properties is provided to hooks as an environment variable. This allows users to pass virtual machine dependent parameters to the hook scripts. Additionally hook scripts are able to use the presence, or absence, of a given custom property to determine whether they should execute to completion.
Defining Custom Properties
The custom properties that are accepted by the Red Hat Enterprise Virtualization Manager — and in turn passed to custom hooks — are defined using the configuration tool, rhevm-config. Run this command as the root user on the host where Red Hat Enterprise Virtualization Manager is installed.
The configuration key UserDefinedVMProperties is used to store the names of the custom properties supported. Regular expressions defining the valid values for each named custom property are also contained in this configuration key.
Where multiple custom properties are defined they are separated by a semi-colon. Note that when setting the configuration key any existing value it contained is overwritten. When combining new and existing custom properties it is necessary to include all of the custom properties in the command used to set the key's value.
Once the configuration key has been updated the jbossas service must be restarted for it to take effect.

Example 16.1. Defining smartcard Custom Property

  1. Check the existing custom properties defined by the UserDefinedVMProperties configuration key using rhevm-config -g UserDefinedVMProperties.
    In this case the custom property memory is already defined. The regular expression ^[0-9]+$ ensures that the custom property will only ever contain numeric characters.
    # rhevm-config -g UserDefinedVMProperties
    UserDefinedVMProperties :  version: general
    UserDefinedVMProperties :  version: 2.2
    UserDefinedVMProperties : memory=^[0-9]+$ version: 3.0
    
  2. As the memory custom property is already defined in the UserDefinedVMProperties configuration key the new custom property must be appended to it. The additional custom property, smartcard, is added to the configuration key's value. The new custom property is able to hold a value of true or false.
    # rhevm-config -s UserDefinedVMProperties='memory=^[0-9]+$;smartcard=^(true|false)$' --cver=3.0
    
  3. Verify that the custom properties defined by the UserDefinedVMProperties configuration key now match your expectations.
    # rhevm-config -g UserDefinedVMProperties
    UserDefinedVMProperties :  version: general
    UserDefinedVMProperties :  version: 2.2
    UserDefinedVMProperties : memory=^[0-9]+$;smartcard=^(true|false)$ version: 3.0
    
  4. Finally, the jbossas service must be restarted for the configuration change to take effect.
    # service restart jbossas

Setting Custom Properties
Once custom properties are defined to Red Hat Enterprise Virtualization Manager you are able to begin setting them on virtual machines. Custom properties are set on the Custom Properties tab of the New Server Virtual Machine, New Desktop Virtual Machine, Edit Server Virtual Machine, and Edit Desktop Virtual Machine dialog boxes in the Administration Portal.
You are also able to set custom properties from the Run Once dialog box. Custom properties set from the Run Once dialog box will only apply to the virtual machine until it is next shutdown.
The Custom Properties must be provided as key to value pairs of the form key=value, where key is the name of the custom property and value is the value which it should be set to for this virtual machine. Where multiple custom properties are being provided they must be separated by a semi-colon, as illustrated in the example below.
Dialog box illustrating the use of the Custom Properties field.

Figure 16.1. Custom Properties Field


Evaluating Custom Properties in Hooks
Each key set in the Custom Properties field for a virtual machine is appended as an environment variable when calling hook scripts. Although the regular expressions used to validate the Custom Properties field provide some protection you should ensure that your scripts also validate that the inputs provided match their expectations.

Example 16.2. Evaluating Custom Properties

This short Python example checks for the existence of the custom property key1. If the custom property is set then the value is printed to standard error. If the custom property is not set then no action is taken.
#!/usr/bin/python

import os
import sys

if os.environ.has_key('key1'):
	sys.stderr.write('key1 value was : %s\n' % os.environ['key1'])
else:
    sys.exit(0)

16.1.3. Hooking module

VDSM ships with a Python hooking module, providing helper functions for VDSM hook scripts. This module is provided as an example, and is only relevant to VDSM hooks written in Python.
The hooking module supports reading of a virtual machine's libvirt XML into a DOM object. Hook scripts can then use Python's built in xml.dom library (http://docs.python.org/release/2.6/library/xml.dom.html) to manipulate the object.
The modified object can then be saved back to libvirt XML using the hooking module. The hooking module provides the following functions to support hook development:

Table 16.2. Hooking module functions

Name Argument Description
tobool string Converts a string "true" or "false" to a Boolean value
read_domxml - Reads the virtual machine's libvirt XML into a DOM object
write_domxml DOM object Writes the virtual machine's libvirt XML from a DOM object