Skip to content

Recipe XML Format

Ondrej Lichtner edited this page Nov 6, 2016 · 30 revisions

This document describes the format of recipe XML files accepted by lnst-ctl. This is more of a reference guide than a manual or how-to. If you want to know how to structure your very first recipe, please refer to [How to Structure LNST Recipe](How to Structure LNST Recipes).

0. Index

Here is a map of the XML format. To get a description of a tag, click on its name.

<lnstrecipe>

1. Recipe Structure

LNST recipes have the following structure:

<lnstrecipe>
    <network>
        ...
    </network>

    <task>
    </task>
    ...
</lnstrecipe>

You need to provide information about the machines required for the test. All these information are listed under the <network> tag, since the machines create a network environment. After that you can specify one or more tasks to be executed. Each task is enclosed in a <task> tag. Think of tasks as test cases.

ELEMENT: <lnstrecipe>
Root element required in every valid LNST recipe.
Attributes: Required: None
Optional: None
Children: Required: <network>
<task>
Optional: None

2. Network

There must be exactly one <network> tag provided in every valid LNST recipe. The tag contains an enumeration of machine details (in the form of <host> tags) required to perform the test.

ELEMENT: <network>
Contains a list of machines required to perform the test.
Attributes: Required: None
Optional: None
Children: Required: <host>
Optional: None
Example
<network>
    <host id="1">...</host>
    <host id="peanut">...</host>
    ...
</network>

2.2 Host tag

Each host tag can contains two sections, parameters within the <params> tag and enumeration of the its interfaces (<interfaces> tag). The former is optional, the latter mandatory. You can request a number of parameters for the machine to have, such as a type and version of the operating system, even some hardware details.

ELEMENT: <host>
Specification of a machine that is required to perform the test.
Attributes: Required: [string] id: An unique identifier of the machine
Optional: None
Children: Required: <interfaces>
Optional: <params>
ELEMENT: <params>
The parameters of a machine.
Attributes: Required: None
Optional: None
Children: Required: <param>
Optional: None
ELEMENT: <param>
A single parameter of a machine.
Attributes: Required: [string] name: The name of the parameter
[string] value: The required value
Optional: None
Children: Required: None
Optional: None
Example
<host id="peanut">
    <params>
        <param name="os" value="rhel6.2"/>
        <param name="type" value="server"/>
    </params>
    <interfaces>...</interfaces>
</host>

2.3 Interfaces

The second (and far more complicated) part of machine specification is the network configuration. In this section of the recipe, you need to specify what interfaces you would like for the machine to have and how they should be configured. You will be able to refer to the herein configured devices from the tasks.

ELEMENT: <interfaces>
List of interfaces of a machine with their configuration
Attributes: Required: None
Optional: None
Children: Required: one of following:
<eth>
<bond>
<team>
<vlan>
<bridge>
<macvlan>
<ovs_bridge>
<lo>
<vti>
<vti6>
<vxlan>
<veth_pair>
Optional: None
ELEMENT: <veth_pair>
Tag containing a pair of <veth> tags
Attributes: Required: None
Optional: None
Children: Required: <veth> Note: the <veth> tag needs to be specified twice
Optional: None
ELEMENT: <eth>, <bond>, <team>, <vlan>, <bridge>, <macvlan>, <ovs_bridge>, <lo>, <vti>, <vti6>, <veth>, <vxlan>
Test interface configuration
Attributes: Required: [string] id: unique identifier of the interface
[string] label: an interface label indicating which interfaces can talk to each other; Note: applicable to <eth> only
Optional: [string] netns: specifies which network namespace should the interface be moved to or created in
Children: Required: None
Optional: <addresses>
<options> Note: applicable to all except <eth>
<params> Note: applicable to <eth> only
<slaves> Note: applicable to all except <eth>, <lo>, <vti> and <veth>
<vlan> Note: applicable to <ovs_bridge> only
<bond> Note: applicable to <ovs_bridge> only
<netem> Note: applicable to <eth> only.

2.3.1 Addresses

Address can be assigned to all interface types.

ELEMENT: <addresses>
A list of addresses to be assigned to this interface
Attributes: Required: None
Optional: None
Children: Required: <address>
Optional: None
ELEMENT: <address>
An address
Attributes: Required: [string] value: IP or IP6 address
Optional: None
Children: Required: None
Optional: None

