-
Notifications
You must be signed in to change notification settings - Fork 32
Recipe XML Format
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).
Here is a map of the XML format. To get a description of a tag, click on its name.
<lnstrecipe>
|
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.
Root element required in every valid LNST recipe. | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: |
<network> <task>
|
Optional: | None |
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.
Contains a list of machines required to perform the test. | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: |
<host>
|
Optional: | None |
<network>
<host id="1">...</host>
<host id="peanut">...</host>
...
</network>
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.
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>
|
The parameters of a machine. | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: |
<param>
|
Optional: | None |
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 |
<host id="peanut">
<params>
<param name="os" value="rhel6.2"/>
<param name="type" value="server"/>
</params>
<interfaces>...</interfaces>
</host>
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.
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 |
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 |
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.
|
Address can be assigned to all interface types.
A list of addresses to be assigned to this interface | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: |
<address>
|
Optional: | None |
An address | ||
Attributes: | Required: | [string] value: IP or IP6 address |
Optional: | None | |
Children: | Required: | None |
Optional: | None |
Some interface types have configurable options. Use the option child tag to set them.
A list of configuration options | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: |
<option>
|
Optional: | None |
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 |
The parameters tag allows you to request specific details about the interface, such as the driver, NIC model, etc.
The parameters of an interface. | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: |
<param>
|
Optional: | None |
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 |
Interfaces that are not associated with any physical device (all except <eth>
)
usually have slave interfaces assigned.
A list of slave interfaces | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: |
<slave>
|
Optional: | None |
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.
We will have a closer look at the configuration of different interface types in the following sections.
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:
<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>
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>
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>
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>
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>
The only supported option for VLANs is vlan_tci. It can be configured as follows:
<options>
<option name="vlan_tci" value="10"/>
</options>
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>
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>
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>
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>
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>
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>
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>
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>
In case of the bridge the addresses are configured directly on the interfaces.
<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>
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:
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 |
ELEMENT: <bond>
| ||
Bond on the Open vSwitch Bridge | ||
Attributes: | Required: | [string] id: bond id |
Optional: | None | |
Children: | Required: |
<slaves>
|
Optional: |
<options>
|
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.
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.
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.
<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>
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.
<lo id="loopback">
<addresses>
<address>192.168.2.2/24</address>
</addresses>
</lo>
The virtual tunnel interface can be used to create IPSec tunnels over normal connections.
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 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 id="vti6">
<options>
<option name="local" value="2002::1/64"/>
<option name="remote" value="2002::2/64"/>
<option name="key" value="1"/>
</options>
</vti6>
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_pair>
<veth id="veth1" netns="secure">
<addresses>
<address>192.168.1.1/24</address>
</addresses>
</veth>
<veth id="veth2"/>
</veth_pair>
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.
<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>
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.
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>
|
<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>
<task python="task_check_ping.py"/>
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:
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 |
Set of command options | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: | None |
Optional: |
<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 |
<run command="tcpdump -i {devname(2, 1)}" host="1" timeout="30"/>
<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>
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"/>
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>
.
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 |
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"/>
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"/>
Wait will not signal the background process, but instead it will wait for it to terminate.
<wait host="1" bg_id="ping_cmd"/>
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.
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"/>
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:
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
|
A list of configuration options | ||
Attributes: | Required: | None |
Optional: | None | |
Children: | Required: |
<option>
|
Optional: | None |
An option | ||
Attributes: | Required: |
[string] name: option name [string] value: option value |
Optional: | None | |
Children: | Required: | None |
Optional: | None |
<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.
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.
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.
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:
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.
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.
Returns hardware address of specified interface.
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).
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.