[lnst] VirtDomainCtl: Adding TODO Comment
by Jiří Pírko
commit 069ca42413249b025c5e0da914221c49dafb94a3
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:55 2013 +0200
VirtDomainCtl: Adding TODO Comment
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Common/VirtUtils.py | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
---
diff --git a/lnst/Common/VirtUtils.py b/lnst/Common/VirtUtils.py
index ac3a928..af290e5 100644
--- a/lnst/Common/VirtUtils.py
+++ b/lnst/Common/VirtUtils.py
@@ -42,7 +42,8 @@ def _virsh(cmd):
except ExecCmdFail as err:
raise VirtUtilsError("virsh error: %s" % err)
-
+# TODO: This class should use the python bindings to libvirt,
+# not the virsh CLI interface
class VirtDomainCtl:
_name = None
10 years, 11 months
[lnst] lnst-slave: Fixing bug with packet capture
by Jiří Pírko
commit c914e1d25dce80ab14734bcb5685dc47451ba398
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:54 2013 +0200
lnst-slave: Fixing bug with packet capture
There was a problem with the packet capture feature. The files were
deleted, but not removed from the list, so when you executed a different
test, the slave tried to delete the files again which resulted in an
exception.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Slave/NetTestSlave.py | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
---
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index aac7a82..f4549f6 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -162,10 +162,12 @@ class SlaveMethods:
return True
def _remove_capture_files(self):
- for name in self._capture_files.itervalues():
+ for key, name in self._capture_files.iteritems():
logging.debug("Removing temporary packet capture file %s", name)
os.unlink(name)
+ self._capture_files.clear()
+
def _update_system_config(self, options, persistent):
system_config = self._system_config
for option, values in options.iteritems():
10 years, 11 months
[lnst] NetTestSlave: Adding system config handling
by Jiří Pírko
commit 2a62f1a8966e27e79a1f052f41268819bbf9aa72
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:53 2013 +0200
NetTestSlave: Adding system config handling
This commit moves system config handling that used to be done at the
controller to the slaves.
It makes much more sense here, as it can be cleaned up automatically in
case the controller stops responding.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Slave/NetTestSlave.py | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)
---
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index 5e71ba1..aac7a82 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -33,6 +33,7 @@ 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
+from lnst.Common.NetTestCommand import NetTestCommandSystemConfig
DefaultRPCPort = 9999
@@ -51,6 +52,7 @@ class SlaveMethods:
self._capture_files = {}
self._copy_targets = {}
self._copy_sources = {}
+ self._system_config = {}
self._cache = ResourceCache(config.get_option("cache", "dir"),
config.get_option("cache", "expiration_period"))
@@ -74,6 +76,7 @@ class SlaveMethods:
return "hello"
def bye(self):
+ self.restore_system_config()
self.clear_resource_table()
self._cache.del_old_entries()
self.reset_file_transfers()
@@ -163,6 +166,30 @@ class SlaveMethods:
logging.debug("Removing temporary packet capture file %s", name)
os.unlink(name)
+ def _update_system_config(self, options, persistent):
+ system_config = self._system_config
+ for option, values in options.iteritems():
+ if persistent:
+ if option in system_config:
+ del system_config[option]
+ else:
+ if not option in system_config:
+ initial_val = {"initial_val": values["previous_val"]}
+ system_config[option] = initial_val
+ system_config[option]["current_val"] = values["current_val"]
+
+ def restore_system_config(self):
+ logging.info("Restoring system configuration")
+ for option, values in self._system_config.iteritems():
+ try:
+ cmd_str = "echo \"%s\" >%s" % (values["initial_val"], option)
+ (stdout, stderr) = exec_cmd(cmd_str)
+ except ExecCmdFail:
+ logging.warn("Unable to restore '%s' config option!", option)
+ return False
+
+ return True
+
def run_command(self, command):
try:
cmd = NetTestCommand(self._command_context, command,
@@ -186,6 +213,7 @@ class SlaveMethods:
self._netconfig.cleanup()
self._command_context.cleanup()
self._cache.del_old_entries()
+ self.restore_system_config()
return True
def clear_resource_table(self):
10 years, 11 months
[lnst] Logs: Adding missing 'self'
by Jiří Pírko
commit 168e0f5493530988ecd69979a68a1dcb63dae653
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:52 2013 +0200
Logs: Adding missing 'self'
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Common/Logs.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/lnst/Common/Logs.py b/lnst/Common/Logs.py
index 28dda7d..284ecc2 100644
--- a/lnst/Common/Logs.py
+++ b/lnst/Common/Logs.py
@@ -162,7 +162,7 @@ class LoggingCtl:
logger.removeHandler(self.slaves[slave_id][1])
logger.removeHandler(self.slaves[slave_id][2])
- del slaves[slave_id]
+ del self.slaves[slave_id]
def add_client_log(self, slave_id, log_record):
name = self.slaves[slave_id][0]
10 years, 11 months
[lnst] Logs: Adding get_recipe_log_path()
by Jiří Pírko
commit be1b290ab00e7ab43f740875620c5cf640c8fc20
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:51 2013 +0200
Logs: Adding get_recipe_log_path()
This commit adds a new method for accessing the current logging
directory. This is required when copying packet capture files from the
slaves to the controller.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Common/Logs.py | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
---
diff --git a/lnst/Common/Logs.py b/lnst/Common/Logs.py
index 1f08265..28dda7d 100644
--- a/lnst/Common/Logs.py
+++ b/lnst/Common/Logs.py
@@ -218,3 +218,6 @@ class LoggingCtl:
file_info.setLevel(logging.INFO)
return (file_debug, file_info)
+
+ def get_recipe_log_path(self):
+ return self.recipe_log_path
10 years, 11 months
[lnst] NetTestCommandSystemConfig: Modifying result
by Jiří Pírko
commit 3325f5b9ec851355e0bc9052980e40833af26d68
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:50 2013 +0200
NetTestCommandSystemConfig: Modifying result
The results of NetTestCommandSystemConfig to include the information
about the persistence of the values set. This is later used to determine
whether to clean them up or not.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Common/NetTestCommand.py | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
---
diff --git a/lnst/Common/NetTestCommand.py b/lnst/Common/NetTestCommand.py
index 208e391..527764e 100644
--- a/lnst/Common/NetTestCommand.py
+++ b/lnst/Common/NetTestCommand.py
@@ -285,7 +285,7 @@ class NetTestCommandSystemConfig(NetTestCommandGeneric):
(stdout, stderr) = exec_cmd(cmd_str)
def run(self):
- res_data = {}
+ res_data = {"options": {}, "persistent": False}
# inline version
if "option" in self._command:
@@ -313,8 +313,11 @@ class NetTestCommandSystemConfig(NetTestCommandGeneric):
self.set_fail("Unable to set %s config option!" % option)
return
- res_data[option] = {"current_val": new_values[-1],
- "previous_val": prev_val}
+ if "persistent" in self._command:
+ res_data["persistent"] = self._command["persistent"]
+
+ res_data["options"][option] = {"current_val": new_values[-1],
+ "previous_val": prev_val}
res = {"passed": True}
res["res_data"] = res_data
10 years, 11 months
[lnst] NetTestCommand: Adding get_type() method
by Jiří Pírko
commit 91bc5d52f289b6272ed139ad6bd02711679af9fa
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:49 2013 +0200
NetTestCommand: Adding get_type() method
This commit adds the method get_type() to the NetTestCommand class for
accessing the type of the command in question.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Common/NetTestCommand.py | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
---
diff --git a/lnst/Common/NetTestCommand.py b/lnst/Common/NetTestCommand.py
index 57a9350..208e391 100644
--- a/lnst/Common/NetTestCommand.py
+++ b/lnst/Common/NetTestCommand.py
@@ -167,6 +167,9 @@ class NetTestCommand:
def get_connection_pipe(self):
return self._connection_pipe
+ def get_type(self):
+ return self._command["type"]
+
class NetTestCommandContext:
def __init__(self):
self._dict = {}
10 years, 11 months
[PATCH 00/14] NetTestController Refactoring
by Radek Pazdera
Hello everyone,
This set is a major NetTestController refactoring. Over the course of the
last year, we did a lot of conceptual changes to LNST and we took the path
of least resistance while adding them to the code. This however wasn't
working anymore, because the code was getting a bit bloated and hard to
follow. This is the first step of putting some order in it and other
will surely follow.
During this refactoring, I also changed the format of the XML recipe
based on the discussions we had. The changes are described with the
individual patch in the series.
What was left out from in this phase is the parser, which I consider
good enough for now. Ondra is working on the XML scheme for recipes so
it will be better to wait to see if we will be able to integrate the
scheme directly into parser in a reasonable way.
Other than that, I didn't focus all that much on error handling. I will
do some more tests of the corner cases and follow up with patches on
problems with that should any come up.
Please let me know, if I forgot something :).
Cheers,
-Radek
Radek Pazdera (14):
XmlProcessing: Renaming RecipeParser to LnstParser
SlaveMachineParse: Moving from NetTestParse
NetTestParse: Renaming to RecipeParse
lnst-ctl: More XML format changes
lnst-ctl: Refactoring logging initialisation
NetTestCommand: Adding get_type() method
NetTestCommandSystemConfig: Modifying result
Logs: Adding get_recipe_log_path()
Logs: Adding missing 'self'
NetTestSlave: Adding system config handling
lnst-slave: Fixing bug with packet capture
VirtDomainCtl: Adding TODO Comment
NetTestController: Major Refactoring
smoke-tests: Changing the XML format
lnst/Common/Logs.py | 26 +-
lnst/Common/NetTestCommand.py | 12 +-
lnst/Common/VirtUtils.py | 3 +-
lnst/Common/XmlProcessing.py | 28 +-
lnst/Common/XmlTemplates.py | 34 +-
lnst/Controller/Machine.py | 520 +++++++++++++++++++++++++++
lnst/Controller/NetTestController.py | 466 +++++--------------------
lnst/Controller/NetTestParse.py | 642 ----------------------------------
lnst/Controller/RecipeParse.py | 497 ++++++++++++++++++++++++++
lnst/Controller/SlaveMachineParse.py | 108 ++++++
lnst/Controller/SlavePool.py | 68 +++--
lnst/Slave/NetTestSlave.py | 32 ++-
recipes/smoke/lib/conf-bond.xml | 8 +-
recipes/smoke/lib/conf-eth.xml | 6 +-
recipes/smoke/lib/conf-team.xml | 8 +-
recipes/smoke/lib/conf-vlan.xml | 6 +-
recipes/smoke/lib/recipe-temp.xml | 6 +-
recipes/smoke/lib/req.xml | 14 -
18 files changed, 1360 insertions(+), 1124 deletions(-)
create mode 100644 lnst/Controller/Machine.py
delete mode 100644 lnst/Controller/NetTestParse.py
create mode 100644 lnst/Controller/RecipeParse.py
create mode 100644 lnst/Controller/SlaveMachineParse.py
delete mode 100644 recipes/smoke/lib/req.xml
--
1.7.7.6
10 years, 11 months
[lnst] lnst-ctl: Refactoring logging initialisation
by Jiří Pírko
commit a3bcab188ca70a2f249a5f3f83941c5b3018aafe
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:48 2013 +0200
lnst-ctl: Refactoring logging initialisation
This commit contain some cosmetic changes in the interface between the
LoggingCtl class and the NetTestController.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Common/Logs.py | 23 +++++++++++++++--------
lnst/Controller/NetTestController.py | 24 ++++++------------------
2 files changed, 21 insertions(+), 26 deletions(-)
---
diff --git a/lnst/Common/Logs.py b/lnst/Common/Logs.py
index 032a4af..1f08265 100644
--- a/lnst/Common/Logs.py
+++ b/lnst/Common/Logs.py
@@ -141,7 +141,7 @@ class LoggingCtl:
logger.removeHandler(self.recipe_handlers[1])
self.recipe_handlers = (None, None)
- def add_slave(self, name):
+ def add_slave(self, slave_id, name):
slave_log_path = os.path.join(self.recipe_log_path, name)
self._clean_folder(slave_log_path)
@@ -153,17 +153,24 @@ class LoggingCtl:
logger.addHandler(slave_info)
logger.addHandler(slave_debug)
- self.slaves[name] = (slave_info, slave_debug)
- return logger
+ self.slaves[slave_id] = (name, slave_info, slave_debug)
- def remove_slave(self, name):
- logger = logging.getLogger(name)
+ def remove_slave(self, slave_id):
+ logger = logging.getLogger(self.slaves[slave_id][0])
logger.propagate = False
- logger.removeHandler(self.slaves[name][0])
- logger.removeHandler(self.slaves[name][1])
+ logger.removeHandler(self.slaves[slave_id][1])
+ logger.removeHandler(self.slaves[slave_id][2])
+
+ del slaves[slave_id]
+
+ def add_client_log(self, slave_id, log_record):
+ name = self.slaves[slave_id][0]
+ logger = logging.getLogger(name)
- del self.slaves[name]
+ log_record['address'] = '(' + name + ')'
+ record = logging.makeLogRecord(log_record)
+ logger.handle(record)
def set_connection(self, target):
if self.transmit_handler != None:
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 55055a7..d51e66f 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -48,7 +48,7 @@ class NetTestController:
self._config = config
self._log_ctl = log_ctl
self._recipe_path = recipe_path
- self._msg_dispatcher = MessageDispatcher()
+ self._msg_dispatcher = MessageDispatcher(log_ctl)
sp = SlavePool(config.get_option('environment', 'pool_dirs'),
check_process_running("libvirtd"), config)
@@ -345,8 +345,7 @@ class NetTestController:
domain_ctl.detach_interface(dev["hwaddr"])
#clean-up slave logger
- address = socket.gethostbyname(info["hostname"])
- self._log_ctl.remove_slave(address)
+ self._log_ctl.remove_slave(machine_id)
# remove dynamically created bridges
networks = self._recipe["networks"]
@@ -650,12 +649,11 @@ class NetTestController:
return packages
class MessageDispatcher(ConnectionHandler):
- def __init__(self):
+ def __init__(self, log_ctl):
super(MessageDispatcher, self).__init__()
- self._slaves = {}
+ self._log_ctl = log_ctl
- def add_slave(self, machine_id, connection, machine_info):
- self._slaves[machine_id] = machine_info
+ def add_slave(self, machine_id, connection):
self.add_connection(machine_id, connection)
def send_message(self, machine_id, data):
@@ -681,7 +679,7 @@ class MessageDispatcher(ConnectionHandler):
def _process_message(self, message):
if message[1]["type"] == "log":
record = message[1]["record"]
- self._add_client_log(message[0], record)
+ self._log_ctl.add_client_log(message[0], record)
elif message[1]["type"] == "result":
msg = "Recieved result message from different slave %s" % message[0]
logging.debug(msg)
@@ -692,16 +690,6 @@ class MessageDispatcher(ConnectionHandler):
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)
-
def disconnect_slave(self, machine_id):
- del self._slaves[machine_id]
soc = self.get_connection(machine_id)
self.remove_connection(soc)
10 years, 11 months
[lnst] lnst-ctl: More XML format changes
by Jiří Pírko
commit 36c0678a486aaf6bb97e5e17805ccbc1c05a0e00
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Apr 18 19:51:47 2013 +0200
lnst-ctl: More XML format changes
This commit introduces (yet again) some more XML format changes. This
time, the <netdevice> and <interface> abstractions were merged together.
Now there is an only description of a machine that looks like this:
<machine id="1">
<params>
<param name="os" value="rhel6.2"/>
</params>
<interfaces>
<interface network="ttnet" id="t1" type="eth">
<params>
<param name="hwaddr" value="52:54:00:2e:d5:a8"/>
</params>
</interface>
<interface network="ttnet" id="t2" type="eth"/>
<interface id="t3" type="bond">
<slaves>
<slave id="t1"/>
<slave id="t2"/>
</slaves>
<addresses>
<address value="192.168.100.240/24"/>
</addresses>
</interface>
</interfaces>
</machine>
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
lnst/Controller/NetTestController.py | 14 +-
lnst/Controller/RecipeParse.py | 273 ++++++++++++++--------------------
lnst/Controller/SlaveMachineParse.py | 67 ++++-----
lnst/Controller/SlavePool.py | 25 ++--
4 files changed, 160 insertions(+), 219 deletions(-)
---
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index def5258..55055a7 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -123,7 +123,7 @@ class NetTestController:
def _prepare_device(self, machine_id, dev_id):
info = self._get_machineinfo(machine_id)
- dev = self._recipe["machines"][machine_id]["netdevices"][dev_id]
+ dev = self._recipe["machines"][machine_id]["interfaces"][dev_id]
dev_net_name = dev["network"]
networks = self._recipe["networks"]
@@ -166,7 +166,7 @@ class NetTestController:
br_name = brctl.get_name()
brctl.init()
- logging.info("Creating netdevice %s (%s) on machine %s",
+ logging.info("Creating interface %s (%s) on machine %s",
dev_id, dev["hwaddr"], machine_id)
domain_ctl = info["virt_domain_ctl"]
@@ -194,12 +194,12 @@ class NetTestController:
% (dev_id, machine_id)
raise NetTestError(msg)
elif len(phys_devs) > 1:
- msg = "Multiple netdevices with same address %s on machine %s" \
+ msg = "Multiple interfaces with same address %s on machine %s" \
% (dev["hwaddr"], machine_id)
raise NetTestError(msg)
def _device_ready(self, machine_id, dev_id):
- dev = self._recipe["machines"][machine_id]["netdevices"][dev_id]
+ dev = self._recipe["machines"][machine_id]["interfaces"][dev_id]
devs = self._rpc_call(machine_id,
'get_devices_by_hwaddr', dev["hwaddr"])
@@ -287,11 +287,11 @@ class NetTestController:
if prov_id:
provisioner = self._slave_pool.get_provisioner(machine_id)
logging.info("Initializing provisioned system (%s)" % prov_id)
- for device in provisioner["netdevices"].itervalues():
+ for device in provisioner["interfaces"].itervalues():
self._rpc_call(machine_id, 'set_device_down', device["hwaddr"])
machine = self._recipe["machines"][machine_id]
- for dev_id in machine["netdevices"].iterkeys():
+ for dev_id in machine["interfaces"].iterkeys():
self._prepare_device(machine_id, dev_id)
def _init_slave_rpc(self, machine_id):
@@ -339,7 +339,7 @@ class NetTestController:
if "created_devices" not in info:
continue
for dev_id, dev in reversed(info["created_devices"]):
- logging.info("Removing netdevice %s (%s) from machine %s",
+ logging.info("Removing interface %s (%s) from machine %s",
dev_id, dev["hwaddr"], machine_id)
domain_ctl = info["virt_domain_ctl"]
domain_ctl.detach_interface(dev["hwaddr"])
diff --git a/lnst/Controller/RecipeParse.py b/lnst/Controller/RecipeParse.py
index 2981099..fe155cb 100644
--- a/lnst/Controller/RecipeParse.py
+++ b/lnst/Controller/RecipeParse.py
@@ -52,8 +52,6 @@ class FirstPass(LnstParser):
"""
def parse(self, node):
- self._data["provisioning"]["setup_requirements"] = {}
-
if node.nodeType == node.DOCUMENT_NODE:
scheme = {"lnstrecipe": self._lnstrecipe}
self._process_child_nodes(node, scheme,
@@ -67,28 +65,71 @@ class FirstPass(LnstParser):
default_handler=self._ignore_tag)
def _machines(self, node, params):
+ if not "machines" in self._data:
+ self._data["machines"] = {}
+
scheme = {"machine": self._machine}
self._process_child_nodes(node, scheme,
default_handler=self._ignore_tag)
def _machine(self, node, params):
- params = {}
- params["id"] = self._get_attribute(node, "id")
+ m_id = self._get_attribute(node, "id")
+ if not m_id in self._data["machines"]:
+ self._data["machines"][m_id] = {}
+
+ if not "params" in self._data["machines"][m_id]:
+ self._data["machines"][m_id]["params"] = {}
+
+ if not "interfaces" in self._data["machines"][m_id]:
+ self._data["machines"][m_id]["interfaces"] = {}
- scheme = {"requirements": self._requirements}
+ target = self._data["machines"][m_id]["params"]
+ params = {"id": m_id, "target": target}
+ scheme = {"params": self._params,
+ "interfaces": self._interfaces}
self._process_child_nodes(node, scheme, params,
default_handler=self._ignore_tag)
- def _requirements(self, node, params):
- machine_req = self._data["provisioning"]["setup_requirements"]
+ def _params(self, node, params):
+ subparser = ParamsParse(self)
+ subparser.set_params_dict(params["target"])
+ subparser.parse(node)
+
+ def _interfaces(self, node, params):
+ params = {"id": params["id"]}
+ scheme = {"interface": self._interface}
+ self._process_child_nodes(node, scheme, params)
+
+ def _interface(self, node, params):
m_id = params["id"]
- template = {}
- template["netdevices"] = {}
- machine_req[m_id] = template
+ machine = self._data["machines"][m_id]
- subparser = RequirementsParse(self)
- subparser.set_template(template)
- subparser.parse(node)
+ if_id = self._get_attribute(node, "id")
+ if_type = self._get_attribute(node, "type")
+
+ if if_id in machine["interfaces"]:
+ msg = "Two interfaces with the same id '%s', " % if_id
+ raise XmlProcessingError(msg)
+
+ # Matching works with eth devices only
+ if if_type != "eth":
+ return
+
+ if not if_id in machine["interfaces"]:
+ machine["interfaces"][if_id] = {}
+ iface = machine["interfaces"][if_id]
+
+ iface["type"] = if_type
+ iface["network"] = self._get_attribute(node, "network")
+
+ if not "params" in machine["interfaces"][if_id]:
+ machine["interfaces"][if_id]["params"] = {}
+
+ target = machine["interfaces"][if_id]["params"]
+ params = {"target": target}
+ scheme = {"params": self._params}
+ self._process_child_nodes(node, scheme, params,
+ default_handler=self._ignore_tag)
def _ignore_tag(self, node, params):
pass
@@ -159,174 +200,65 @@ class MachineParse(LnstParser):
self._machine = recipe["machines"][self._id]
self._machine["netconfig"] = {}
- scheme = {"requirements": self._requirements,
- "netconfig": self._netconfig }
+ scheme = {"params": self._ignore_tag,
+ "interfaces": self._interfaces}
self._process_child_nodes(node, scheme)
- def _netconfig(self, node, params):
- subparser = NetConfigParse(self)
- subparser.set_machine(self._id, self._machine)
- subparser.parse(node)
-
- def _requirements(self, node, params):
- try:
- self._trigger_event("machine_ready", {"machine_id": self._id})
- except Exception as exc:
- logging.error(XmlProcessingError(str(exc), node))
- raise
-
-class ParamsParse(LnstParser):
- _params = None
-
- def set_params_dict(self, target):
- self._params = target
-
- def parse(self, node):
- scheme = {"param": self._param}
+ def _interfaces(self, node, params):
+ scheme = {"interface": self._interface}
self._process_child_nodes(node, scheme)
- def _param(self, node, params):
- name = self._get_attribute(node, "name")
-
- if self._has_attribute(node, "value"):
- value = self._get_attribute(node, "value")
- else:
- value = self._get_text_content(node)
-
- self._params[name] = value
-
-class RequirementsParse(LnstParser):
- _requirements = None
-
- def set_template(self, tmp_dict):
- self._requirements = tmp_dict
-
- def parse(self, node):
- self._requirements["params"] = {}
- self._requirements["netdevices"] = {}
-
- scheme = {"params": self._params,
- "netdevices": self._netdevices}
- params = {"target": self._requirements["params"]}
- self._process_child_nodes(node, scheme, params)
-
- def _params(self, node, params):
- subparser = ParamsParse(self)
- subparser.set_params_dict(params["target"])
+ def _interface(self, node, params):
+ subparser = InterfaceParse(self)
+ subparser.set_machine(self._id, self._machine)
subparser.parse(node)
- def _netdevices(self, node, params):
- scheme = {"netdevice": self._netdevice}
- self._process_child_nodes(node, scheme)
-
- def _netdevice(self, node, params):
- reqs = self._requirements
- phys_id = self._get_attribute(node, "phys_id")
-
- dev = reqs["netdevices"][phys_id] = {}
- dev["network"] = self._get_attribute(node, "network")
-
- dev["params"] = {}
-
- scheme = {"params": self._params}
- params = {"target": dev["params"]}
- self._process_child_nodes(node, scheme, params)
-
- if "type" in dev["params"]:
- dev["type"] = dev["params"]["type"]
-
- if "hwaddr" in dev["params"]:
- dev["hwaddr"] = normalize_hwaddr(dev["params"]["hwaddr"])
-
+ def _ignore_tag(self, node, params):
+ pass
-class NetConfigParse(LnstParser):
+class InterfaceParse(LnstParser):
_machine_id = None
_machine = None
+ _iface = None
def set_machine(self, machine_id, machine):
self._machine_id = machine_id
self._machine = machine
def parse(self, node):
- netconfig = self._machine["netconfig"]
- self._netconfig = netconfig
+ if_id = self._get_attribute(node, "id")
- devices = self._machine["netdevices"]
- self._devices = devices
+ if not if_id in self._machine["interfaces"]:
+ self._machine["interfaces"][if_id] = {}
+ self._iface = iface = self._machine["interfaces"][if_id]
- scheme = {"interface": self._interface}
- self._process_child_nodes(node, scheme)
-
- def _interface(self, node, params):
- netconfig = self._netconfig
- devices = self._devices
-
- dev_id = self._get_attribute(node, "id")
- if not dev_id in netconfig:
- netconfig[dev_id] = {}
- else:
- msg = "Netdevice 'id' used more than once"
- raise XmlProcessingError(msg, node)
+ iface["type"] = self._get_attribute(node, "type")
- dev = netconfig[dev_id]
- dev["type"] = self._get_attribute(node, "type")
-
- if self._has_attribute(node, "phys_id"):
- self._process_phys_id_attr(node, dev)
-
- params = {"dev_id": dev_id}
scheme = {"addresses": self._addresses}
- scheme["options"] = self._options
- if dev["type"] == "eth":
- pass
- elif dev["type"] in ["bond", "bridge", "vlan", "macvlan", "team"]:
+ if iface["type"] in ["bond", "bridge", "vlan", "macvlan", "team"]:
scheme["slaves"] = self._slaves
- else:
- logging.warn("unknown type \"%s\"" % dev["type"])
+ scheme["options"] = self._options
- self._process_child_nodes(node, scheme, params)
+ if self._has_attribute(node, "network"):
+ msg = "Attribute network is not supported by type '%s' " + \
+ "interfaces" % iface["type"]
+ raise XmlProcessingError(msg)
+ elif iface["type"] == "eth":
+ iface["network"] = self._get_attribute(node, "network")
+
+ scheme["params"] = self._ignore_tag
+
+ self._process_child_nodes(node, scheme)
try:
- self._trigger_event("interface_config_ready",
- {"machine_id": self._machine_id,
- "netdev_config_id": dev_id})
+ event_params = {"machine_id": self._machine_id, "if_id": if_id}
+ self._trigger_event("interface_config_ready", event_params)
except Exception as exc:
msg = "Unable to configure interface %s on machine %s [%s]." % \
- (dev_id, self._machine_id, str(exc))
+ (if_id, self._machine_id, str(exc))
logging.error(XmlProcessingError(str(msg), node))
raise
- def _process_phys_id_attr(self, node, dev):
- netconfig = self._netconfig
- devices = self._devices
-
- if dev["type"] == "eth":
- phys_id = self._get_attribute(node, "phys_id")
- self._check_phys_id(node, phys_id, netconfig)
- dev["phys_id"] = phys_id
-
- if phys_id in devices:
- phys_dev = devices[phys_id]
- if phys_dev["type"] == dev["type"]:
- dev["hwaddr"] = phys_dev["hwaddr"]
- if "name" in phys_dev:
- dev["name"] = phys_dev["name"]
- else:
- msg = "phys_id passed but does not match any device on machine"
- raise XmlProcessingError(msg, node)
- else:
- logging.warn("phys_id found on non-eth netdev, ignoring")
-
-
- @staticmethod
- def _check_phys_id(node, dev_pid, config):
- for key in config:
- if not "phys_id" in config[key]:
- continue
- if config[key]["phys_id"] == dev_pid:
- msg = "same phys_id \"%s\" used more than once" % dev_pid
- raise XmlProcessingError(msg, node)
-
def _addresses(self, node, params):
self._list_init(node, params, "addresses", {"address": self._address})
@@ -336,8 +268,7 @@ class NetConfigParse(LnstParser):
else:
addr = self._get_text_content(node)
- dev_id = params["dev_id"]
- self._netconfig[dev_id]["addresses"].append(addr)
+ self._iface["addresses"].append(addr)
def _options(self, node, params):
self._list_init(node, params, "options", {"option": self._option})
@@ -350,8 +281,7 @@ class NetConfigParse(LnstParser):
else:
value = self._get_text_content(node)
- dev_id = params["dev_id"]
- self._netconfig[dev_id]["options"].append((name, value))
+ self._iface["options"].append((name, value))
def _slaves(self, node, params):
self._list_init(node, params, "slaves", {"slave": self._slave})
@@ -362,16 +292,35 @@ class NetConfigParse(LnstParser):
else:
slave_id = self._get_text_content(node)
- dev_id = params["dev_id"]
- self._netconfig[dev_id]["slaves"].append(slave_id)
+ self._iface["slaves"].append(slave_id)
def _list_init(self, node, params, node_name, scheme):
- dev_id = params["dev_id"]
- dev = self._netconfig[dev_id]
- dev[node_name] = []
+ self._iface[node_name] = []
self._process_child_nodes(node, scheme, params)
+ def _ignore_tag(self, node, params):
+ pass
+
+class ParamsParse(LnstParser):
+ _params = None
+
+ def set_params_dict(self, target):
+ self._params = target
+
+ def parse(self, node):
+ scheme = {"param": self._param}
+ self._process_child_nodes(node, scheme)
+
+ def _param(self, node, params):
+ name = self._get_attribute(node, "name")
+
+ if self._has_attribute(node, "value"):
+ value = self._get_attribute(node, "value")
+ else:
+ value = self._get_text_content(node)
+
+ self._params[name] = value
class CommandSequenceParse(LnstParser):
def parse(self, node):
diff --git a/lnst/Controller/SlaveMachineParse.py b/lnst/Controller/SlaveMachineParse.py
index 8c0a090..0be18d6 100644
--- a/lnst/Controller/SlaveMachineParse.py
+++ b/lnst/Controller/SlaveMachineParse.py
@@ -30,7 +30,7 @@ class SlaveMachineParse(LnstParser):
def parse(self, node):
scheme = {"params": self._params,
- "netdevices": self._netdevices}
+ "interfaces": self._interfaces}
params = {"target": self._machine["params"]}
self._process_child_nodes(node, scheme, params)
@@ -46,70 +46,63 @@ class SlaveMachineParse(LnstParser):
subparser.set_params_dict(params["target"])
subparser.parse(node)
- def _netdevices(self, node, params):
- scheme = {"netdevice": self._netdevice,
+ def _interfaces(self, node, params):
+ scheme = {"interface": self._interface,
"libvirt_create": self._libvirt_create}
new_params = {"create": None}
self._process_child_nodes(node, scheme, new_params)
def _libvirt_create(self, node, params):
- scheme = {"netdevice": self._netdevice}
+ scheme = {"interface": self._interface}
new_params = {"create": "libvirt"}
self._process_child_nodes(node, scheme, new_params)
- def _netdevice(self, node, params):
+ def _interface(self, node, params):
machine = self._machine
- phys_id = self._get_attribute(node, "phys_id")
+ iface_id = self._get_attribute(node, "id")
- dev = machine["netdevices"][phys_id] = {}
- dev["create"] = params["create"]
- dev["network"] = self._get_attribute(node, "network")
- dev["params"] = {}
+ iface = machine["interfaces"][iface_id] = {}
+ iface["create"] = params["create"]
+ iface["network"] = self._get_attribute(node, "network")
+ iface["params"] = {}
- # parse device parameters
+ # parse interface parameters
scheme = {"params": self._params}
- params = {"target": dev["params"]}
+ params = {"target": iface["params"]}
self._process_child_nodes(node, scheme, params)
- if "type" in dev["params"]:
- dev["type"] = dev["params"]["type"]
+ if "type" in iface["params"]:
+ iface["type"] = iface["params"]["type"]
else:
msg = "Missing required parameter 'type'"
raise XmlProcessingError(msg, node)
- # hwaddr parameter is optional for dynamic devices,
- # but it is required by non-dynamic devices
- if dev["create"] and "hwaddr" in dev["params"]:
- dev["hwaddr"] = normalize_hwaddr(dev["params"]["hwaddr"])
+ # hwaddr parameter is optional for dynamic interface,
+ # but it is required by non-dynamic interfaces
+ if iface["create"] and "hwaddr" in iface["params"]:
+ iface["hwaddr"] = normalize_hwaddr(iface["params"]["hwaddr"])
else:
- if "hwaddr" in dev["params"]:
- dev["hwaddr"] = normalize_hwaddr(dev["params"]["hwaddr"])
+ if "hwaddr" in iface["params"]:
+ iface["hwaddr"] = normalize_hwaddr(iface["params"]["hwaddr"])
else:
msg = "Missing required parameter 'hwaddr'"
raise XmlProcessingError(msg, node)
- # name parameter is only valid when the device is not dynamic
- if "name" in dev["params"]:
- if dev["create"]:
- msg = "'name' parameter is not valid with dynamic devices"
+ # name parameter is only valid when the interface is not dynamic
+ if "name" in iface["params"]:
+ if iface["create"]:
+ msg = "'name' parameter is not valid with dynamic interfaces"
raise XmlProcessingError(msg, node)
else:
- dev["name"] = dev["params"]["name"]
+ iface["name"] = iface["params"]["name"]
- # bridge parameter is valid only when the device is dynamic
- if "libvirt_bridge" in dev["params"]:
- if dev["create"] == "libvirt":
- dev["libvirt_bridge"] = dev["params"]["libvirt_bridge"]
+ # bridge parameter is valid only when the interface is dynamic
+ if "libvirt_bridge" in iface["params"]:
+ if iface["create"] == "libvirt":
+ iface["libvirt_bridge"] = iface["params"]["libvirt_bridge"]
else:
msg = "'libvirt_bridge' parameter is not valid with" \
- "dynamic devices"
+ "dynamic ifaceices"
raise XmlProcessingError(msg, node)
-
- try:
- self._trigger_event("netdevice_ready",
- {"machine_id": self._machine_id, "dev_id": phys_id})
- except Exception as exc:
- logging.error(XmlProcessingError(str(exc), node))
- raise
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index d884c05..9a9b3cd 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -59,7 +59,7 @@ class SlavePool:
parser.set_include_root(dirname)
parser.disable_events()
- machine = {"params": {}, "netdevices": {}}
+ machine = {"params": {}, "interfaces": {}}
machine_id = re.sub("\.[xX][mM][lL]$", "", basename)
parser.set_machine(machine_id, machine)
@@ -101,7 +101,6 @@ class SlavePool:
mapper = SetupMapper()
self._map = mapper.map_setup(setup_requirements, self._pool)
-
if self._map == None:
return None
@@ -138,17 +137,17 @@ class SlavePool:
machine = copy.deepcopy(self._pool[pm_id])
- new_netdevices = {}
+ new_interfaces = {}
if_map = self._map["machines"][tm_id]["interfaces"]
for t_if, p_if in if_map.iteritems():
- new_netdevices[t_if] = machine["netdevices"][p_if]
+ new_interfaces[t_if] = machine["interfaces"][p_if]
for t_net, p_net in self._map["networks"].iteritems():
- if new_netdevices[t_if]["network"] == p_net:
- new_netdevices[t_if]["network"] = t_net
+ if new_interfaces[t_if]["network"] == p_net:
+ new_interfaces[t_if]["network"] = t_net
break
- machine["netdevices"] = new_netdevices
+ machine["interfaces"] = new_interfaces
return machine
class SetupMapper:
@@ -207,7 +206,7 @@ class SetupMapper:
networks = {}
for m_id, m_config in machine_configs.iteritems():
- for dev_id, dev_info in m_config["netdevices"].iteritems():
+ for dev_id, dev_info in m_config["interfaces"].iteritems():
net = dev_info["network"]
if not net in networks:
networks[net] = []
@@ -218,7 +217,7 @@ class SetupMapper:
topology[m_id] = []
for net_name, net in networks.iteritems():
devs_in_net = []
- for dev_id, dev_info in m_config["netdevices"].iteritems():
+ for dev_id, dev_info in m_config["interfaces"].iteritems():
if dev_info["network"] == net_name:
devs_in_net.append(dev_id)
@@ -266,8 +265,8 @@ class SetupMapper:
return False
# check number of devices
- tm_ndevs = len(template_machine["netdevices"])
- pm_ndevs = len(pool_machine["netdevices"])
+ tm_ndevs = len(template_machine["interfaces"])
+ pm_ndevs = len(pool_machine["interfaces"])
if tm_ndevs > pm_ndevs:
return False
@@ -314,8 +313,8 @@ class SetupMapper:
:rtype: Bool
"""
- t_if = self._template_machines[tm_id]["netdevices"][t_if_id]
- p_if = self._pool_machines[pm_id]["netdevices"][pm_if_id]
+ t_if = self._template_machines[tm_id]["interfaces"][t_if_id]
+ p_if = self._pool_machines[pm_id]["interfaces"][pm_if_id]
properties = ["type", "hwaddr"]
for prop_name, prop_value in t_if.iteritems():
10 years, 11 months