2.3.2 Options

Some interface types have configurable options. Use the option child tag to set them.

ELEMENT: <options>
A list of configuration options
Attributes: Required: None
Optional: None
Children: Required: <option>
Optional: None
ELEMENT: <option>
An option
Attributes: Required: [string] name: option name
[string] value: option value; Note: Value can also be passed as tag content
Optional: None
Children: Required: None
Optional: None

2.3.3 Params

The parameters tag allows you to request specific details about the interface, such as the driver, NIC model, etc.

ELEMENT: <params>
The parameters of an interface.
Attributes: Required: None
Optional: None
Children: Required: <param>
Optional: None
ELEMENT: <param>
A single parameter of an interface.
Attributes: Required: [string] name: The name of the parameter
[string] value: The required value
Optional: None
Children: Required: None
Optional: None

2.3.4 Slaves

Interfaces that are not associated with any physical device (all except <eth>) usually have slave interfaces assigned.

ELEMENT: <slaves>
A list of slave interfaces
Attributes: Required: None
Optional: None
Children: Required: <slave>
Optional: None
ELEMENT: <slave>
Slave interface
Attributes: Required: [string] id: slave identifier
Optional: None
Children: Required: None
Optional: None

LNST is even able to configure multiple network devices into bonds and teams. It can also perform VLAN and bridging configuration for you.

2.4 Interface types

We will have a closer look at the configuration of different interface types in the following sections.

2.4.1 Simple Ethernet Interface

When setting up a plain Ethernet interface you need to specify it with the <eth> tag and set it's attributes id and label. The label attribute tells LNST which interfaces can talk to each other. You also need to configure an address using the addresses tag. See the example below:

Example
<interfaces>
    <eth id="testiface" label="net1">
        <addresses>
            <address value="192.168.100.226/24"/>
        </addresses>
    </eth>
    <eth id="2" label="net1">
        <addresses>
            <address value="192.168.100.240/24"/>
        </addresses>
    </eth>
</interfaces>

2.4.2 Bonding

Slaves

The configuration of a bond is a little more tricky. Firstly, you need to have at least two ethernet interfaces which will be part of the bond.

<eth id="test_if1" label="net1"/>
<eth id="test_if2" label="net2"/>

After that, it is necessary to create a new interface of type bond. Then you will need to specify the slave interfaces that will be part of the bond:

<slaves>
    <slave id="test_if1"/>
    <slave id="test_if2"/>
</slaves>
Options

The bonding driver also has a lot of configurable parameters. You can specify any of them using the option tag. For the full list of available parameters, please refer to the original bonding driver documentation.

In our example we will set only the bonding mode (0 or round-robin) and miimon link check interval to 100ms

<options>
    <option name="mode" value="0"/>
    <option name="miimon" value="100"/>
</options>

Bond created inside an Open vSwitch also accept some options, full list of available options can be viewed in the Open vSwitch documentation for the ovs-vswitchd database. Options for Open vSwitch bond, similar to the bonding options shown higher, would look like this:

<options>
    <option name="bond_mode" value="active-backup"/>
    <option name="other_config:bond-miimon-interval" value="100"/>
</options>
Bond Example

Let's summarize all snippets sketched above into one bond interface configuration:

<host id="testmachine1">
    <interfaces>
        <eth id="test_if1" label="net1"/>
        <eth id="test_if2" label="net1"/>
        <bond id="test_bond">
            <slaves>
                <slave id="test_if1"/>
                <slave id="test_if2"/>
            </slaves>
            <options>
                <option name="mode" value="0"/>
                <option name="miimon" value="100"/>
            </options>
            <addresses>
                <address value="192.168.200.1/24"/>
            </addresses>
        </bond>
    </interfaces>
</host>

2.4.3 Vlan

Slaves

First you need to initialize the interface which will be used to configure the VLAN:

<eth id="test_if1" label="net1"/>

The interface is "enslaved" under the newly created VLAN interface using the <slaves> tag:

<slaves>
    <slave id="test_if1"/>
</slaves>
Options

The only supported option for VLANs is vlan_tci. It can be configured as follows:

<options>
    <option name="vlan_tci" value="10"/>
</options>
VLAN Example

Let's summarize all snippets sketched above into one VLAN interface configuration:

