From ef1d3e9e374badb09650c15af3af7b00658fa427 Mon Sep 17 00:00:00 2001 From: Claudio-Daniel Freire Date: Fri, 27 May 2011 15:05:26 +0200 Subject: [PATCH] Ticket #39, and a few fixes with find_candidates --- src/nepi/testbeds/planetlab/execute.py | 3 +- src/nepi/testbeds/planetlab/metadata_v01.py | 2 +- src/nepi/testbeds/planetlab/node.py | 59 +++++++++++++++++---- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/nepi/testbeds/planetlab/execute.py b/src/nepi/testbeds/planetlab/execute.py index 15065b89..4d4644de 100644 --- a/src/nepi/testbeds/planetlab/execute.py +++ b/src/nepi/testbeds/planetlab/execute.py @@ -104,7 +104,8 @@ class TestbedController(testbed_impl.TestbedController): node.assign_node_id(node_id) to_provision.add(node_id) elif not candidates: - raise RuntimeError, "Cannot assign resources for node %s, no candidates" % (guid,) + raise RuntimeError, "Cannot assign resources for node %s, no candidates sith %s" % (guid, + node.make_filter_description()) # Now do the backtracking search for a suitable solution # First with existing slice nodes diff --git a/src/nepi/testbeds/planetlab/metadata_v01.py b/src/nepi/testbeds/planetlab/metadata_v01.py index b746b5b2..c35d46b4 100644 --- a/src/nepi/testbeds/planetlab/metadata_v01.py +++ b/src/nepi/testbeds/planetlab/metadata_v01.py @@ -166,7 +166,7 @@ def create_node(testbed_instance, guid): # add constraint on number of (real) interfaces # by counting connected devices - dev_guids = testbed_instance.get_connected(guid, "node", "devs") + dev_guids = testbed_instance.get_connected(guid, "devs", "node") num_open_ifaces = sum( # count True values NODEIFACE == testbed_instance._get_factory_id(guid) for guid in dev_guids ) diff --git a/src/nepi/testbeds/planetlab/node.py b/src/nepi/testbeds/planetlab/node.py index 08ec7a7c..65143725 100644 --- a/src/nepi/testbeds/planetlab/node.py +++ b/src/nepi/testbeds/planetlab/node.py @@ -24,12 +24,12 @@ class Node(object): # There are replacements that are applied with string formatting, # so '%' has to be escaped as '%%'. 'architecture' : ('arch','value'), - 'operating_system' : ('fcdistro','value'), + 'operatingSystem' : ('fcdistro','value'), 'pl_distro' : ('pldistro','value'), - 'min_reliability' : ('reliability%(timeframe)s', ']value'), - 'max_reliability' : ('reliability%(timeframe)s', '[value'), - 'min_bandwidth' : ('bw%(timeframe)s', ']value'), - 'max_bandwidth' : ('bw%(timeframe)s', '[value'), + 'minReliability' : ('reliability%(timeframe)s', ']value'), + 'maxReliability' : ('reliability%(timeframe)s', '[value'), + 'minBandwidth' : ('bw%(timeframe)s', ']value'), + 'maxBandwidth' : ('bw%(timeframe)s', '[value'), } DEPENDS_PIDFILE = '/tmp/nepi-depends.pid' @@ -43,14 +43,14 @@ class Node(object): # Attributes self.hostname = None self.architecture = None - self.operating_system = None + self.operatingSystem = None self.pl_distro = None self.site = None self.emulation = None - self.min_reliability = None - self.max_reliability = None - self.min_bandwidth = None - self.max_bandwidth = None + self.minReliability = None + self.maxReliability = None + self.minBandwidth = None + self.maxBandwidth = None self.min_num_external_ifaces = None self.max_num_external_ifaces = None self.timeframe = 'm' @@ -106,6 +106,7 @@ class Node(object): # get initial candidates (no tag filters) basefilters = self.build_filters({}, self.BASEFILTERS) + rootfilters = basefilters.copy() if filter_slice_id: basefilters['|slice_ids'] = (filter_slice_id,) @@ -128,7 +129,7 @@ class Node(object): # don't bother if there's no filter defined if attr in applicable: - tagfilter = basefilters.copy() + tagfilter = rootfilters.copy() tagfilter['tagname'] = tagname % replacements tagfilter[expr % replacements] = getattr(self,attr) tagfilter['node_id'] = list(candidates) @@ -183,6 +184,42 @@ class Node(object): candidates = set(filter(predicate, candidates)) return candidates + + def make_filter_description(self): + """ + Makes a human-readable description of filtering conditions + for find_candidates. + """ + + # get initial candidates (no tag filters) + filters = self.build_filters({}, self.BASEFILTERS) + + # keyword-only "pseudofilters" + if self.site: + filters['peer'] = self.site + + # filter by tag, one tag at a time + applicable = self.applicable_filters + for tagfilter in self.TAGFILTERS.iteritems(): + attr, (tagname, expr) = tagfilter + + # don't bother if there's no filter defined + if attr in applicable: + filters[attr] = getattr(self,attr) + + # filter by vsys tags - special case since it doesn't follow + # the usual semantics + if self.required_vsys: + filters['vsys'] = ','.join(list(self.required_vsys)) + + # filter by iface count + if self.min_num_external_ifaces is not None or self.max_num_external_ifaces is not None: + filters['num_ifaces'] = '-'.join([ + str(self.min_num_external_ifaces or '0'), + str(self.max_num_external_ifaces or 'inf') + ]) + + return '; '.join(map('%s: %s'.__mod__,filters.iteritems())) def assign_node_id(self, node_id): self._node_id = node_id -- 2.47.0