lcfg-libvirt

The last few months, when I was getting free time off other projects, I was working on a new LCFG component, lcfg-libvirt. The main idea behind lcfg-libvirt is not just to manage libVirt itself, but use libVirt via the component to manage multiple virtualisation platforms without the need to use multiple components.

At first stage, the goal was to generalise the resources that could be used by both Xen and KVM guests, as well as other platform candidates that are supported by libVirt.

The second stage was to migrate all the existing lcfg-xen functionality into the component, using the new resources and manage the Xen guests via libVirt.

At the third stage, KVM support was added at the same level as the pre-existing Xen support. At this stage, network management via virsh was implemented as well. In order to get networking sorted I had to create a new patch for the lcfg-network component in order to support bridge interfaces at an OS level.

The man page is still missing. The lcfg-xen(8) will be used as the basis for this as well.

The functionality so far can be summarised as bellow:

– Support for Xen, hardware virtualised, guests (migrated from lcfg-xen).
– Support for Xen, paravirtualised, guests (migrated from lcfg-xen).
– Support for Xen specific networking (migrated from lcfg-xen).
– Support for KVM guests for both Intel and AMD processors.
– Support for KVM specific networking.
– Guest cloning for both Xen and KVM guests (migrated from lcfg-xen).
– Support for NAT, Bridge and Routed interfaces for both Xen and KVM.
– Use of virsh to manage guests and generic networking.

KVM guest example:

!libvirt.hosttype               mSET(kvm)

!libvirt.vms    mADD(pe2900x1)

!libvirt.name_pe2900x1                  mSET(pe2900x1)
!libvirt.type_pe2900x1                  mSET(hvm)
!libvirt.uuid_pe2900x1                  mSET(56bcea35-a598-4ce8-97f1-02cba34e3451)
!libvirt.disks_pe2900x1                 mADD(root test)
!libvirt.diskname_pe2900x1_root         mSET(pe2900x1)
!libvirt.disksize_pe2900x1_root         mSET(32)
!libvirt.diskpath_pe2900x1_root         mSET(/guests)
!libvirt.diskname_pe2900x1_test         mSET(test)
!libvirt.disksize_pe2900x1_test         mSET(10)
!libvirt.diskpath_pe2900x1_test         mSET(/guests)
!libvirt.boot_pe2900x1                  mSET(no)
!libvirt.opts_pe2900x1                  mADD(vnc monitor)
!libvirt.optvalue_pe2900x1_vnc          mSET(1)
!libvirt.optvalue_pe2900x1_monitor      mSET(pty)
!libvirt.nethost_pe2900x1               mADD(vif1 vif2)
!libvirt.hostmac_pe2900x1_vif1          mSET(12:28:aa:02:1e:4d)
!libvirt.bridge_pe2900x1_vif1           mSET(br0)
!libvirt.netmode_pe2900x1_vif1          mSET(bridge)
!libvirt.hostmac_pe2900x1_vif2          mSET(23:12:cb:af:1a:cf)
!libvirt.bridge_pe2900x1_vif2           mSET(default)
!libvirt.netmode_pe2900x1_vif2          mSET(network)

Xen guest example:

!libvirt.hosttype               mSET(xen)

!libvirt.vms    mADD(pe2900x1)

!libvirt.name_pe2900x1                  mSET(pe2900x1)
!libvirt.type_pe2900x1                  mSET(hvm)
!libvirt.uuid_pe2900x1                  mSET(56bcea35-a598-4ce8-89f87-02cba34e7205)
!libvirt.disks_pe2900x1                 mADD(root test)
!libvirt.diskname_pe2900x1_root         mSET(pe2900x1)
!libvirt.disksize_pe2900x1_root         mSET(32)
!libvirt.diskpath_pe2900x1_root         mSET(/guests)
!libvirt.diskname_pe2900x1_test         mSET(test)
!libvirt.disksize_pe2900x1_test         mSET(10)
!libvirt.diskpath_pe2900x1_test         mSET(/guests)
!libvirt.boot_pe2900x1                  mSET(no)
!libvirt.nethost_pe2900x1               mADD(vif1)
!libvirt.hostmac_pe2900x1_vif1          mSET(12:28:ad:12:ac:2a)
!libvirt.bridge_pe2900x1_vif1           mSET(xenbr0)
!libvirt.script_pe2900x1_vif1           mSET(vif-bridge)
!libvirt.netmode_pe2900x1_vif1          mSET(bridge)

