Contextualizing Virtual Machines 3.8
The only requirement for OpenNebula Virtual Machine guests is that they need to be able to configure their network. The easiest way to accomplish this is deploying a Virtual Router and DHCP server inside each Virtual Network.
Alternatively, the OS can be contextualized to be able to:
This guide describes how to install and use the generic contextualization.
When OpenNebula assigns an IP address to a network interface, the MAC address is set to MAC_PREFFIX:IP. This way the VM can know the assigned IP without an external DHCP server. For example, with the default mac prefix 02:00:
IP = 192.169.0.118 MAC = 02:00:c0:a9:00:76
To configure other networking parameters, like the gateway or the network mask, OpenNebula provides a generic contextualization mechanism. The method we provide to present configuration parameters to a newly started virtual machine is using an ISO image (OVF recommendation). This method is network agnostic, making it suitable to configure network interfaces. In the VM description file you can specify the contents of the ISO file (files and directories), set the device where the ISO image will be accessible from, and specify the configuration parameters that will be written to a file for later use inside the virtual machine.
In this image we see a Virtual Machine with two associated disks. The Disk Image holds the Operating System. The ISO image is dynamically created by OpenNebula, and contains the contextualization for that VM:
context.sh
: file that contains configuration variables, filled by OpenNebula with the parameters specified in the VM Templateinit.sh
: script called by the VM at start time, if it exists
The other files, certificates
and service.conf
are shown as an example of how any files can be included in the context ISO. They could contain files needed by the init.sh script
:
FILES
attribute within CONTEXT
is only allowed to OpenNebula users within the oneadmin group.
To enable a Virtual Machine guest to use the contextualization ISO, it needs a series of scripts that will be executed at startup.
You can use the images available in the Marketplace, that are already prepared, or prepare your own images.
There are two packages available:
If your distribution is not supported, see the Generating Custom Contextualization Packages section below to learn how to customize these packages or port them to other distributions.
After the installation is done, the VM on start will configure the network using the mac address generated by OpenNebula. They will also try to mount the cdrom context image from /dev/cdrom
and if init.sh
is found it will be executed.
The OpenNebula community has contributed scripts to contextualize Windows VMs. You can find more information in this blog post, and download the scripts from the IEETA wiki.
The VM Template contains a CONTEXT section where you can put arbitrary attributes, or reference other resource's template. These attributes will be written in the context.sh file.
There are some predefined attributes that the contextualization scripts will make use of:
Attribute | Description |
---|---|
<DEV>_IP | IP assigned to the interface |
<DEV>_NETWORK | Interface network |
<DEV>_MASK | Interface net mask |
<DEV>_GATEWAY | Interface gateway |
<DEV>_DNS | DNS servers for the network |
DNS | main DNS server for the machine |
SSH_PUBLIC_KEY | public ssh key added to root's authorized_keys |
Let's see a brief example. Given these two Virtual Networks:
Public:
NAME = public
NETWORK_ADDRESS = 130.10.0.0
NETWORK_MASK = 255.255.255.0
GATEWAY = 130.10.0.1
DNS = "8.8.8.8 8.8.4.4"
Private:
NAME = private NETWORK_ADDRESS = 10.0.0.0 NETWORK_MASK = 255.255.0.0
We can configure both network interfaces adding this context section to the VM template:
NIC = [ NETWORK = "public"] NIC = [ NETWORK = "private"] CONTEXT = [ ETH0_IP = "$NIC[IP, NETWORK=\"public\"]", ETH0_NETWORK = "$NETWORK[NETWORK, NETWORK=\"public\"]", ETH0_MASK = "$NETWORK[MASK, NETWORK=\"public\"]", ETH0_GATEWAY = "$NETWORK[GATEWAY, NETWORK=\"public\"]", ETH0_DNS = "$NETWORK[DNS, NETWORK=\"public\"]", ETH1_IP = "$NIC[IP, NETWORK=\"private\"]", ETH1_NETWORK = "$NETWORK[NETWORK, NETWORK=\"private\"]", ETH1_MASK = "$NETWORK[MASK, NETWORK=\"private\"]", SSH_PUBLIC_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+vPFFwem49zcepQxsyO51YMSpuywwt6GazgpJe9vQzw3BA97tFrU5zABDLV6GHnI0/ARqsXRX1mWGwOlZkVBl4yhGSK9xSnzBPXqmKdb4TluVgV5u7R5ZjmVGjCYyYVaK7BtIEx3ZQGMbLQ6Av3IFND+EEzf04NeSJYcg9LA3lKIueLHNED1x/6e7uoNW2/VvNhKK5Ajt56yupRS9mnWTjZUM9cTvlhp/Ss1T10iQ51XEVTQfS2VM2y0ZLdfY5nivIIvj5ooGLaYfv8L4VY57zTKBafyWyRZk1PugMdGHxycEh8ek8VZ3wUgltnK+US3rYUTkX9jj+Km/VGhDRehp user@host" ]
Remember to change the name of the network in the context section. If you add more that one interface to a Virtual Machine you can add the same parameters changing ETH0 to ETH1, ETH2, etc.
You can also add an `SSH_PUBLIC_KEY` parameter to the context to add an SSH public key to the root's `authorized_keys` file.
Now you are ready to run the Virtual Machine.
In the VM template you can tell OpenNebula to create a contextualization image and to fill it with values using CONTEXT
parameter. For example:
CONTEXT = [ hostname = "MAINHOST", ip_private = "$NIC[IP, NETWORK=\"public net\"]", dns = "$NETWORK[DNS, NETWORK_ID=0]", root_pass = "$IMAGE[ROOT_PASS, IMAGE_ID=3]", ip_gen = "10.0.0.$VMID", files = "/service/init.sh /service/certificates.$UID /service/service.conf" ]
Variables inside CONTEXT section will be added to context.sh
file inside the contextualization image. These variables can be specified in three different ways:
hostname = "MAINHOST"
$<template_variable>
: any single value variable of the VM template, like for example:\\ip_gen = "10.0.0.$VMID"
$<template_variable>[<attribute>]
: Any single value contained in a multiple value variable in the VM template, like for example:ip_private = $NIC[IP]
$<template_variable>[<attribute>, <attribute2>=<value2>]
: Any single value contained in a multiple value variable in the VM template, setting one attribute to discern between multiple variables called the same way, like for example:ip_public = "$NIC[IP, NETWORK=\"Public\"]"
. You can use any of the attributes defined in the variable, NIC in the previous example.
$NETWORK[<vnet_attribute>, <NETWORK_ID|NETWORK>=<vnet_id|vnet_name>]
: Any single value variable in the Virtual Network template, like for example:dns = "$NETWORK[DNS, NETWORK_ID=3]"
Note that the network MUST be in used by any of the NICs defined in the template. The vnet_attribute can be TEMPLATE
to include the whole vnet template in XML (base64 encoded).
$IMAGE[<image_attribute>, <IMAGE_ID|IMAGE>=<img_id|img_name>]
: Any single value variable in the Image template, like for example:root = "$IMAGE[ROOT_PASS, IMAGE_ID=0]"
Note that the image MUST be in used by any of the DISKs defined in the template. The image_attribute can be TEMPLATE
to include the whole image template in XML (base64 encoded).
$USER[<user_attribute>]
: Any single value variable in the user (owner of the VM) template, like for example:ssh_key = "$USER[SSH_KEY]"
The user_attribute can be TEMPLATE
to include the whole user template in XML (base64 encoded).
$UID
, the uid of the VM owner$TEMPLATE
, the whole template in XML format and encoded in base64The file generated will be something like this:
# Context variables generated by OpenNebula hostname="MAINHOST" ip_private="192.168.0.5" dns="192.168.4.9" ip_gen="10.0.0.85" files="/service/init.sh /service/certificates.5 /service/service.conf" target="sdb" root="13.0"
Some of the variables have special meanings, but none of them are mandatory:
Attribute | Description |
---|---|
files | Files and directories that will be included in the contextualization image |
target | device where the contextualization image will be available to the VM instance. Please note that the proper device mapping may depend on the guest OS, e.g. ubuntu VMs should use hd* as the target device |
Network configuration is a script located in /etc/one-context.d/00-network
. Any file located in that directory will be executed on start, in alphabetical order. This way we can add any script to configure or start processes on boot. For example, we can have a script that populates authorized_keys file using a variable in the context.sh. Remember that those variables are exported to the environment and will be easily accessible by the scripts:
#!/bin/bash echo "$SSH_PUBLIC_KEY" > /root/.ssh/authorized_keys
OpenNebula source code comes with the scripts and the files needed to generate contextualization packages. This way you can also generate custom packages tweaking the scripts that will go inside your images or adding new scripts that will perform other duties.
The files are located in share/scripts/context-packages
:
base
: files that will be in all the packages. Right now it contains empty udev
rules and the init script that will be executed on startup.base_<type>
: files specific for linux distributions. It contains the contextualization scripts for the network and comes in rpm
and deb
flavors. You can add here your own contextualization scripts and they will be added to the package when you run the generation script.generate.sh
: The script that generates the packages.postinstall
: This script will be executed after the package installation and will clean the network and udev
configuration. It will also add the init script to the started services on boot.To generate the packages you will need:
You can also give to the generation script some parameters using env variables to generate the packages. For example, to generate an rpm
package you will execute:
<xterm> $ PACKAGE_TYPE=rpm ./generate.sh </xterm>
These are the default values of the parameters, but you can change any of them the same way we did for PACKAGE_TYPE
:
VERSION=3.7.80 MAINTAINER=C12G Labs <support@c12g.com> LICENSE=Apache PACKAGE_NAME=one-context VENDOR=C12G Labs DESCRIPTION=" This package prepares a VM image for OpenNebula: * Disables udev net and cd persistent rules * Deletes udev net and cd persistent rules * Unconfigures the network * Adds OpenNebula contextualization scripts to startup To get support use the OpenNebula mailing list: http://opennebula.org/community:mailinglists " PACKAGE_TYPE=deb URL=http://opennebula.org
For more information check the README.md
file from that directory.