<host id="testmachine1">
    <interfaces>
        <eth id="1" label="net1"/>
        <vlan id="testifc1"/>
            <options>
                <option name="vlan_tci" value="10"/>
            </options>
            <slaves>
                <slave id="1"/>
            </slaves>
            <addresses>
                <address value="192.168.200.2/24"/>
            </addresses>
        </vlan>
    </interfaces>
</host>

2.4.4 MAC-VLAN

Slave

First you need to initialize the underlying interface which will be used to configure the MAC-VLAN:

<eth id="test_if1" label="net1"/>

The interface is "enslaved" under the newly created MAC-VLAN interface using the <slaves> tag:

<slaves>
    <slave id="test_if1"/>
</slaves>
Options

If you want to have custom MAC address assigned to the macvlan device you need to provide it under <options> tag.

<options>
    <option name="hwaddr" value="56:61:4f:7c:77:db"/>
</options>
MAC-VLAN Example

Let's summarize all snippets sketched above into one macvlan interface configuration:

<host id="testmachine1">
    <interfaces>
        <eth id="1" label="net1"/>
        <macvlan id="testifc1"/>
            <options>
                <option name="hwaddr" value="56:61:4f:7c:77:db">
            </options>
            <slaves>
                <slave id="1"/>
            </slaves>
            <addresses>
                <address value="192.168.200.2/24"/>
            </addresses>
        </macvlan>
    </interfaces>
</host>

2.4.5 Team

Slaves

First you need to initialize the interfaces which will be used to configure the team:

<eth id="1" label="net1"/>
<eth id="2" label="net1"/>
<eth id="3" label="net1"/>

The interfaces are "enslaved" under the newly created team interface using the <slaves> tag:

<slaves>
    <slave id="1"/>
    <slave id="2"/>
    <slave id="3"/>
</slaves>
Options

You can put a JSON (JavaScript Object Notation) configuration for the team device directly in the LNST recipe:

<options>
    <option name="teamd_config">
        {
            "hwaddr": "00:11:22:33:44:55",
            "runner": {"name": "roundrobin"}
        }
    </option>
</options>
Team Example

Let's summarize all snippets sketched above into one team interface configuration:

<host id="testmachine1">
    <interfaces>
        <eth id="1" label="net1"/>
        <eth id="2" label="net1"/>
        <eth id="3" label="net1"/>
        <team id="testiface">
            <options>
                <option name="teamd_config">
                    {
                        "hwaddr": "00:11:22:33:44:55",
                        "runner": {"name": "roundrobin"}
                    }
                </option>
            </options>
            <slaves>
                <slave id="1"/>
                <slave id="2"/>
                <slave id="3"/>
            </slaves>
            <addresses>
                 <address value="{$testip}"/>
                 <address value="{$testip6}"/>
            </addresses>
        </team>
    </interfaces>
</host>

2.4.6 Bridge

Slaves

First you need to initialize the interfaces which will be used to configure the bridge:

<eth id="1" label="net1"/>
<eth id="2" label="net2"/>

The interfaces are "enslaved" under the newly created team interface using the <slaves> tag:

<slaves>
    <slave id="1"/>
    <slave id="2"/>
</slaves>
Address

In case of the bridge the addresses are configured directly on the interfaces.

Bridge Example
<host id="testmachine1">
    <interfaces>
        <eth id="1" label="net1">
            <addresses>
                 <address value="192.168.1.101"/>
            </addresses>
        </eth>
        <eth id="2" label="net2">
            <addresses>
                 <address value="192.168.1.102"/>
            </addresses>
        </eth>
        <bridge id="lnstbr">
            <slaves>
                <slave id="1"/>
                <slave id="2"/>
            </slaves>
        </bridge>
    </interfaces>
</host>

2.4.7 Open vSwitch Bridge

NOTE: Open vSwitch needs to be properly installed before LNST tries to use it, this also includes having the databse initialised. To do this refer to the official Open vSwitch website or if you're using a Fedora/RHEL distribution, run this command:

$ ovsdb-tool create /etc/openvswitch/conf.db

The Open vSwitch bridge configuration resembles the configuration of a normal bridge - you specify the bridge ports in the same way, by using the <slaves> tag. However, on top of the normal bridge functionality the Open vSwitch allows for additional features:

VLANs

The <vlan> tags define VLANs in the Open vSwitch. The semantics of this tag are different from the vlan tag that defines a device, here it takes the more traditional meaning of a VLAN. A single port can be a part of multiple VLANs, this device is then configured as a trunk device.

