velocity templates - RENCI-NRIG/orca5 GitHub Wiki

Overview of post-boot scripts

A post-boot script can be added to any node within a slice. This script can be written in any language that can be interpreted by the compute node (that said, the most common script language in use is shell or Bash). The script is executed immediately after boot is complete. Prior to execution these scripts are processed by a Velocity template engine inside ORCA that performs macro substitutions and allows the script to reference entities within the slice (virtual machines, network links, etc.) as objects. In addition, Velocity is a Turing-complete language suitable for code auto-generation using macros like #foreach and #if. This represents a rich 'network scripting' capability within substrates running ORCA.

This document explains the use of the templating features in post-boot scripts. Post-boot scripts can be specified natively in Flukes, or as [wiki:orca-and-rspec RSpec extension].

Details

For added functionality, ORCA uses velocity templates to create the scripts. See the user's guide for details about Velocity.

ORCA templates follow the Velocity syntax which can be used to replace several key properties that are assigned by ORCA after the slice request is submitted. These properties include MACs and IP addresses assigned to data plane interfaces and the unique name assigned to each object.

Velocity variable Description
$self Refers to the virtual machine on which the script will be executed
$<nodeName> Refers to the virtual machine with the specified name (as in $node1)
$<groupName> Refers to a group of virtual machines (as an array; as in $group1)
$sliceName Refers to the name/urn of the slice
$userDN Refers to the user who created the slice
$sliceID Refers to the guid ID of the slice

The $self and $ variables refer to individual virtual machine objects. These objects

Properties of virtual machines notes examples
IP("link name") Refers to the IP address of the interface assigned to the link called "link name" $self.IP("link0"), $node0.IP("link0")
MAC("link name") Refers to the MAC of the interface assigned to the link called "link name" $self.MAC("link0"), $node0.MAC("link0")
Name() Refers to the name assigned by ORCA to the virtual machine $self.Name(), $node0.Name()

Group objects are simply arrays of virtual machine objects. Groups are referred to by name and virtual machines with in a group are referred to by the group name with a corresponding index.

Properties of groups notes examples
size() Refers number of virtual machines in the group $NodeGroup0.size()
get(index) Refers to a specific virtual machine within a group $NodeGroup0.get(0)

Individual virtual machines with a group have the same properties as individual virtual machines.

$NodeGroup0.get(0).IP("link name") Refers to the IP address of interface assigned to the link called "link name" in the first virtual machine in the group
$NodeGroup0.get(0).MAC("link name") Refers to the MAC of the interface assigned to the link called "link name" in the first virtual machine in the group
$NodeGroup0.get(0).Name() Refers to the name assigned by ORCA to the first virtual machine in the group

The following is an example post boot script that adds an entry to the /etc/hosts file for each of the instances in the request and sets the hostname of each instance to an appropriate value. In this particular example, the first virtual machine in the group is assumed to be a master node named "master" while the remaining nodes are named "NodeGroup-1", "NodeGroup-2", etc.. The names of the group and node correspond to names in the screen shot. Note the use of the #foreach macro that allows for generation of code - the resulting script after the processing has multiple 'echo' lines.

Image(flukes-templates1.png)

#!/bin/bash
echo $NodeGroup0.get(0).IP("Link0") master >> /etc/hosts
#set ( $size = $NodeGroup0.size()  - 1 )
#foreach ( $i in [1..$size] )
   echo $NodeGroup0.get($i).IP("Link0")  `echo $NodeGroup0.get($i).Name() |  sed 's/\//-/g'` >> /etc/hosts
#end
name=$self.Name()
if [ "$name" = "NodeGroup0/0" ];
then
   echo master > /etc/hostname
else
   echo $self.Name() |  sed 's/\//-/g' > /etc/hostname
fi
/bin/hostname -F /etc/hostname

After Velocity processing, the script for the first member of the node group looks like this (note that the script will look different depending on which node you are on):

#!/bin/bash
echo 172.16.100.1 master >> /etc/hosts

echo 172.16.100.1  `echo NodeGroup0/0 |  sed 's/\//-/g'` >> /etc/hosts
echo 172.16.100.2  `echo NodeGroup0/1 |  sed 's/\//-/g'` >> /etc/hosts
echo 172.16.100.3  `echo NodeGroup0/2 |  sed 's/\//-/g'` >> /etc/hosts
echo 172.16.100.4  `echo NodeGroup0/3 |  sed 's/\//-/g'` >> /etc/hosts

name=NodeGroup0/0
if [ "$name" = "NodeGroup0/0" ];
then
   echo master > /etc/hostname
else
   echo NodeGroup0/0 |  sed 's/\//-/g' > /etc/hostname
fi
/bin/hostname -F /etc/hostname

Note that when a broadcast link is involved, the template should use the name of the broadcast link box, not the names of the edges leading to it.

Getting public IP of the node

While technically not part of the post-boot script processing, there is a facility that is part of the NEuca-py guest tools running inside guest VM that allows a script writer to learn the management IP address (public) of the node. Note that taking address from eth0 of the node will not provide a public IP address due to OpenStack NAT.

To get the public IP address the following command can be issued inside the shell or in a shell script:

$ neuca-get-public-ip

Debugging

Experimenters can use the neuca tools inside their VM image to debug problems with post-boot script templates. Specifically invoking

$ neuca-user-script

will show the state of the post-boot script after Velocity processing and should help pinpoint any problems in macro substitutions in the template. You can also inspect the script after templates are applied once Flukes is able to display the slice manifest (click on 'View Properties').

⚠️ **GitHub.com Fallback** ⚠️