Network configuration example:

!libvirt.networking             mADD(routed)
!libvirt.nettype_routed         mSET(interface)
!libvirt.netname_routed         mSET(routed)
!libvirt.netuuid_routed         mSET(56bcea35-a598-4ce8-97f1-02acd24s6985)
!libvirt.bridgename_routed      mSET(virbr9)
!libvirt.mode_routed            mSET(route)
!libvirt.modedev_routed         mSET(eth0)
!libvirt.ipaddr_routed          mSET(192.168.1.0)
!libvirt.netmask_routed         mSET(255.255.255.0)
!libvirt.dhcpstart_routed       mSET(192.168.1.1)
!libvirt.dhcpend_routed         mSET(192.168.1.254)
!libvirt.nethost_routed         mSET(host1 host2)
!libvirt.hostname_routed_host1  mSET(test)
!libvirt.hostmac_routed_host1   mSET(00:1E:C9:53:29:AD)
!libvirt.hostip_routed_host1    mSET(1.1.1.1)
!libvirt.hostname_routed_host2  mSET(test2)
!libvirt.hostmac_routed_host2   mSET(00:1F:B9:65:12:AB)
!libvirt.hostip_routed_host2    mSET(2.2.2.2)

Source code available on LCFG SVN. You’ll need an Informatics iFriend account to see the contents. RPMs should follow sooner or later.

lcfg-network patch

The existing version of lcfg-network component that manages the networking at an OS level, general and very briefly that means the scripts under /etc/sysconfig/network-scripts/ as well as /etc/sysconfig/network and /etc/hosts, lacks of support for bridge interfaces. The following patch adds support for such usage.

network.cin.patch (script)
network.def.patch (resources)

Two new resources have been defined:

type
This resource can be used to define the type of the interface.  For example,
defining a bridge interface as "type"_<interface>, then that should be set to "Bridge".

bridge
This resource can be used by the main interface in case it is bridged.  For instance,
if eth0 is bridged over br0, then "bridge"_<interface> should be set to "br0".

That would look like this:

!network.interfaces     mADD(eth0 br0)
!network.hwaddr_eth0    mSET(00:12:11:22:26:2B)
!network.bridge_eth0    br0
!network.ipaddr_br0     DHCP
!network.type_br0       Bridge

The official RPM hasn’t still be generated.

Without the use of the patch, the workaround of configuring a bridge interface is via the file component. You’ll need something like the following in your machine’s profile:

!network.interfaces     mREMOVE(eth0)

!file.files             mADD(eth0)
file.file_eth0          /etc/sysconfig/network-scripts/ifcfg-eth0
file.type_eth0          literal
file.mode_eth0          0644
!file.tmpl_eth0         mSET(DEVICE=eth0\nHWADDR=XX:XX:XX:XX:XX:XX\nONBOOT=yes\nBRIDGE=br0)

!file.files             mADD(br0)
file.file_br0           /etc/sysconfig/network-scripts/ifcfg-br0
file.type_br0           literal
file.mode_br0           0644
!file.tmpl_br0          mSET(DEVICE=br0\nTYPE=Bridge\nBOOTPROTO=dhcp\nONBOOT=yes)

Airport charges

From one of my recent flights, getting from Edinburgh to Athens with a corresponding flight in Amsterdam. All operated by KLM. I was aware of a number of additional charges but not as many as those displayed in the detailed price specification.

Funniest one the “Netherlands noise isolation charge”. I think there should be a “discount” for Greek passport holders as the Dutch passport control takes rather long unlike other EU passport holders… Perhaps something like “Netherlands passport control annoyance: -£10”.

GlobusToolkit scripts

Three basic scripts for WS-GRAM, GSI-SSH and GridFTP that can make life with Globus Toolkit a bit easier.

WS-GRAM

#!/bin/bash

HOSTNAME=`hostname`
VERSION=4.2.1

