From: Radek Pazdera rpazdera@redhat.com
This commit makes NetConfigParser accept <netdevice> options in a slightly different format. Previous format of options accepted values only as an 'value' attribute to the <option> tag. With this modification it is possible to define options also with values as a text elements of the option tag. There are now two possibilities:
<!-- The usual way --> <option name="opt" value="5" />
<!-- Longer values can be specified like this --> <option name="teamd_config"> { "device": "team1", "runner": {"name": "roundrobin"}, "ports": {"eth3": {}, "eth4": {}} } </option>
Signed-off-by: Radek Pazdera rpazdera@redhat.com --- NetConfig/NetConfigParse.py | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/NetConfig/NetConfigParse.py b/NetConfig/NetConfigParse.py index f94a73d..6538737 100644 --- a/NetConfig/NetConfigParse.py +++ b/NetConfig/NetConfigParse.py @@ -96,7 +96,17 @@ class NetConfigParse:
def _parse_options_handler(self, lst, dom_element, config): name = str(dom_element.getAttribute("name")) - value = str(dom_element.getAttribute("value")) + + value = "" + if dom_element.hasAttribute("value"): + value = str(dom_element.getAttribute("value")) + elif dom_element.hasChildNodes(): + node = dom_element.firstChild + try: + value = str(dom_element.firstChild.data) + except: + raise Exception("Invalid option value") + lst.append((name, value))
def _parse_options(self, netdev, dom_netdev, config):
From: Radek Pazdera rpazdera@redhat.com
Call to _cleanup() was added to 'all_dump' and 'config_only' actions, so the slaves are properly deconfigured when '-c' argument is present.
Signed-off-by: Radek Pazdera rpazdera@redhat.com --- NetTest/NetTestController.py | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py index 12a871d..c5cfed0 100644 --- a/NetTest/NetTestController.py +++ b/NetTest/NetTestController.py @@ -200,10 +200,14 @@ class NetTestController: def all_dump_recipe(self): self._prepare() pprint(self._recipe) + if self._docleanup: + self._cleanup() return True
def config_only_recipe(self): self._prepare() + if self._docleanup: + self._cleanup() return True
def run_recipe(self): @@ -218,7 +222,8 @@ class NetTestController: if not res: break
- self._cleanup() + if self._docleanup: + self._cleanup() return res
def eval_expression_recipe(self, expr):
From: Radek Pazdera rpazdera@redhat.com
Comments in the XML recipe might interfere with the parser in some cases and result in exceptions. The best way to deal with this is to remove them from the recipe.
Signed-off-by: Radek Pazdera rpazdera@redhat.com --- Common/XmlPreprocessor.py | 15 +++++++++++++++ NetTest/NetTestParse.py | 2 ++ 2 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/Common/XmlPreprocessor.py b/Common/XmlPreprocessor.py index 21ce86e..be2cab2 100644 --- a/Common/XmlPreprocessor.py +++ b/Common/XmlPreprocessor.py @@ -50,6 +50,21 @@ class XmlPreprocessor: else: raise XmlTemplateError("Alias name '%s' is reserved" % name)
+ def remove_comments(self, node): + """ + Remove all comment nodes from the tree. + """ + + comments = [] + for child in node.childNodes: + if child.nodeType == node.COMMENT_NODE: + comments.append(child) + else: + self.remove_comments(child) + + for comment in comments: + node.removeChild(comment) + def expand(self, node): """ Traverse DOM tree from `node' down and expand any diff --git a/NetTest/NetTestParse.py b/NetTest/NetTestParse.py index 5b5101a..68c0058 100644 --- a/NetTest/NetTestParse.py +++ b/NetTest/NetTestParse.py @@ -81,6 +81,8 @@ class NetTestParse: dom = parseString(self._recipe_xml_string) xml_prep = self._xml_prep
+ xml_prep.remove_comments(dom) + self._load_included_parts(dom) dom_nettestrecipe = dom.getElementsByTagName("nettestrecipe")[0]
From: Radek Pazdera rpazdera@redhat.com
This commit introduces team device support to LNST. Example net configuration to demonstrate usage of team with LNST was added as well.
Signed-off-by: Radek Pazdera rpazdera@redhat.com --- NetConfig/NetConfigDevNames.py | 6 ++++ NetConfig/NetConfigDevice.py | 36 +++++++++++++++++++++++++++- NetConfig/NetConfigParse.py | 2 +- example_recipes/net_configs/team1.xml | 42 +++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 example_recipes/net_configs/team1.xml
diff --git a/NetConfig/NetConfigDevNames.py b/NetConfig/NetConfigDevNames.py index a8636f6..8522e00 100644 --- a/NetConfig/NetConfigDevNames.py +++ b/NetConfig/NetConfigDevNames.py @@ -76,6 +76,9 @@ class NetConfigDevNames: def _assign_name_macvlan(self, netdev, config): self._assign_name_generic("t_macvlan", netdev, config)
+ def _assign_name_team(self, netdev, config): + self._assign_name_generic("t_team", netdev, config) + def _assign_name_vlan(self, netdev, config): real_netdev = config[netdev["slaves"][0]] vlan_tci = get_option(netdev, "vlan_tci") @@ -95,6 +98,9 @@ class NetConfigDevNames: self._assign_name_bridge(netdev, config) elif dev_type == "macvlan": self._assign_name_macvlan(netdev, config) + elif dev_type == "team": + self._assign_name_team(netdev, config) + ''' In second round assign names for vlans as they use previously assigned names diff --git a/NetConfig/NetConfigDevice.py b/NetConfig/NetConfigDevice.py index e024db7..be8e673 100644 --- a/NetConfig/NetConfigDevice.py +++ b/NetConfig/NetConfigDevice.py @@ -212,12 +212,46 @@ class NetConfigDeviceVlan(NetConfigDeviceGeneric): else: exec_cmd("vconfig rem %s" % dev_name)
+class NetConfigDeviceTeam(NetConfigDeviceGeneric): + _pidfile = None + + def _slaves_up(self): + for slaveid in get_slaves(self._netdev): + slavenetdev = self._config[slaveid] + NetConfigDevice(slavenetdev, self._config).up() + + def _slaves_down(self): + for slaveid in get_slaves(self._netdev): + slavenetdev = self._config[slaveid] + NetConfigDevice(slavenetdev, self._config).down() + + def configure(self): + self._slaves_down() + + teamd_config = get_option(self._netdev, "teamd_config") + teamd_config = teamd_config.replace('"', '\"') + + dev_name = self._netdev["name"] + pidfile = "/var/run/teamd_%s.pid" % dev_name + + exec_cmd("teamd -r -d -c "%s" -t %s -p %s" % (teamd_config, dev_name, pidfile)) + + self._pidfile = pidfile + + def deconfigure(self): + dev_name = self._netdev["name"] + pidfile = "/var/run/teamd_%s.pid" % dev_name + + exec_cmd("teamd -k -p %s" % pidfile) + self._slaves_up() + type_class_mapping = { "eth": NetConfigDeviceEth, "bond": NetConfigDeviceBond, "bridge": NetConfigDeviceBridge, "macvlan": NetConfigDeviceMacvlan, - "vlan": NetConfigDeviceVlan + "vlan": NetConfigDeviceVlan, + "team": NetConfigDeviceTeam }
def NetConfigDevice(netdev, config): diff --git a/NetConfig/NetConfigParse.py b/NetConfig/NetConfigParse.py index 6538737..95f9aa0 100644 --- a/NetConfig/NetConfigParse.py +++ b/NetConfig/NetConfigParse.py @@ -191,7 +191,7 @@ class NetConfigParse:
if dev_type == "eth": pass - elif dev_type in ["bond", "bridge", "vlan", "macvlan"]: + elif dev_type in ["bond", "bridge", "vlan", "macvlan", "team"]: self._parse_options(netdev, dom_netdev, config) self._parse_slaves(netdev, dom_netdev, config) else: diff --git a/example_recipes/net_configs/team1.xml b/example_recipes/net_configs/team1.xml new file mode 100644 index 0000000..4bebf13 --- /dev/null +++ b/example_recipes/net_configs/team1.xml @@ -0,0 +1,42 @@ +<netconfig> + <netdevice id="1" type="eth" phys_id="1" /> + <netdevice id="2" type="eth" phys_id="2" /> + <netdevice id="5" type="team"> + <options> + <!-- Team device name can be omitted from teamd config, + because it will be overridden by LNST anyway. --> + <option name="teamd_config"> + { + "runner": {"name": "roundrobin"}, + "ports": {"eth1": {}, "eth2": {}} + } + </option> + </options> + <slaves> + <slave id="1" /> + <slave id="2" /> + </slaves> + <addresses> + <address value="192.168.122.200/24" /> + </addresses> + </netdevice> + <netdevice id="3" type="eth" phys_id="3" /> + <netdevice id="4" type="eth" phys_id="4" /> + <netdevice id="6" type="team"> + <options> + <option name="teamd_config"> + { + "runner": {"name": "roundrobin"}, + "ports": {"eth3": {}, "eth4": {}} + } + </option> + </options> + <slaves> + <slave id="3" /> + <slave id="4" /> + </slaves> + <addresses> + <address value="192.168.122.210/24" /> + </addresses> + </netdevice> +</netconfig>
lnst-developers@lists.fedorahosted.org