ELEMENT: <vlan>
VLAN on the Open vSwitch Bridge
Attributes: Required: [integer] tag: VLAN tag
Optional: None
Children: Required: <slaves>
Optional: None
Bonds
ELEMENT: <bond>
Bond on the Open vSwitch Bridge
Attributes: Required: [string] id: bond id
Optional: None
Children: Required: <slaves>
Optional: <options>
Tunnels
ELEMENT: <tunnel>
Tunnel interface on the Open vSwitch Bridge
Attributes: Required: [string] id: id of the tunnel interface
[string] type: can be vxlan, gre or geneve
Optional: None
Children: Required: None
Optional: <options>
<addresses>

Options accepts any options that can be directly set for the tunnel Interface through the ovs-vsctl set Interface command.

Internal ports
ELEMENT: <internal>
Internal port interface on the Open vSwitch Bridge
Attributes: Required: [string] id: id of the tunnel interface
Optional: None
Children: Required: None
Optional: <options>
<addresses>

Options accepts any options that can be directly set for the tunnel Interface through the ovs-vsctl set Interface command.

Flow entries
ELEMENT: <flow_entries>
Flow entries for the Open vSwitch Bridge
Attributes: Required: None
Optional: [string] value flow entry value
Children: Required: None
Optional: Textual value of the flow entry

You can now also specify flow entries for the ovs bridge. These are directly passed to the ovs-ofctl add-flow command. For the specific format of flow entries refer to the OvS documentation.

Open vSwitch Bridge Example
<ovs_bridge id="ovs1">
    <slaves>
        <slave id="if1"/>
        <slave id="if2"/>
        <slave id="if3"/>
    </slaves>
    <vlan tag="1">
        <slaves>
            <slave id="if1"/>
        </slaves>
    </vlan>
    <vlan tag="2">
        <slaves>
            <slave id="if2"/>
        </slaves>
    </vlan>
    <internal id="int0">
        <addresses>
            <address value="{$vxlan_net}.1/24"/>
            <address value="{$vxlan_net6}::1/64"/>
        </addresses>
        <options>
            <option name="ofport_request" value="5"/>
            <option name="name" value="int0"/>
        </options>
    </internal>
    <tunnel id="vxlan1" type="vxlan">
        <options>
            <option name="option:remote_ip" value="{$net}.2"/>
            <option name="option:key" value="flow"/>
            <option name="ofport_request" value="10"/>
        </options>
    </tunnel>
    <flow_entries>
        <entry>table=0,in_port=5,actions=set_field:100->tun_id,output:10</entry>
        <entry>table=0,in_port=10,tun_id=100,actions=output:5</entry>
        <entry>table=0,priority=100,actions=drop</entry>
    </flow_entries>
</ovs_bridge>

2.4.8 Loopback

The <lo> tag can be used for only basic configuration of the loopback device

  • setting IP addresses. The more important use of the tag is to associate it with an ID that the user can use later in the recipe if he needs to work with the loopback device.

There is one more specific property that the loopback has - there can only be one loopback device present, per network namespace. If this rule is broken LNST will not execute the recipe.

Loopback Example
<lo id="loopback">
    <addresses>
        <address>192.168.2.2/24</address>
    </addresses>
</lo>

2.4.9 Virtual Tunnel Interface (VTI and VTI6)

The virtual tunnel interface can be used to create IPSec tunnels over normal connections.

Options

The vti (vti6) interface accepts 3 options:

  • key the only mandatory option that is used to identify the device with regards to xfrm IPSec policies
  • local specifies IP address that is used as the local endpoint for the IPSec tunnel
  • remote specifies IP address that is used as the remote endpoint for the IPSec tunnel
VTI Example
<vti id="vti">
    <options>
        <option name="local" value="1.1.1.1"/>
        <option name="remote" value="1.1.1.2"/>
        <option name="key" value="1"/>
    </options>
</vti>
VTI6 Example
<vti6 id="vti6">
    <options>
        <option name="local" value="2002::1/64"/>
        <option name="remote" value="2002::2/64"/>
        <option name="key" value="1"/>
    </options>
</vti6>

2.4.10 Virtual Ethernet (veth)

