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():