[lnst] recipes: Adding Smoke test recipes
by Jiří Pírko
commit a17cc7330789e4971e3fdf398c1ceda0cc65f5ad
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Mar 14 12:03:29 2013 +0100
recipes: Adding Smoke test recipes
We are breaking quite a few things at the moment (and we plan to keep
doing so for a while), so I decided to develop a small set of smoke
tests we can use while working on these changes.
These tests should cover most of the basic functionality and verify
that the changes didn't break anything crucial.
If you have any more things that should be tested, please, feel free
to add them here!
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
recipes/smoke/generate-recipes.sh | 62 +++++++++++++++++++++++++++++++++++
recipes/smoke/lib/conf-bond.xml | 13 +++++++
recipes/smoke/lib/conf-eth.xml | 7 ++++
recipes/smoke/lib/conf-team.xml | 21 ++++++++++++
recipes/smoke/lib/conf-vlan.xml | 14 ++++++++
recipes/smoke/lib/recipe-temp.xml | 19 +++++++++++
recipes/smoke/lib/req.xml | 14 ++++++++
recipes/smoke/lib/seq-bg.xml | 13 +++++++
recipes/smoke/lib/seq-exec.xml | 7 ++++
recipes/smoke/lib/seq-ping.xml | 10 ++++++
recipes/smoke/lib/seq-sysconfig.xml | 10 ++++++
11 files changed, 190 insertions(+), 0 deletions(-)
---
diff --git a/recipes/smoke/generate-recipes.sh b/recipes/smoke/generate-recipes.sh
new file mode 100755
index 0000000..d9a4e6f
--- /dev/null
+++ b/recipes/smoke/generate-recipes.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+# LNST Smoke Tests
+# Author: Radek Pazdera <rpazdera(a)redhat.com>
+# License: GNU GPLv2
+
+# This script will generate a set of recipes for assessing the very basic
+# functionality of LNST.
+
+DIR="tests/"
+LIB="../lib"
+
+echo "[LNST Smoke Tests]"
+
+echo -n "Creating '$DIR' directory for the recipes..."
+mkdir -p $DIR
+cd $DIR
+echo -e "[DONE]"
+
+sequences=""
+for seq in `ls -1 $LIB/seq-*`; do
+ echo "Found command sequence $seq"
+ sequences="$sequences\n <command_sequence source=\"$seq\"/>"
+done
+
+CONF_FILES=`ls -1 $LIB/conf-*`
+for conf in $CONF_FILES; do
+ echo "Found configuration $conf"
+done
+
+for machine1 in $CONF_FILES; do
+ for machine2 in $CONF_FILES; do
+ name1=`echo -n "$machine1" | head -c -4 | cut -c 13-`
+ name2=`echo -n "$machine2" | head -c -4 | cut -c 13-`
+ recipe_name="recipe-$name1-$name2.xml"
+ echo -ne "Generating $DIR$recipe_name..."
+ cat "$LIB/recipe-temp.xml" | \
+ sed "s|#CONF1#|$machine1|g" | \
+ sed "s|#CONF2#|$machine2|g" | \
+ sed "s|#SEQUENCES#|$sequences|g" > "$recipe_name"
+
+ echo -e "[DONE]"
+ done
+done
+
+echo ""
+
+echo "To run these recipes, you need to have a pool prepared with at"
+echo "least two machines. Both of them must have at least two test"
+echo "interfaces connected to the same network segment."
+
+echo ""
+
+echo " +-----------+ +--------+ +-----------+"
+echo " | |----------| |----------| |"
+echo " | Machine | | Switch | | Machine |"
+echo " | 1 |----------| |----------| 2 |"
+echo " | | +--------+ | |"
+echo " +-----------+ +-----------+"
+
+echo -e "\nYou can execute the set using the following command:"
+echo " ./lnst-ctl -d recipes/smoke/tests/ run"
diff --git a/recipes/smoke/lib/conf-bond.xml b/recipes/smoke/lib/conf-bond.xml
new file mode 100644
index 0000000..7e78719
--- /dev/null
+++ b/recipes/smoke/lib/conf-bond.xml
@@ -0,0 +1,13 @@
+<netconfig>
+ <interface id="if-1" phys_id="dev-1" type="eth"/>
+ <interface id="if-2" phys_id="dev-2" type="eth"/>
+ <interface id="testiface" type="bond">
+ <slaves>
+ <slave id="if-1"/>
+ <slave id="if-2"/>
+ </slaves>
+ <addresses>
+ <address value="{$testip}"/>
+ </addresses>
+ </interface>
+</netconfig>
diff --git a/recipes/smoke/lib/conf-eth.xml b/recipes/smoke/lib/conf-eth.xml
new file mode 100644
index 0000000..6df4cfb
--- /dev/null
+++ b/recipes/smoke/lib/conf-eth.xml
@@ -0,0 +1,7 @@
+<netconfig>
+ <interface id="testiface" phys_id="dev-1" type="eth">
+ <addresses>
+ <address value="{$testip}"/>
+ </addresses>
+ </interface>
+</netconfig>
diff --git a/recipes/smoke/lib/conf-team.xml b/recipes/smoke/lib/conf-team.xml
new file mode 100644
index 0000000..05c050a
--- /dev/null
+++ b/recipes/smoke/lib/conf-team.xml
@@ -0,0 +1,21 @@
+<netconfig>
+ <interface id="if-1" phys_id="dev-1" type="eth"/>
+ <interface id="if-2" phys_id="dev-2" type="eth"/>
+ <interface id="testiface" type="team">
+ <options>
+ <option name="teamd_config">
+ {
+ "hwaddr": "00:11:22:33:44:55",
+ "runner": {"name": "roundrobin"}
+ }
+ </option>
+ </options>
+ <slaves>
+ <slave id="1"/>
+ <slave id="2"/>
+ </slaves>
+ <addresses>
+ <address value="{$testip}"/>
+ </addresses>
+ </interface>
+</netconfig>
diff --git a/recipes/smoke/lib/conf-vlan.xml b/recipes/smoke/lib/conf-vlan.xml
new file mode 100644
index 0000000..7b1b657
--- /dev/null
+++ b/recipes/smoke/lib/conf-vlan.xml
@@ -0,0 +1,14 @@
+<netconfig>
+ <interface id="if-1" phys_id="dev-1" type="eth"/>
+ <interface id="testiface" type="vlan"/>
+ <options>
+ <option name="vlan_tci" value="10"/>
+ </options>
+ <slaves>
+ <slave id="1"/>
+ </slaves>
+ <addresses>
+ <address value="{$testip}"/>
+ </addresses>
+ </interface>
+</netconfig>
diff --git a/recipes/smoke/lib/recipe-temp.xml b/recipes/smoke/lib/recipe-temp.xml
new file mode 100644
index 0000000..2578cca
--- /dev/null
+++ b/recipes/smoke/lib/recipe-temp.xml
@@ -0,0 +1,19 @@
+<lnstrecipe>
+ <machines>
+ <machine id="1">
+ <define>
+ <alias name="testip" value="192.168.100.240/24"/>
+ </define>
+ <requirements source="../lib/req.xml"/>
+ <netconfig source="#CONF1#"/>
+ </machine>
+ <machine id="2">
+ <define>
+ <alias name="testip" value="192.168.100.215/24"/>
+ </define>
+ <requirements source="../lib/req.xml"/>
+ <netconfig source="#CONF2#"/>
+ </machine>
+ </machines>
+ #SEQUENCES#
+</lnstrecipe>
diff --git a/recipes/smoke/lib/req.xml b/recipes/smoke/lib/req.xml
new file mode 100644
index 0000000..57a592f
--- /dev/null
+++ b/recipes/smoke/lib/req.xml
@@ -0,0 +1,14 @@
+<requirements>
+ <netdevices>
+ <netdevice network="net" phys_id="dev-1">
+ <params>
+ <param name="type" value="eth"/>
+ </params>
+ </netdevice>
+ <netdevice network="net" phys_id="dev-2">
+ <params>
+ <param name="type" value="eth"/>
+ </params>
+ </netdevice>
+ </netdevices>
+</requirements>
diff --git a/recipes/smoke/lib/seq-bg.xml b/recipes/smoke/lib/seq-bg.xml
new file mode 100644
index 0000000..302a9f4
--- /dev/null
+++ b/recipes/smoke/lib/seq-bg.xml
@@ -0,0 +1,13 @@
+<command_sequence>
+ <command machine_id="1" timeout="30" type="test"
+ value="IcmpPing" bg_id="1">
+ <options>
+ <option name="addr" value="{ip(2,testiface)}"/>
+ <option name="count" value="40"/>
+ <option name="interval" value="0.2"/>
+ <option name="limit_rate" value="95"/>
+ </options>
+ </command>
+ <command type="ctl_wait" value="5"/>
+ <command machine_id="1" timeout="30" type="intr" value="1"/>
+</command_sequence>
diff --git a/recipes/smoke/lib/seq-exec.xml b/recipes/smoke/lib/seq-exec.xml
new file mode 100644
index 0000000..9cd014e
--- /dev/null
+++ b/recipes/smoke/lib/seq-exec.xml
@@ -0,0 +1,7 @@
+<command_sequence>
+ <command machine_id="1" timeout="30" type="exec"
+ value="[ `ip -o link | grep {devname(1,testiface)} | wc -l` -gt 0 ]"/>
+ <!-- This does not yet work for non-eth devices -->
+ <!--<command machine_id="1" timeout="30" type="exec"
+ value="[ `ip -o link | grep {hwaddr(1,testiface)} | wc -l` -gt 0 ]"/>-->
+</command_sequence>
diff --git a/recipes/smoke/lib/seq-ping.xml b/recipes/smoke/lib/seq-ping.xml
new file mode 100644
index 0000000..27dd032
--- /dev/null
+++ b/recipes/smoke/lib/seq-ping.xml
@@ -0,0 +1,10 @@
+<command_sequence>
+ <command machine_id="1" timeout="30" type="test" value="IcmpPing">
+ <options>
+ <option name="addr" value="{ip(2,testiface)}"/>
+ <option name="count" value="40"/>
+ <option name="interval" value="0.2"/>
+ <option name="limit_rate" value="95"/>
+ </options>
+ </command>
+</command_sequence>
diff --git a/recipes/smoke/lib/seq-sysconfig.xml b/recipes/smoke/lib/seq-sysconfig.xml
new file mode 100644
index 0000000..f901b7b
--- /dev/null
+++ b/recipes/smoke/lib/seq-sysconfig.xml
@@ -0,0 +1,10 @@
+<command_sequence>
+ <command machine_id="1" type="system_config">
+ <options>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="5"/>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="6"/>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="7"/>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="8"/>
+ </options>
+ </command>
+</command_sequence>
10 years, 8 months
[PATCH] NetTestParse: Fixing wrong node for exceptions
by Radek Pazdera
This patch fixes a copy-paste error of XmlProcessingErrors in
NetTestParser. These exceptions were referencing xml_dom instead of
node.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
lnst/Controller/NetTestParse.py | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lnst/Controller/NetTestParse.py b/lnst/Controller/NetTestParse.py
index 430c033..64fb34f 100644
--- a/lnst/Controller/NetTestParse.py
+++ b/lnst/Controller/NetTestParse.py
@@ -172,7 +172,7 @@ class MachineParse(RecipeParser):
try:
self._trigger_event("machine_ready", {"machine_id": self._id})
except Exception as exc:
- logging.error(XmlProcessingError(str(exc), xml_dom))
+ logging.error(XmlProcessingError(str(exc), node))
raise
class ParamsParse(RecipeParser):
@@ -330,7 +330,7 @@ class SlaveMachineParse(RecipeParser):
self._trigger_event("netdevice_ready",
{"machine_id": self._machine_id, "dev_id": phys_id})
except Exception as exc:
- logging.error(XmlProcessingError(str(exc), xml_dom))
+ logging.error(XmlProcessingError(str(exc), node))
raise
class NetConfigParse(RecipeParser):
@@ -387,7 +387,7 @@ class NetConfigParse(RecipeParser):
except Exception as exc:
msg = "Unable to configure interface %s on machine %s [%s]." % \
(dev_id, self._machine_id, str(exc))
- logging.error(XmlProcessingError(str(msg), xml_dom))
+ logging.error(XmlProcessingError(str(msg), node))
raise
def _process_phys_id_attr(self, node, dev):
--
1.7.7.6
10 years, 8 months
[PATCH] NetTestParse: Fixing a bug with params parsing
by Radek Pazdera
At the moment, lnst-ctl drops dead when you specify some parameters
in the requirements for the devices.
This patch fixes it.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
lnst/Controller/NetTestParse.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lnst/Controller/NetTestParse.py b/lnst/Controller/NetTestParse.py
index 430c033..6f7d901 100644
--- a/lnst/Controller/NetTestParse.py
+++ b/lnst/Controller/NetTestParse.py
@@ -230,10 +230,10 @@ class RequirementsParse(RecipeParser):
scheme = {"params": self._params}
params = {"target": dev["params"]}
- self._process_child_nodes(node, scheme)
+ self._process_child_nodes(node, scheme, params)
if "type" in dev["params"]:
- dev["type"] = self._get_attribute(node, "type")
+ dev["type"] = dev["params"]["type"]
if "hwaddr" in dev["params"]:
dev["hwaddr"] = normalize_hwaddr(dev["params"]["hwaddr"])
--
1.7.7.6
10 years, 8 months
[PATCH] XmlTemplates: Bug in alias processing
by Radek Pazdera
There was a bug causing a stack trace in the alias processing code in
XmlTemplates. And it actually appears it was there unnoticed for quite
a few months.
This patch fixes that.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
lnst/Common/XmlTemplates.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lnst/Common/XmlTemplates.py b/lnst/Common/XmlTemplates.py
index 26db78a..29d90d9 100644
--- a/lnst/Common/XmlTemplates.py
+++ b/lnst/Common/XmlTemplates.py
@@ -172,7 +172,7 @@ class XmlTemplates:
alias_match = re.match(self._alias_re, string)
if alias_match:
alias_name = alias_match.group(1)
- alias_obj = self._find_definition(alias_name)
+ result = self._find_definition(alias_name)
return result
--
1.7.7.6
10 years, 8 months
[PATCH] recipes: Adding Smoke test recipes
by Radek Pazdera
We are breaking quite a few things at the moment (and we plan to keep
doing so for a while), so I decided to develop a small set of smoke
tests we can use while working on these changes.
These tests should cover most of the basic functionality and verify
that the changes didn't break anything crucial.
If you have any more things that should be tested, please, feel free
to add them here!
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
recipes/smoke/generate-recipes.sh | 62 +++++++++++++++++++++++++++++++++++
recipes/smoke/lib/conf-bond.xml | 13 +++++++
recipes/smoke/lib/conf-eth.xml | 7 ++++
recipes/smoke/lib/conf-team.xml | 21 ++++++++++++
recipes/smoke/lib/conf-vlan.xml | 14 ++++++++
recipes/smoke/lib/recipe-temp.xml | 19 +++++++++++
recipes/smoke/lib/req.xml | 14 ++++++++
recipes/smoke/lib/seq-bg.xml | 13 +++++++
recipes/smoke/lib/seq-exec.xml | 7 ++++
recipes/smoke/lib/seq-ping.xml | 10 ++++++
recipes/smoke/lib/seq-sysconfig.xml | 10 ++++++
11 files changed, 190 insertions(+), 0 deletions(-)
create mode 100755 recipes/smoke/generate-recipes.sh
create mode 100644 recipes/smoke/lib/conf-bond.xml
create mode 100644 recipes/smoke/lib/conf-eth.xml
create mode 100644 recipes/smoke/lib/conf-team.xml
create mode 100644 recipes/smoke/lib/conf-vlan.xml
create mode 100644 recipes/smoke/lib/recipe-temp.xml
create mode 100644 recipes/smoke/lib/req.xml
create mode 100644 recipes/smoke/lib/seq-bg.xml
create mode 100644 recipes/smoke/lib/seq-exec.xml
create mode 100644 recipes/smoke/lib/seq-ping.xml
create mode 100644 recipes/smoke/lib/seq-sysconfig.xml
diff --git a/recipes/smoke/generate-recipes.sh b/recipes/smoke/generate-recipes.sh
new file mode 100755
index 0000000..d9a4e6f
--- /dev/null
+++ b/recipes/smoke/generate-recipes.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+# LNST Smoke Tests
+# Author: Radek Pazdera <rpazdera(a)redhat.com>
+# License: GNU GPLv2
+
+# This script will generate a set of recipes for assessing the very basic
+# functionality of LNST.
+
+DIR="tests/"
+LIB="../lib"
+
+echo "[LNST Smoke Tests]"
+
+echo -n "Creating '$DIR' directory for the recipes..."
+mkdir -p $DIR
+cd $DIR
+echo -e "[DONE]"
+
+sequences=""
+for seq in `ls -1 $LIB/seq-*`; do
+ echo "Found command sequence $seq"
+ sequences="$sequences\n <command_sequence source=\"$seq\"/>"
+done
+
+CONF_FILES=`ls -1 $LIB/conf-*`
+for conf in $CONF_FILES; do
+ echo "Found configuration $conf"
+done
+
+for machine1 in $CONF_FILES; do
+ for machine2 in $CONF_FILES; do
+ name1=`echo -n "$machine1" | head -c -4 | cut -c 13-`
+ name2=`echo -n "$machine2" | head -c -4 | cut -c 13-`
+ recipe_name="recipe-$name1-$name2.xml"
+ echo -ne "Generating $DIR$recipe_name..."
+ cat "$LIB/recipe-temp.xml" | \
+ sed "s|#CONF1#|$machine1|g" | \
+ sed "s|#CONF2#|$machine2|g" | \
+ sed "s|#SEQUENCES#|$sequences|g" > "$recipe_name"
+
+ echo -e "[DONE]"
+ done
+done
+
+echo ""
+
+echo "To run these recipes, you need to have a pool prepared with at"
+echo "least two machines. Both of them must have at least two test"
+echo "interfaces connected to the same network segment."
+
+echo ""
+
+echo " +-----------+ +--------+ +-----------+"
+echo " | |----------| |----------| |"
+echo " | Machine | | Switch | | Machine |"
+echo " | 1 |----------| |----------| 2 |"
+echo " | | +--------+ | |"
+echo " +-----------+ +-----------+"
+
+echo -e "\nYou can execute the set using the following command:"
+echo " ./lnst-ctl -d recipes/smoke/tests/ run"
diff --git a/recipes/smoke/lib/conf-bond.xml b/recipes/smoke/lib/conf-bond.xml
new file mode 100644
index 0000000..7e78719
--- /dev/null
+++ b/recipes/smoke/lib/conf-bond.xml
@@ -0,0 +1,13 @@
+<netconfig>
+ <interface id="if-1" phys_id="dev-1" type="eth"/>
+ <interface id="if-2" phys_id="dev-2" type="eth"/>
+ <interface id="testiface" type="bond">
+ <slaves>
+ <slave id="if-1"/>
+ <slave id="if-2"/>
+ </slaves>
+ <addresses>
+ <address value="{$testip}"/>
+ </addresses>
+ </interface>
+</netconfig>
diff --git a/recipes/smoke/lib/conf-eth.xml b/recipes/smoke/lib/conf-eth.xml
new file mode 100644
index 0000000..6df4cfb
--- /dev/null
+++ b/recipes/smoke/lib/conf-eth.xml
@@ -0,0 +1,7 @@
+<netconfig>
+ <interface id="testiface" phys_id="dev-1" type="eth">
+ <addresses>
+ <address value="{$testip}"/>
+ </addresses>
+ </interface>
+</netconfig>
diff --git a/recipes/smoke/lib/conf-team.xml b/recipes/smoke/lib/conf-team.xml
new file mode 100644
index 0000000..05c050a
--- /dev/null
+++ b/recipes/smoke/lib/conf-team.xml
@@ -0,0 +1,21 @@
+<netconfig>
+ <interface id="if-1" phys_id="dev-1" type="eth"/>
+ <interface id="if-2" phys_id="dev-2" type="eth"/>
+ <interface id="testiface" type="team">
+ <options>
+ <option name="teamd_config">
+ {
+ "hwaddr": "00:11:22:33:44:55",
+ "runner": {"name": "roundrobin"}
+ }
+ </option>
+ </options>
+ <slaves>
+ <slave id="1"/>
+ <slave id="2"/>
+ </slaves>
+ <addresses>
+ <address value="{$testip}"/>
+ </addresses>
+ </interface>
+</netconfig>
diff --git a/recipes/smoke/lib/conf-vlan.xml b/recipes/smoke/lib/conf-vlan.xml
new file mode 100644
index 0000000..7b1b657
--- /dev/null
+++ b/recipes/smoke/lib/conf-vlan.xml
@@ -0,0 +1,14 @@
+<netconfig>
+ <interface id="if-1" phys_id="dev-1" type="eth"/>
+ <interface id="testiface" type="vlan"/>
+ <options>
+ <option name="vlan_tci" value="10"/>
+ </options>
+ <slaves>
+ <slave id="1"/>
+ </slaves>
+ <addresses>
+ <address value="{$testip}"/>
+ </addresses>
+ </interface>
+</netconfig>
diff --git a/recipes/smoke/lib/recipe-temp.xml b/recipes/smoke/lib/recipe-temp.xml
new file mode 100644
index 0000000..2578cca
--- /dev/null
+++ b/recipes/smoke/lib/recipe-temp.xml
@@ -0,0 +1,19 @@
+<lnstrecipe>
+ <machines>
+ <machine id="1">
+ <define>
+ <alias name="testip" value="192.168.100.240/24"/>
+ </define>
+ <requirements source="../lib/req.xml"/>
+ <netconfig source="#CONF1#"/>
+ </machine>
+ <machine id="2">
+ <define>
+ <alias name="testip" value="192.168.100.215/24"/>
+ </define>
+ <requirements source="../lib/req.xml"/>
+ <netconfig source="#CONF2#"/>
+ </machine>
+ </machines>
+ #SEQUENCES#
+</lnstrecipe>
diff --git a/recipes/smoke/lib/req.xml b/recipes/smoke/lib/req.xml
new file mode 100644
index 0000000..57a592f
--- /dev/null
+++ b/recipes/smoke/lib/req.xml
@@ -0,0 +1,14 @@
+<requirements>
+ <netdevices>
+ <netdevice network="net" phys_id="dev-1">
+ <params>
+ <param name="type" value="eth"/>
+ </params>
+ </netdevice>
+ <netdevice network="net" phys_id="dev-2">
+ <params>
+ <param name="type" value="eth"/>
+ </params>
+ </netdevice>
+ </netdevices>
+</requirements>
diff --git a/recipes/smoke/lib/seq-bg.xml b/recipes/smoke/lib/seq-bg.xml
new file mode 100644
index 0000000..302a9f4
--- /dev/null
+++ b/recipes/smoke/lib/seq-bg.xml
@@ -0,0 +1,13 @@
+<command_sequence>
+ <command machine_id="1" timeout="30" type="test"
+ value="IcmpPing" bg_id="1">
+ <options>
+ <option name="addr" value="{ip(2,testiface)}"/>
+ <option name="count" value="40"/>
+ <option name="interval" value="0.2"/>
+ <option name="limit_rate" value="95"/>
+ </options>
+ </command>
+ <command type="ctl_wait" value="5"/>
+ <command machine_id="1" timeout="30" type="intr" value="1"/>
+</command_sequence>
diff --git a/recipes/smoke/lib/seq-exec.xml b/recipes/smoke/lib/seq-exec.xml
new file mode 100644
index 0000000..9cd014e
--- /dev/null
+++ b/recipes/smoke/lib/seq-exec.xml
@@ -0,0 +1,7 @@
+<command_sequence>
+ <command machine_id="1" timeout="30" type="exec"
+ value="[ `ip -o link | grep {devname(1,testiface)} | wc -l` -gt 0 ]"/>
+ <!-- This does not yet work for non-eth devices -->
+ <!--<command machine_id="1" timeout="30" type="exec"
+ value="[ `ip -o link | grep {hwaddr(1,testiface)} | wc -l` -gt 0 ]"/>-->
+</command_sequence>
diff --git a/recipes/smoke/lib/seq-ping.xml b/recipes/smoke/lib/seq-ping.xml
new file mode 100644
index 0000000..27dd032
--- /dev/null
+++ b/recipes/smoke/lib/seq-ping.xml
@@ -0,0 +1,10 @@
+<command_sequence>
+ <command machine_id="1" timeout="30" type="test" value="IcmpPing">
+ <options>
+ <option name="addr" value="{ip(2,testiface)}"/>
+ <option name="count" value="40"/>
+ <option name="interval" value="0.2"/>
+ <option name="limit_rate" value="95"/>
+ </options>
+ </command>
+</command_sequence>
diff --git a/recipes/smoke/lib/seq-sysconfig.xml b/recipes/smoke/lib/seq-sysconfig.xml
new file mode 100644
index 0000000..f901b7b
--- /dev/null
+++ b/recipes/smoke/lib/seq-sysconfig.xml
@@ -0,0 +1,10 @@
+<command_sequence>
+ <command machine_id="1" type="system_config">
+ <options>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="5"/>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="6"/>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="7"/>
+ <option name="/proc/sys/net/ipv4/igmp_max_memberships" value="8"/>
+ </options>
+ </command>
+</command_sequence>
--
1.7.7.6
10 years, 8 months
[lnst] NetTestController: reimplement communication
by Jiří Pírko
commit 8858385938cb9f4fe4916a00a0ab10c6d1087dd5
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Mar 8 16:24:46 2013 +0100
NetTestController: reimplement communication
This commit reimplements the communication from the controllers
perspective.
I added a new class MessageDispatcher that inherits the class
ConnectionHandler. This class adds new methods that can be easily used
to send messages to the slaves. It encapsulates communication with every
slave used by the controller. For this reason this patch also removes
the rpc objects from machines infos and related methods. Instead we
create a normal TCP socket that is stored in the MessageDispatcher
object.
For compatibility reasons I simple rewrote the _rpc_call method so that
the communication just works with through the MessageDispatcher but I
expect that this will change in the future when we refactor the rest of
the controller.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
lnst/Controller/NetTestController.py | 104 ++++++++++++++++++++++------------
1 files changed, 68 insertions(+), 36 deletions(-)
---
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index c034f33..e84c658 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -30,6 +30,8 @@ from lnst.Common.NetTestCommand import NetTestCommandContext, NetTestCommand
from lnst.Common.NetTestCommand import str_command
from lnst.Controller.NetTestParse import NetTestParse
from lnst.Controller.SlavePool import SlavePool
+from lnst.Common.ConnectionHandler import send_data, recv_data
+from lnst.Common.ConnectionHandler import ConnectionHandler
class NetTestError(Exception):
pass
@@ -46,6 +48,7 @@ class NetTestController:
self._config = config
self._log_ctl = log_ctl
self._recipe_path = recipe_path
+ self._msg_dispatcher = MessageDispatcher()
sp = SlavePool(config.get_option('environment', 'pool_dirs'),
check_process_running("libvirtd"))
@@ -89,15 +92,6 @@ class NetTestController:
return info
- def _get_machinerpc(self, machine_id):
- try:
- rpc = self._get_machineinfo(machine_id)["rpc"]
- except KeyError:
- msg = "XMLRPC connection required, but not yet available"
- raise NetTestError(msg)
-
- return rpc
-
@staticmethod
def _session_die(session, status):
logging.debug("%s terminated with status %s", session.command, status)
@@ -244,14 +238,13 @@ class NetTestController:
domain_ctl = VirtDomainCtl(info["libvirt_domain"])
info["virt_domain_ctl"] = domain_ctl
- if not "rpc" in info:
- self._init_slave_logging(machine_id)
- self._init_slave_rpc(machine_id)
+ self._init_slave_logging(machine_id)
+ self._init_slave_rpc(machine_id)
- info["configured_interfaces"] = []
+ info["configured_interfaces"] = []
- self._rpc_call(machine_id, "clear_resource_table")
- required = self._resource_table
+ self._rpc_call(machine_id, "clear_resource_table")
+ required = self._resource_table
if self._docleanup and not info["skip_cleanup"]:
self._rpc_call(machine_id, 'machine_cleanup')
@@ -310,9 +303,9 @@ class NetTestController:
port = self._config.get_option('environment', 'rpcport')
logging.info("Connecting to RPC on machine %s", hostname)
- url = "http://%s:%d" % (hostname, port)
- rpc = ServerProxy(url, allow_none = True)
- info["rpc"] = rpc
+ rpc = socket.create_connection((hostname, port))
+ self._msg_dispatcher.add_slave(machine_id, rpc, info)
+
if self._rpc_call(machine_id, 'hello', self._recipe_path) != "hello":
msg = "Unable to establish RPC connection to machine %s. " \
% hostname
@@ -330,7 +323,7 @@ class NetTestController:
return
for machine_id in self._recipe["machines"]:
info = self._get_machineinfo(machine_id)
- if "rpc" not in info or "configured_interfaces" not in info:
+ if "configured_interfaces" not in info:
continue
self._rpc_call(machine_id, "bye")
@@ -557,26 +550,16 @@ class NetTestController:
info["system_config"] = {}
def _rpc_call(self, machine_id, method_name, *args):
- rpc = self._get_machinerpc(machine_id)
- rpc_method = getattr(rpc, method_name)
-
- result = rpc_method(*args)
+ data = {}
+ data["type"] = "command"
+ data["method_name"] = method_name
+ data["args"] = args
- logs = rpc.get_new_logs()
- self._add_client_logs(machine_id, logs)
- return result
+ self._msg_dispatcher.send_message(machine_id, data)
- def _add_client_logs(self, machine_id, logs):
- info = self._get_machineinfo(machine_id)
- address = socket.gethostbyname(info['hostname'])
- logger = info['logger']
+ result = self._msg_dispatcher.wait_for_result(machine_id)
- for log in logs:
- data = log.data
- data = pickle.loads(data)
- data['address'] = '(' + address + ')'
- record = logging.makeLogRecord(data)
- logger.handle(record)
+ return result
def _copy_to_slave(self, local_path, machine_id, remote_path=None):
remote_path = self._rpc_call(machine_id, "start_copy_to", remote_path)
@@ -653,3 +636,52 @@ class NetTestController:
packages[pkg_name] = {"path": pkg_path,
"hash": pkg_hash}
return packages
+
+class MessageDispatcher(ConnectionHandler):
+ def __init__(self):
+ super(MessageDispatcher, self).__init__()
+ self._slaves = {}
+
+ def add_slave(self, machine_id, connection, machine_info):
+ self._slaves[machine_id] = machine_info
+ self.add_connection(machine_id, connection)
+
+ def send_message(self, machine_id, data):
+ soc = self.get_connection(machine_id)
+
+ if send_data(soc, data) == False:
+ msg = "Connection error from slave %s" % machine_id
+ raise NetTestError(msg)
+
+ def wait_for_result(self, machine_id):
+ wait = True
+ while wait:
+ messages = self.check_connections()
+ for msg in messages:
+ if msg[1]["type"] == "result" and msg[0] == machine_id:
+ wait = False
+ result = msg[1]["result"]
+ else:
+ self._process_message(msg)
+
+ return result
+
+ def _process_message(self, message):
+ if message[1]["type"] == "log":
+ record = message[1]["record"]
+ self._add_client_log(message[0], record)
+ elif message[1]["type"] == "result":
+ msg = "Recieved result message from different slave %s" % message[0]
+ logging.debug(msg)
+ else:
+ msg = "Unknown message type: %s" % message[1]["type"]
+ raise NetTestError(msg)
+
+ def _add_client_log(self, machine_id, log_record):
+ info = self._slaves[machine_id]
+ address = socket.gethostbyname(info['hostname'])
+ logger = info['logger']
+
+ log_record['address'] = '(' + address + ')'
+ record = logging.makeLogRecord(log_record)
+ logger.handle(record)
10 years, 8 months
[lnst] NetTestSlave: new Slave implementation
by Jiří Pírko
commit b8ecafc332400e9b2374e1fa814ecc4792539976
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Mar 8 16:24:45 2013 +0100
NetTestSlave: new Slave implementation
This commit adds a new class ServerHandler, reimplements the
NetTestSlave class and renames the class NetTestSlaveXMLRPC to
SlaveMethods.
The NetTestSlave class implements the control flow of the slave
machines. Its run method contains the main loop in which we try to
accept a new connection and proccess recieved messages. The messages are
processed by the function _process_msg and if the message represents a
command recieved from the controller it is relayed to a SlaveMethods
object.
The handling of sockets and pipes used in communication is located in
the class ServerHandler that contains the server socket and the socket
representing the connection from the controller. And to track the
controller socket and the communication pipes it uses a
ConnectionHandler object.
I renamed the NetTestSlaveXMLRPC class to SlaveMethods because it more
closely resebles how it is used by the NetTestSlave.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
lnst/Slave/NetTestSlave.py | 128 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 127 insertions(+), 1 deletions(-)
---
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index 8827d2a..5a00b0d 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -14,6 +14,8 @@ jpirko(a)redhat.com (Jiri Pirko)
import signal
import select, logging
import os
+import datetime
+import socket
from time import sleep
from xmlrpclib import Binary
from tempfile import NamedTemporaryFile
@@ -28,10 +30,12 @@ from lnst.Common.NetTestCommand import CommandException, NetTestCommand
from lnst.Slave.NetConfig import NetConfig
from lnst.Slave.NetConfigDevice import NetConfigDeviceAllCleanup
from lnst.Common.Utils import check_process_running
+from lnst.Common.ConnectionHandler import recv_data, send_data
+from lnst.Common.ConnectionHandler import ConnectionHandler
DefaultRPCPort = 9999
-class NetTestSlaveXMLRPC:
+class SlaveMethods:
'''
Exported xmlrpc methods
'''
@@ -255,3 +259,125 @@ class NetTestSlaveXMLRPC:
for file_handle in self._copy_sources.itervalues():
file_handle.close()
self._copy_sources = {}
+
+class ServerHandler(object):
+ def __init__(self, addr):
+ self._connection_handler = ConnectionHandler()
+ try:
+ self._s_socket = socket.socket()
+ self._s_socket.bind(addr)
+ self._s_socket.listen(1)
+ except socket.error as e:
+ logging.error(e[1])
+ exit(1)
+
+ self._c_socket = None
+
+ def accept_connection(self):
+ self._c_socket, addr = self._s_socket.accept()
+ self._c_socket = (self._c_socket, addr[0])
+ logging.info("Recieved connection from %s" % self._c_socket[1])
+
+ self._connection_handler.add_connection(self._c_socket[1],
+ self._c_socket[0])
+ return self._c_socket
+
+ def get_ctl_sock(self):
+ if self._c_socket != None:
+ return self._c_socket[0]
+ else:
+ return None
+
+ def get_messages(self):
+ messages = self._connection_handler.check_connections()
+ addr = self._c_socket[1]
+ if self._connection_handler.get_connection(addr) == None:
+ self._c_socket = None
+ return messages
+
+ def send_data_to_ctl(self, data):
+ if self._c_socket != None:
+ return send_data(self._c_socket[0], data)
+ else:
+ return False
+
+ def add_connection(self, id, connection):
+ self._connection_handler.add_connection(id, connection)
+
+ def remove_connection(self, id):
+ self._connection_handler.remove_connection(id, connection)
+
+ def clear_connections(self):
+ self._connection_handler.clear_connections()
+
+ def update_connections(self, connections):
+ for key, connection in connections.iteritems():
+ self.add_connection(key, connection)
+
+class NetTestSlave:
+ def __init__(self, config, log_ctl, port = DefaultRPCPort):
+ die_when_parent_die()
+
+ self._cmd_context = NetTestCommandContext()
+ self._methods = SlaveMethods(self._cmd_context, config, log_ctl)
+
+ self.register_die_signal(signal.SIGHUP)
+ self.register_die_signal(signal.SIGINT)
+ self.register_die_signal(signal.SIGTERM)
+
+ self._server_handler = ServerHandler(("", port))
+
+ self._finished = False
+
+ self._log_ctl = log_ctl
+
+ def run(self):
+ while not self._finished:
+ if self._server_handler.get_ctl_sock() == None:
+ try:
+ self._server_handler.accept_connection()
+ except socket.error:
+ continue
+ self._log_ctl.set_connection(
+ self._server_handler.get_ctl_sock())
+
+ msgs = self._server_handler.get_messages()
+
+ for msg in msgs:
+ self._process_msg(msg[1])
+
+ if self._server_handler.get_ctl_sock() == None:
+ self._log_ctl.cancel_connection()
+
+ def _process_msg(self, msg):
+ if msg["type"] == "command":
+ method = getattr(self._methods, msg["method_name"], None)
+ if method != None:
+ result = method(*msg["args"])
+ response = {"type": "result", "result": result}
+ if not self._server_handler.send_data_to_ctl(response):
+ self._log_ctl.cancel_connection()
+ else:
+ err = "Method not found: %s" % msg["method_name"]
+ response = {"type": "error", "err": err}
+ if not self._server_handler.send_data_to_ctl(response):
+ self._log_ctl.cancel_connection()
+
+ elif msg["type"] == "log":
+ if not self._server_handler.send_data_to_ctl(msg):
+ self._log_ctl.cancel_connection()
+ elif msg["type"] == "exception":
+ if not self._server_handler.send_data_to_ctl(msg):
+ self._log_ctl.cancel_connection()
+ else:
+ raise Exception("Recieved unknown command")
+
+ pipes = self._cmd_context.get_read_pipes()
+ self._server_handler.update_connections(pipes)
+
+ def register_die_signal(self, signum):
+ signal.signal(signum, self._signal_die_handler)
+
+ def _signal_die_handler(self, signum, frame):
+ logging.info("Caught signal %d -> dying" % signum)
+ self._finished = True
10 years, 8 months
[lnst] NetTestCommand: add pipe, set logs
by Jiří Pírko
commit 88826fae10a9944a563e81465e6ac02279953f52
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Mar 8 16:24:44 2013 +0100
NetTestCommand: add pipe, set logs
This commit adds a new pipe connection for background commands. This
pipe will be used to transmit log messages and later it will overtake
the entire communication with the background process.
I also added a method to the NetTestCommandContext class that will
retrieve the communication pipes from all the background processes- this
is a temporary solution to allow NetTestSlave to register these pipes in
its ServerHandler.
I also made the background processes to correctly use these pipes to
transport logs to the Slave application which will realy them to the
controller.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
lnst/Common/NetTestCommand.py | 22 ++++++++++++++++++++--
1 files changed, 20 insertions(+), 2 deletions(-)
---
diff --git a/lnst/Common/NetTestCommand.py b/lnst/Common/NetTestCommand.py
index 49feeae..05a7ca3 100644
--- a/lnst/Common/NetTestCommand.py
+++ b/lnst/Common/NetTestCommand.py
@@ -16,6 +16,7 @@ import sys
import signal
import imp
import pickle, traceback
+import multiprocessing
from lnst.Common.ExecCmd import exec_cmd, ExecCmdFail
def str_command(command):
@@ -58,17 +59,25 @@ class BgCommand:
return self._bg_id
def run(self):
- read_pipe, write_pipe = os.pipe()
+ read_pipe, write_pipe = os.pipe() #TODO multiprocessing
+ con_read_pipe, con_write_pipe = multiprocessing.Pipe()
self._pid = os.fork()
if self._pid:
os.close(write_pipe)
logging.debug("Running in background with"
" id \"%s\", pid \"%d\"" % (self._bg_id, self._pid))
self._read_pipe = read_pipe
- return {"passed": True}
+ self._connection_pipe = con_read_pipe
+ return {"passed": True, "pipe": self._read_pipe}
os.close(read_pipe)
os.setpgrp()
self._cmd_cls.set_handle_intr()
+ self._connection_pipe = con_write_pipe
+
+ self._log_ctl.unset_recipe()
+ self._log_ctl.cancel_connection()
+ self._log_ctl.set_connection(self._connection_pipe)
+
try:
self._cmd_cls.run()
result = self._cmd_cls.get_result()
@@ -110,6 +119,9 @@ class BgCommand:
os.close(self._read_pipe)
return result
+ def get_connection_pipe(self):
+ return self._connection_pipe
+
class NetTestCommandContext:
def __init__(self):
self._dict = {}
@@ -131,6 +143,12 @@ class NetTestCommandContext:
self._kill_all_bg_cmds()
self._dict = {}
+ def get_read_pipes(self):
+ pipes = {}
+ for key in self._dict:
+ pipes[key] = self._dict[key].get_connection_pipe()
+ return pipes
+
def NetTestCommandTest(command, resource_table):
test_name = command["value"]
if not test_name in resource_table["module"]:
10 years, 8 months
[lnst] NetTestSlave: remove current Slave communication implementation
by Jiří Pírko
commit 61a1a85e9b8233a5a2ad5af5fc49d833ed2ace51
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Mar 8 16:24:43 2013 +0100
NetTestSlave: remove current Slave communication implementation
This commit removes the current implementation of communication protocol
on the Slave. The new implementation will come in the following commit.
The commits are sepparated because I rewrote most of the code here
because the summarized patch would be confusing.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
lnst/Slave/NetTestSlave.py | 44 --------------------------------------------
1 files changed, 0 insertions(+), 44 deletions(-)
---
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index bdbf4b7..8827d2a 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -17,10 +17,8 @@ import os
from time import sleep
from xmlrpclib import Binary
from tempfile import NamedTemporaryFile
-from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
from lnst.Common.Logs import log_exc_traceback
from lnst.Common.PacketCapture import PacketCapture
-from lnst.Common.XmlRpc import Server
from lnst.Common.Utils import die_when_parent_die
from lnst.Common.NetUtils import scan_netdevs, test_tcp_connection
from lnst.Common.ExecCmd import exec_cmd
@@ -257,45 +255,3 @@ class NetTestSlaveXMLRPC:
for file_handle in self._copy_sources.itervalues():
file_handle.close()
self._copy_sources = {}
-
-class MySimpleXMLRPCServer(Server):
- def __init__(self, command_context, *args, **kwargs):
- self._finished = False
- self._command_context = command_context
- Server.__init__(self, *args, **kwargs)
-
- def register_die_signal(self, signum):
- signal.signal(signum, self._signal_die_handler)
-
- def _signal_die_handler(self, signum, frame):
- logging.info("Caught signal %d -> dying" % signum)
- self._finished = True
-
- def serve_forever_with_signal_check(self):
- while True:
- try:
- if self._finished:
- self._command_context.cleanup()
- import sys
- sys.exit()
- return
- self.handle_request()
- except select.error:
- pass
-
-class NetTestSlave:
- def __init__(self, config, log_ctl, port = DefaultRPCPort):
- die_when_parent_die()
-
- command_context = NetTestCommandContext()
- server = MySimpleXMLRPCServer(command_context,
- ("", port), SimpleXMLRPCRequestHandler,
- logRequests = False)
- server.register_die_signal(signal.SIGHUP)
- server.register_die_signal(signal.SIGINT)
- server.register_die_signal(signal.SIGTERM)
- server.register_instance(NetTestSlaveXMLRPC(command_context, config))
- self._server = server
-
- def run(self):
- self._server.serve_forever_with_signal_check()
10 years, 8 months