-
Notifications
You must be signed in to change notification settings - Fork 31
How to Structure LNST Recipes
If you have set up your topology and configured all the slave machines, you can finally proceed to running tests. This document will describe the process of designing a test recipe. It is a practically oriented text with a lot of examples; however it will not provide you with a full manual to the recipe XML format employed by LNST. If you seek the complete format specs, please refer to the Recipe XML Reference.
The process of recipe design in LNST breaks down into two parts: deciding what environment will the test require and what actions will be necessary in order to perform it. In fact, LNST recipes reflect this directly in their structure. Each recipe has two sections represented by two tags. The <network> tag contains the description of the test environment (network topology and configuration of the machines) and one or more <task> tags that contains the test cases (i.e. the actions performed during the test). Both of them are discussed in the following sections:
<lnstrecipe>
<network/>
<task/>
<task/>
...
</lnstrecipe>We will be designing a simple example recipe in this guide to showcase the discussed proposals. It will be just a ping test between two machines, but at this point, it would be counterproductive to deal with too much complexity.
The very first thing for you to decide is what machines will your test require? What will the topology look like? Do you have any requirements for the hardware used? Do you want to run your test on a specific operating system? All these requirements go to the first section of the recipe.
The requirements for the example test are the following:
- The ping will be IPv4
- Acceptable packet loss is 10%
- The test must not run longer than 30 seconds
- All the slave machines must run Fedora 18
These are pretty standard test requirements. There are no hardware limitations, because ping works on almost anything (these days, you could ping a fridge if you wanted to). There is, however, a requirement on the operating system, because we want to test the networking stack of Fedora 18. We (sort of arbitrarily) defined an acceptable packet loss of 10% just to showcase various capabilities of LNST. Finally, the test execution time should not exceed 30 seconds. If the tests were run unattended in a batch, we want to prevent any infinite loops and waits.
The test environment for each recipe is specified by an enumeration of hosts that participate in the test within the <network> tag. Each host has its unique id that is used for later reference to it. The tag must contain two children, the <params> defining the requirements for the host and <interfaces> defining the required interfaces and their configuration:
<network>
<host id="sender">
<params/>
<interfaces/>
</host>
<host id="receiver">
<params/>
<interfaces/>
</host>
</network>Now when we are clear on the requirements, we can proceed to write them down in the language of LNST, which is XML. We will need exactly two hosts to ping from one to another. Both of the hosts must be connected to one network segment so they can reach one another. All this is specified within the <host> tag. Host requirements are specified by the <params> and <interfaces> tags and can be expressed as follows:
<params>
<param name="os" name="Fedora18"/>
<!-- include following line when you need specific machine for the test
<param name="hostname" name="testbox1.example.com"/>
-->
</params>
<interfaces>
<eth id="nic-1" label="test-seg">
<addresses>
<address value="192.168.100.215/24"/>
</addresses>
</eth>
<!-- include following lines when specific NIC is needed
<eth id="nic-2" label="test-seg">
<params>
<param name="hwaddr" value="00:de:ad:00:be:af"/>
</params>
<addresses>
<address value="192.168.100.215/24"/>
</addresses>
</eth>
-->
</interfaces>The first element, the <params> tag, is the place to specify any requirements that are tied to the host. This might include operating system properties, any hardware requirements, or even a specific hostname --- in case the test requires only a unique machine to run.
The second part of the requirements is focused on network interfaces. The <interfaces> tag enumerates the network interfaces with their required properties and configuration. In this case we need only one ethernet interface - tag <eth>. It is possible to setup soft devices like bonding and vlans here but we will keep it simple in this guide and you can learn about it more in Quick Guides.
The most important property of the ethernet interface type is the label attribute, which specifies that interfaces with the same label can talk to each other. In our test, we will need to specify the same label to both sides of the ping test to make sure the interfaces can reach one another. Every interface in the list must have an id attribute (unique within the machine's scope) that will be used later on in the task to retrieve various information about the interface. In addition, if a unique interface is required for the test, you can add a hwaddr parameter to identify an interface by its MAC address.
All network configuration is done within the respective interface tag, in our case within the <eth> tag. In this specific case, the configuration will be simple as it is simple IP address assignment, but LNST offers a wide range of configuration options for other types of devices. For the full list of supported configuration options, please refer to the advanced Recipe XML Reference.
The requirements for the second machine will be exactly the same, because we want two machines with Fedora 18, each with a single interface that is connected to the same network segment. We will therefore not discuss them any further.
We can now put together the requirements with the configuration and finalize the first part of the recipe that is the list of machines that form the test environment:
<network>
<host id="sender">
<params>
<param name="os" value="Fedora18"/>
</params>
<interfaces>
<eth id="nic-1" label=test-seg">
<addresses>
<address value="192.168.100.215/24"/>
</addresses>
</eth>
</interfaces>
</host>
<host id="receiver">
<params>
<param name="os" value="Fedora18"/>
</params>
<interfaces>
<eth id="nic-1" label="test-seg">
<addresses>
<address value="192.168.100.216/24"/>
</addresses>
</eth>
</interfaces>
</host>
</network>As mentioned above, a test case in LNST is represented by the <task> tag and contains one or more child tags that represents steps to take within the task to complete the test case.
These are:
<run><config>-
<ctl_wait>a special command for the controller to wait before running the rest of the task, it is always run on the controller so you cannot use the host attribute with it -
<wait>to wait for completion of a command running in background -
<intr>to interrupt (SIGINT) commands running in background -
<kill>to kill (SIGKILL) commands running in back
For our example we will not be needing all of these; complete documentation on what these task parts do and how to use them is available in Recipe XML Reference. From the set above we will use only the run tag that can be used for:
- executing anything that you can enter on a command line. E.g.:
- yum install tcpdump
- echo 1 > /proc/net/ipv4/ip_forwarding
- executing existing test module from the LNST test library
Since we are writing a simple ping test we will be using the test module IcmpPing.py. You can pass arguments to a test using the ` tags. Test module commands usually accept a number of options as can be seen in the following example. All the test modules distributed with LNST are documented on pages under Test Modules. For further information on this test module visit the page IcmpPing. You can also create your own test module, visit the page Creating Your Own Test Modules.
Task for our ping test:
<task>
<run command="sleep 4" host="receiver"/>
<run module="IcmpPing" host="sender" timeout="30">
<options>
<option name="addr" value="{ip(receiver, nic-1)}"/>
<option name="count" value="40"/>
<option name="interval" value="0.2"/>
<option name="limit_rate" value="95"/>
</options>
</run>
</task>There are two commands in this example:
The host attribute defines on which of the hosts the command should be run. It's value matches one of the host id's defined in <host> tag in the recipe. So the first one would execute the command "sleep" on host reciever.
The second command would start the IcmpPing test from the LNST test library on the host sender. In this command we can also see the use of a template function ip(receiver, nic-1) which will return the IP address associated with the network interface nic-1 on the host receiver.
The complete recipe contains both the environment specification and the task wrapped inside a <lnstrecipe> tag. Additionally you can use several tasks in a recipe if they all require the same environment specification. All of these tasks will be then performed independently with LNST doing a clean-up of the hosts to the original state after each task. A complete recipe that performs our ping test would therefore look something like this:
<lnstrecipe>
<network>
<host id="sender">
<params>
<param name="os" value="Fedora18"/>
</params>
<interfaces>
<eth id="nic-1" label="test-seg">
<addresses>
<address value="192.168.100.215/24"/>
</addresses>
</eth>
</interfaces>
</host>
<host id="receiver">
<params>
<param name="os" value="Fedora18"/>
</params>
<interfaces>
<eth id="nic-1" label="test-seg">
<addresses>
<address value="192.168.100.216/24"/>
</addresses>
</eth>
</interfaces>
</host>
</network>
<task>
<run command="sleep 4" host="receiver"/>
<run module="IcmpPing" host="sender" timeout="30">
<options>
<option name="addr" value="{ip(receiver, nic-1)}"/>
<option name="count" value="40"/>
<option name="interval" value="0.2"/>
<option name="limit_rate" value="95"/>
</options>
</run>
</task>
</lnstrecipe>