if [ "$1" == "start" ]; then

   if [ "$USER" == "globus" ]; then
     export GLOBUS_LOCATION=/usr/local/globus-$VERSION/
     export LD_LIBRARY_PATH=/usr/local/globus-$VERSION/lib
     export GLOBUS_HOSTNAME=$HOSTNAME

     cd $GLOBUS_LOCATION
     ./bin/globus-start-container &
     PID=`ps aux | grep DGLOBUS | grep -v grep | awk {'print $2'}`
     echo "WS-GRAM started with PID $PID"
   else
     echo "Only globus user can start the WS-GRAM service"
     exit 1;
   fi

elif [ "$1" == "stop" ]; then

   if [ "$USERID" == "globus" ] || [ $UID -eq 0 ]; then
     PID=`ps aux | grep DGLOBUS | grep -v grep | awk {'print $2'}`
     kill -9 $PID
     echo "WS-GRAM stopped"
   else
     echo "Only user globus and root can stop WS-GRAM"
     exit 1;
   fi

fi

GSI-SSH

#!/bin/bash

HOSTNAME=`hostname`
VERSION=4.2.1

if [ "$1" == "start" ]; then

   if [ $UID -eq 0 ]; then
     export GLOBUS_LOCATION=/usr/local/globus-$VERSION/
     export LD_LIBRARY_PATH=/usr/local/globus-$VERSION/lib
     export GLOBUS_TCP_PORT_RANGE=20000,25000
     export GLOBUS_HOSTNAME=$HOSTNAME
     export GRID_SECURITY_DIR=/etc/grid-security/
     export X509_USER_KEY=/etc/grid-security/hostkey.pem
     export X509_USER_CERT=/etc/grid-security/hostcert.pem
     export X509_CERT_DIR=/etc/grid-security/certificates
     export GRIDMAP=/etc/grid-security/grid-mapfile

     $GLOBUS_LOCATION/sbin/sshd &
     PID=`ps u | grep $GLOBUS_LOCATION/sbin/sshd | grep -v grep | awk {'print $2 '}`
     echo "GSISSH started with PID $PID"
   else
     echo "Only root can start GSISSH service"
     exit 1;
   fi

elif [ "$1" == "stop" ]; then

   if [ $UID -eq 0 ]; then
     PID=`ps aux | grep globus | grep sshd | grep -v grep | awk {'print $2 '}`
     kill -9 $PID
     echo "GSISSH stopped"
   else
     echo "Only root can stop GSISSH"
     exit 1;
   fi

fi

GridFTP

#!/bin/bash

HOSTNAME=`hostname`
VERSION=4.2.1

if [ "$1" == "start" ]; then

   if [ $UID -eq 0 ]; then
     export GLOBUS_LOCATION=/usr/local/globus-$VERSION/
     export LD_LIBRARY_PATH=/usr/local/globus-$VERSION/lib
     export GLOBUS_TCP_PORT_RANGE=20000,25000
     export GLOBUS_HOSTNAME=$HOSTNAME
     export GRID_SECURITY_DIR=/etc/grid-security/
     export X509_USER_KEY=/etc/grid-security/hostkey.pem
     export X509_USER_CERT=/etc/grid-security/hostcert.pem
     export X509_CERT_DIR=/etc/grid-security/certificates
     export GRIDMAP=/etc/grid-security/grid-mapfile
     export GLOBUS_CALLBACK_POLLING_THREADS=1

     $GLOBUS_LOCATION/sbin/globus-gridftp-server -p 2811 -d 255 -l $GLOBUS_LOCATION/var/gridftp.log \
     -log-transfer $GLOBUS_LOCATION/var/gridftp-transfers.log -hostname $GLOBUS_HOSTNAME &
     PID=`ps aux | grep globus-gridftp-server | grep -v grep | awk {'print $2 '}`
     echo "GridFTP started with PID $PID"
   else
     echo "Only root can start GridFTP service"
     exit 1;
   fi

elif [ "$1" == "stop" ]; then

   if [ $UID -eq 0 ]; then
     PID=`ps aux | grep globus-gridftp-server | grep -v grep | awk {'print $2 '}`
     kill -9 $PID
     echo "GridFTP stopped"
   else
     echo "Only root can stop GridFTP"
     exit 1;
   fi

fi

You could of course combine them all together in a single script but I’d rather prefer to keep them separate and “clean”, executing them depending on what services need to run/stop.