The main use case for virtual ethernet interfaces is in combination with network namespaces where they can be used to connect two namespaces as two machines would be by an ethernet cable. VEth interfaces are always created in pairs which is why we use a parent tag <veth_pair> which contains exactly two <veth> tags.

VEth configuration itself is very similar to basic ethernet interfaces except that you don't specify the label attribute.

VEth example
<veth_pair>
    <veth id="veth1" netns="secure">
        <addresses>
            <address>192.168.1.1/24</address>
        </addresses>
    </veth>
    <veth id="veth2"/>
</veth_pair>

2.4.11 VXLAN

VXLANs are a type of tunnel interface that allows you to create an L2 network over an L3 network. Similar to a VLAN interface it requires precisely one slave interface and accepts a couple of options specific for VXLAN configuration.

You can configure the VXLAN interface to either connect to a specific remote_ip or to a multicast group_ip and select a non-default destion port.

VXLAN example
<host id="testmachine1">
    <interfaces>
        <eth id="1" label="net1"/>
        <vxlan id="testifc1">
            <options>
                <option name="id" value="10"/>
                <option name="remote_ip" value="192.168.0.2"/>
                <option name="group_ip" value="239.1.1.1"/>
                <option name="dstport" value="4789"/>
            </options>
            <slaves>
                <slave id="1"/>
            </slaves>
            <addresses>
                <address value="192.168.200.2/24"/>
            </addresses>
        </xvlan>
    </interfaces>
</host>

3. Task

Tasks can be thought of as test cases. There should be one task for one case. There may be one or more tasks in each recipe. There are currently 2 types of Tasks supported by LNST:

  • Python Tasks, that are newer and recommended, they're described here.
  • XML tasks that are described in this section. These are supported for legacy reasons and you shouldn't be using them when creating new recipes.
ELEMENT: <task>
A sequence of commands forming a single test case
Attributes: Required: None
Optional: [string] python: path to python script, defines that this is a python task and it doesn't allow any children tags
[boolean] quit_on_fail: accepts values yes/no/true/false; default is false; when enabled if this task fails the controller will not execute any more commands or tasks from this recipe
[string] module_dir: path to directory that should be searched for module resources before execution of this task
[string] tools_dir: path to directory that should be searched for tool resources before execution of this task
Children: Required: None
Optional: These child elements are only allowed if the python attribute is NOT DEFINED
<run>
<ctl_wait>
<config>
<wait>
<intr>
<kill>
XML Task Example
<task>
    <run command="sleep 5" host="1"/>
    <run module="IcmpPing" host="1" timeout="30">
        <options>
            <option name="addr" value="{ip(2,1)}"/>
            <option name="count" value="40"/>
            <option name="interval" value="0.2"/>
            <option name="limit_rate" value="95"/>
        </options>
    </run>
    <run module="IcmpPing" host="1" bg_id="1">
        <options>
            <option name="addr" value="{ip(2,1)}"/>
            <option name="count" value="40"/>
            <option name="interval" value="0.2"/>
            <option name="limit_rate" value="95"/>
        </options>
    </run>
    <ctl_wait seconds="5"/>
    <intr host="1" bg_id="1"/>
</task>
Python Task Example
<task python="task_check_ping.py"/>

4. Task commands

4.1 Run

Run element provides three types of running a code depending on specified attributes.

You can execute shell commands on slave machines directly from the recipe. Needless to say, this type of command is intended to be used sporadically for short commands (such as a bash script or third party tool execution). Please do not write programs or scripts using this type of command. Also, if you need to configure a system property using /proc or /sys, please use <config> instead. It will take care of the clean-up at the end of the recipe. It is a good idea to set a timeout, because the command could hang, currently the default timeout is 60 seconds.

This tag also provides ability to run test modules of LNST. Some modules, such as IcmpPing, Iperf, or Multicast are directly a part of LNST distribution, but you can add more of your custom or any other third-party modules as well. Each module can accept a different set of options through the <options> tag. Please refer to the documentation of the respective module for more information. It is also a good idea to provide a timeout, because there could be a bug in the module. See the example of IcmpPing below, other test modules are documented here:

