From: Ondrej Lichtner <olichtne(a)redhat.com>
If a machine in the recipe contained a parameter that was not defined
on a pool machine that was being compared lnst would fail with a
KeyError exception. This commit fixes that.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/SlavePool.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index cd9e508..170c9ac 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -371,7 +371,8 @@ class SetupMapper:
# check machine properties
for prop_name, prop_value in template_machine["params"].iteritems():
- if pool_machine["params"][prop_name] != prop_value:
+ if prop_name not in pool_machine["params"] or\
+ pool_machine["params"][prop_name] != prop_value:
return False
# check number of devices
@@ -660,7 +661,8 @@ class SetupMapper:
def _machine_matches(self, tm, pm):
for prop_name, prop_value in tm["params"].iteritems():
- if pm["params"][prop_name] != prop_value:
+ if prop_name not in pm["params"] or\
+ pm["params"][prop_name] != prop_value:
return False
return True
--
1.8.3.1
Show replies by date
From: Ondrej Lichtner <olichtne(a)redhat.com>
This commit adds a new exception class- MapperError that can be used to
report errors that arise during machine matching. In a previous patch
where I fixed corner cases of machine matching I used SlaveMachineError
which wasn't ideal since that is used for reporting errors in
SlaveMachine xml files. So I replaced it with the MapperError.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/SlavePool.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index 170c9ac..c50cbe6 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -254,6 +254,9 @@ class SlavePool:
return machine
+class MapperError(Exception):
+ pass
+
class SetupMapper:
"""
This class can be used for matching machine setups against
@@ -338,7 +341,7 @@ class SetupMapper:
if not net_in_use:
msg = "Network '%s' contains only one machine!" %
net_name
- raise SlaveMachineError(msg)
+ raise MapperError(msg)
return topology
@@ -596,7 +599,7 @@ class SetupMapper:
for m, cons in template_topology.iteritems():
if len(cons) == 0:
msg = "Isolated machine in template topology: '%s'" %
m
- raise SlaveMachineError(msg)
+ raise MapperError(msg)
if self._map_setup(template_topology, pool_topology):
machine_map = [(tm, pm, self._iface_map[tm]) \
--
1.8.3.1
From: Ondrej Lichtner <olichtne(a)redhat.com>
This commit modifies how we fallback to matching virtual machines when
normal matching fails.
First of all there is now a logging message informing the user about
this happening.
Next we need to check the interfaces of all the machines that are
requested by the recipe for parameters. Parameters are used for matching
and restricting possible interfaces, however this doesn't make sense
when matching virtual devices since these have no parameters to set. The
only exception is the parameter 'hwaddr' which can be used to specify
what mac address should the created interface have.
And finally I added a filter of the pool machines so that only virtual
machines with the parameter 'libvirt_domain' defined are considered when
matching virtual machines - this was a bug that went unnoticed since we
all use virtual machines all the time.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/SlavePool.py | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index c50cbe6..686f20f 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -608,13 +608,35 @@ class SetupMapper:
mmap = self._format_map_dict(machine_map, network_map)
mmap["virtual"] = False
return mmap
- elif self._map_setup_virt(template_machines, pool_machines):
- machine_map = [(tm, pm, []) for tm, pm in self._machine_map]
- mmap = self._format_map_dict(machine_map, [])
- mmap["virtual"] = True
- return mmap
else:
- return None
+ logging.info("Match failed for normal machines, falling back "\
+ "to matching virtual machines.")
+
+ for m_id, m in template_machines.iteritems():
+ for if_id, interface in m["interfaces"].iteritems():
+ if "params" in interface:
+ for name, val in interface["params"].iteritems():
+ if name != "hwaddr":
+ msg = "Dynamically created interfaces "\
+ "only support the 'hwaddr' option.
"\
+ "'%s=%s' found on machine '%s'
"\
+ "interface '%s'" % (name, val,
+ m_id, if_id)
+ raise MapperError(msg)
+
+ #filter machine pool to only contain virtual machines
+ virt_pool_machines = {}
+ for m_id, m in pool_machines.iteritems():
+ if "params" in m and "libvirt_domain" in
m["params"]:
+ virt_pool_machines[m_id] = m
+
+ if self._map_setup_virt(template_machines, virt_pool_machines):
+ machine_map = [(tm, pm, []) for tm, pm in self._machine_map]
+ mmap = self._format_map_dict(machine_map, [])
+ mmap["virtual"] = True
+ return mmap
+ else:
+ return None
def _map_setup(self, template_topology, pool_topology):
--
1.8.3.1
From: Ondrej Lichtner <olichtne(a)redhat.com>
This commit reimplements the method _map_setup_virt because it turned
out that it didn't work properly for some cases. The problem was there
was no backtracking for machine matches, and therefore lnst wouldn't
find a match even if there was one.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/SlavePool.py | 51 ++++++++++++++++++++++++++++----------------
1 file changed, 33 insertions(+), 18 deletions(-)
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index 686f20f..24724be 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -692,24 +692,39 @@ class SetupMapper:
return True
+ @staticmethod
+ def _get_machine_with_most_params(machines):
+ max_machine = None
+ max_len = 0
+ for m_id, m in machines.iteritems():
+ if len(m["params"]) >= max_len:
+ max_len = len(m["params"])
+ max_machine = m_id
+
+ return max_machine
+
def _map_setup_virt(self, template_machines, pool_machines):
- available = set()
- matches = set()
- for m_id in pool_machines.iterkeys():
- available.add(m_id)
-
- for tm_id, tm in template_machines.iteritems():
- match = None
- for am_id in available:
- if self._machine_matches(tm, pool_machines[am_id]):
- match = (tm_id, am_id)
- available.remove(am_id)
- break
+ if len(template_machines) <= 0:
+ return True
- if match:
- matches.add(match)
- else:
- return False
+ machine_id = self._get_machine_with_most_params(template_machines)
+ machine = template_machines[machine_id]
- self._machine_map = list(matches)
- return True
+ for pm_id, pm in pool_machines.iteritems():
+ if not self._machine_matches(machine, pm):
+ continue
+
+ self._machine_map.add((machine_id, pm_id))
+
+ new_pool = copy.deepcopy(pool_machines)
+ del new_pool[pm_id]
+
+ new_template = copy.deepcopy(template_machines)
+ del new_template[machine_id]
+
+ if self._map_setup_virt(new_template, new_pool):
+ return True
+
+ self._machine_map.discard((machine, possible_match))
+
+ return False
--
1.8.3.1