Skip to content

How to Structure LNST Recipes

jtluka edited this page Aug 16, 2013 · 9 revisions

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 <machines> tag contains configuration of the machines (i.e. the test environment) 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>
    <machines/>

    <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.

1. Specify the Test Environment (Machines)

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 machines that participate in the test within the <machines> tag. Each machine 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 machine and <interfaces> defining the required interfaces and their configuration:

<machines>
    <machine id="sender">
        <params/>
        <interfaces/>
    </machine>
    <machine id="receiver">
        <params/>
        <interfaces/>
    </machine>
</machines>

1.1 Machine Requirements

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 machines to ping from one to another. Both of the machines must be connected to one network segment so they can reach one another. All this is specified within the <machine> tag. Machine 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" network="test-seg">
        <addresses>
            <address value="192.168.100.215/24"/>
        </addresses>
    </eth>
<!-- include following lines when specific NIC is needed
    <eth id="nic-2" network="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 machine. 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 QuickGuides.

The most important property of the ethernet interface type is the network attribute, which specifies the network segment this interface must be connected to. In our test, we will need to specify the same network segment 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 command sequence 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.

1.2 Putting It All Together

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:

<machines>
    <machine id="sender">
        <params>
            <param name="os" value="Fedora18"/>
        </params>
        <interfaces>
            <eth id="nic-1" network="test-seg">
                <addresses>
                    <address value="192.168.100.215/24"/>
                </addresses>
            </eth>
        </interfaces>
    </machine>
    <machine id="receiver">
        <params>
            <param name="os" value="Fedora18"/>
        </params>
        <interfaces>
            <eth id="nic-1" network="test-seg">
                <addresses>
                    <address value="192.168.100.216/24"/>
                </addresses>
            </eth>
        </interfaces>
    </machine>
</machines>

2. Create a Test Case (Task)

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.

2.1 Task parts

These are:

  • <run>
  • <config>
  • <ctl_wait> a special command for the controller to wait before running the next command, it is always run on the controller so you cannot use the machine 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 commands do and how to use them is available Documentation/RecipeXMLFormatReference#element:command.

The exec command is anything that you can enter on a command line. E.g.:

  • yum install tcpdump
  • echo 1 > /proc/net/ipv4/ip_forwarding

The test command is an implemented test module. Since we are writing a simple ping test we will be using the test module TestIcmpPing.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 Tests. For further information on this test module visit the page Tests/TestIcmpPing. You can also create your own test module, visit the page Documentation/TestModules.

Command sequence for our ping test:

<command_sequence>
  <command type="exec" machine_id="receiver" value="sleep 4"/>
  <command type="test" machine_id="sender" value="IcmpPing" 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>
  </command>
</command_sequence>

There are two commands in this example:

The machine_id attribute defines on which of the test machines the command should be run. It's value matches one of the machine IDs defined in <machine> tag in the recipe. So the first one would execute the command "sleep" on test machine reciever.

The second command would start the IcmpPing test from the LNST test library on the test machine sender. In this command we can also see the use of a template function Documentation/RecipeXMLFormatReference#ip which will return the IP address associated with the network interface nic-1 on the machine receiver.

3. Completing the recipe

The complete recipe contains both the environment specification and the command sequence wrapped inside a <lnstrecipe> tag. Additionally you can use several command sequences in a recipe if they all require the same environment specification. All of these command sequences will be then performed independently with LNST doing a clean-up of the machines to the original state after each sequence. A complete recipe that performs our ping test would therefore look something like this:

<lnstrecipe>

    <machines>
        <machine id="sender">
            <params>
                <param name="os" value="Fedora18"/>
            </params>
            <interfaces>
                <eth id="nic-1" network="test-seg">
                    <addresses>
                        <address value="192.168.100.215/24"/>
                    </addresses>
                </eth>
            </interfaces>
        </machine>
        <machine id="receiver">
            <params>
                <param name="os" value="Fedora18"/>
            </params>
            <interfaces>
                <eth id="nic-1" network="test-seg">
                    <addresses>
                        <address value="192.168.100.216/24"/>
                    </addresses>
                </eth>
            </interfaces>
        </machine>
    </machines>

    <command_sequence>
        <command type="exec" machine_id="receiver" value="sleep 4"/>
        <command type="test" machine_id="sender" value="IcmpPing" 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>
        </command>
    </command_sequence>

</lnstrecipe>

Clone this wiki locally