ELEMENT: <run>
Run command,test module or 3rd party tool
Attributes: Required: [string] host: machine to run this command on
one of following:
[string] module: specifies an LNST test module to run
[string] command: specifies an command to run on command line
Optional: [string] bg_id: execute command or test in background with a specific bg_id (it will be used later to interrupt or kill it)
[int] timeout: failsafe timeout to terminate command execution in case it hangs
[string] from: specifies a 3rd party tool to run the command from; Note: applicable with command attribute only
["pass"|"fail"] expect: specifies whether the tester expects the command to fail or pass; default is pass
[string] netns: specifies which network namespace should the command be run in
Children: Required: None
Optional: <options>: test module options; Note: applicable with module attribute only
ELEMENT: <options>
Set of command options
Attributes: Required: None
Optional: None
Children: Required: None
Optional: <option>
ELEMENT: <option>
Option assignment
Attributes: Required: [string] name: option name (this is test-specific)
[string] value: option value; Note: If the value is longer, you can omit this attribute and put it in the contents of the tag.
Optional: None
Children: Required: None
Optional: None
Shell command example
<run command="tcpdump -i {devname(2, 1)}" host="1" timeout="30"/>
LNST test example
<run module="IcmpPing" host="1" timeout="30">
    <options>
        <option name="addr" value="{ip(2,1)}"/>
        <option name="count" value="40"/>
        <option name="interval" value="0.2"/>
        <option name="limit_rate" value="95"/>
    </options>
</run>
3rd party tool example

If you have any third-party tools set up with LNST, you can use the from attribute to specify which one LNST should use.

<run from="multicast" command="./igmp_query -a 192.168.1.101" host="1" timeout="30"/>

4.2 Background Execution

Commands execute in sequential order from the controller's perspective, unless you specify any of them to run in the background. To do so, you need to add a bg_id attribute to the command you want to run in the background. After doing so, you need to match the background command with one of the termination commands -- <kill>, <intr> (interrupt), or <wait>.

ELEMENT: <kill>, <intr>, <wait>
Terminate or wait for a command running on background
Attributes: Required: [string] host: machine to run this command on
one of following:
[string] bg_id: specifies an id of the command running on background
Optional: None
Children: Required: None
Optional: None

4.2.1 kill

Using kill to terminate the command will end its life with SIGKILL. In the following example, the controller will execute a ping test on machine 1 in the background. It will wait for 5 seconds and then kill the ping_cmd.

<run module="IcmpPing" host="1" bg_id="ping_cmd">
    <options>
        <option name="addr" value="{ip(2,1)}"/>
        <option name="count" value="40"/>
    </options>
</run>
<ctl_wait seconds="5"/>
<kill host="1" bg_id="ping_cmd"/>

4.2.2 intr

Interrupt is very similar to kill. But it will send SIGINT instead. This can be useful if your test module to does some evaluation of its run when it's terminated, e.g. collecting statistics.

<intr host="1" bg_id="ping_cmd"/>

4.2.3 wait

Wait will not signal the background process, but instead it will wait for it to terminate.

<wait host="1" bg_id="ping_cmd"/>

4.3 ctl_wait

This command is exceptional in the sense that it is not executed on any of the slaves. Instead it is run on the controller machine itself. Therefore it does not require a machine. This command can be used to make the controller wait for some time while the slaves are executing commands in the background.

ELEMENT: <ctl_wait>
Wait specified amount of time on the controller
Attributes: Required: [int] seconds: specifies number of seconds to wait
Optional: None
Children: Required: None
Optional: None
<!-- Controller will wait for 5 seconds -->
<ctl_wait seconds="5"/>

4.4 System Config

System config is the native way for making changes in system configuration through /proc/ or /sys/ interface. There are two versions of the command. One-line or multi-line command that will allow you to set more options at once. Both versions are demonstrated in the following example:

ELEMENT: <config>
Sets and restores system configuration variables in /proc filesystem
Attributes: Required: [string] host: machine to run this command on
[string] option: specifies a path to variable in /proc fs
[string] value: specifies a value to set for the variable set in option attribute
Optional: [string] persistent: if set to true variable's value will not be restored after the task is finished
[string] netns: specifies which network namespace should be configured
Children: Required: None
Optional: <options>: if this tag is present user can specify multiple option-value entries
ELEMENT: <options>
A list of configuration options
Attributes: Required: None
Optional: None
Children: Required: <option>
Optional: None
ELEMENT: <option>
An option
Attributes: Required: [string] name: option name
[string] value: option value
Optional: None
Children: Required: None
Optional: None
Config example
<config host="1" option="/proc/sys/net/ipv4/igmp_max_memberships" value="5" persistent="true"/>

<config host="1">
    <options>
        <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="5"/>
        <option name="/proc/sys/net/ipv4/conf/{devname(2,1)}/force_igmp_version" value="2"/>
    </options>
</config>

The persistent attribute to the first tag denotes, that that option should not be cleaned up at the end of the task. Use this if you need to set the options persistently through multiple tasks or in case the option cannot be reverted back easily (some files in /proc/ return different values than they expect, so LNST will fail to reset them to the previous state. You will need to revert the value back to the original by yourself.

5. Templates

On top of the standard XML syntax, LNST Recipe format is extended with support of, so called, templates. Templates are always enclosed within a pair of curly braces {}. Templates can be used ONLY within an attribute value or within a tag's text content. Templates therefore will not work when used as a name of a tag or attribute!

There are two types of templates that will be discussed in the sections bellow: aliases and template functions.

5.1 Aliases

Aliases can be thought of as macros or variables (although they cannot be changed). You can define an alias absolutely anywhere within the document structure (as long as it does not invalidate the XML) by using the <define> tag.

The alias name is limited to characters in regexp [a-zA-Z0-9_].

<define>
    <alias name="multicast_group" value="239.1.2.3"/>
    <alias name="port" value="1337"/>
    <alias name="test_duration" value="10"/>
    <alias name="send_delay" value="0.1"/>
    <alias name="nonexistent_ip" value="127.0.0.200"/>
</define>

After you define your aliases, you will be able to reference them using the following notation: {$alias_name}. See the example bellow:

<run module="Multicast" bg_id="1" host="1" timeout="30">
    <options>
        <option name="setup" value="send_simple"/>
        <option name="address" value="{$multicast_group}"/>
        <option name="port" value="{$port}"/>
        <option name="duration" value="{$test_duration}"/>
        <option name="delay" value="{$send_delay}"/>
    </options>
</run>

Alias definition's area of effect is within the tag it was defined in and in all subsequent child tags. It will be discarded as soon as the parent tag is closed.

5.2 Template Functions

Template functions are conceptually quite similar to aliases, but instead of an assigned value, they represent an action that will be executed when the recipe is parsed. They can be used the same way as aliases - inside of curly braces. Currently, there are three template functions available in LNST:

5.2.1 ip(host_id, interface_id [, address_id])

Returns an IP address for a specific machine and interface. Third argument is optional and can be used when there are multiple IP addresses associated with a single interface. Be aware that the function returns the address with netmask stripped. To get the netmask use the prefix() function as described below.

5.2.2 prefix(host_id, interface_id [, address_id])

Returns the prefix (netmask) of an IP address for a specific machine and interface. Third argument is optional and can be used when there are multiple IP addresses associated with a single interface.

5.2.3 hwaddr(host_id, interface_id)

Returns hardware address of specified interface.

5.2.4 devname(host_id, interface_id)

Returns the device name of a specified interface.

All four above mentioned functions can be used for retrieving information from machine configs, therefore calling them is only valid within a task. See the following example on how this template can be used:

<config option="/proc/sys/net/ipv4/conf/{devname(1,1)}/forwarding" value="1" host="1" />
<run module="test" value="Multicast" host="1" timeout="30">
    <options>
        <option name="setup" value="max_groups" />
        <option name="interface" value="{ip(1,1)}" />
        <option name="condition" value="max_groups > 0" />
    </options>
</run>

Aliases can be passed to functions as parameters, but the preprocessor does not support nesting (e.g. function cannot have another function passed as an argument).

6. Breaking Recipes into Multiple Files

LNST also offers a possibility of splitting the recipe into several files. This can be useful in case you would like to re-use some code in different recipes. LNST uses a mechanism called XInclude using the <xi:include> tag. The contents of that tag will be loaded from the file specified by the href attribute. For instance, the following machine configuration will be loaded from file peanut.xml:

<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude">
    <network>
        <xi:include href="machine_configs/peanut.xml"/>
    </network>
    <task>
       ...
    </task>
</lnstrecipe>

Example ( peanut.xml ):

<host id="1" xmlns:xi="http://www.w3.org/2003/XInclude">
    <params>
        <param name="os" value="rhel6.2"/>
    </params>
    <xi:include href="machine_configs/interfaces1.xml"/>
</host>

Note that parts of the included machine config are again external.

Clone this wiki locally