From 63bb6c04ee9f566071c3211a76e22559595d42e6 Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Wed, 3 Jun 2015 16:17:43 +0200 Subject: [PATCH] major fix about slice tags no slice tags was exposed by sfi describe before this change we now expose them properly with a 'scope' field that can be either 'slice' or 'sliver' note that nodegroup-based tags are still silently ignored at this point --- using allocate with the 'append' option is probably the best approach anyway, with an empty list of slice tags; this avoid resetting slice tags --- sfa/planetlab/plaggregate.py | 57 ++++++++++++++----- sfa/rspecs/elements/pltag.py | 1 + .../elements/versions/pgv2SliverType.py | 29 +++++++--- 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/sfa/planetlab/plaggregate.py b/sfa/planetlab/plaggregate.py index 7604758c..32d6d933 100644 --- a/sfa/planetlab/plaggregate.py +++ b/sfa/planetlab/plaggregate.py @@ -104,7 +104,7 @@ class PlAggregate: def get_node_tags(self, filter=None): if filter is None: filter={} node_tags = {} - for node_tag in self.driver.shell.GetNodeTags(filter): + for node_tag in self.driver.shell.GetNodeTags(filter, ['tagname', 'value', 'node_id', 'node_tag_id'] ): node_tags[node_tag['node_tag_id']] = node_tag return node_tags @@ -191,12 +191,19 @@ class PlAggregate: if node_ids: node_ids = [node_id for node_id in node_ids if node_id in slice['node_ids']] slice['node_ids'] = node_ids - tags_dict = self.get_slice_tags(slice) + pltags_dict = self.get_pltags_by_node_id(slice) nodes_dict = self.get_slice_nodes(slice, options) slivers = [] for node in nodes_dict.values(): node.update(slice) - node['tags'] = tags_dict[node['node_id']] + # slice-global tags + node['slice-tags'] = pltags_dict['slice-global'] + # xxx + # this is where we chould maybe add the nodegroup slice tags, + # but it's tedious... + # xxx + # sliver tags + node['slice-tags'] += pltags_dict[node['node_id']] sliver_hrn = '%s.%s-%s' % (self.driver.hrn, slice['slice_id'], node['node_id']) node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn node['urn'] = node['sliver_id'] @@ -254,24 +261,28 @@ class PlAggregate: interface['client_id'] = "%s:%s" % (node['node_id'], if_id) rspec_node['interfaces'].append(interface) if_count+=1 - tags = [PLTag(node_tags[tag_id]) for tag_id in node['node_tag_ids'] if tag_id in node_tags] - rspec_node['tags'] = tags + # this is what describes a particular node + node_level_tags = [PLTag(node_tags[tag_id]) for tag_id in node['node_tag_ids'] if tag_id in node_tags] + rspec_node['tags'] = node_level_tags return rspec_node - def sliver_to_rspec_node(self, sliver, sites, interfaces, node_tags, \ + def sliver_to_rspec_node(self, sliver, sites, interfaces, node_tags, sliver_pltags, \ pl_initscripts, sliver_allocations): # get the granularity in second for the reservation system grain = self.driver.shell.GetLeaseGranularity() rspec_node = self.node_to_rspec_node(sliver, sites, interfaces, node_tags, pl_initscripts, grain) + for pltag in sliver_pltags: + logger.debug("Need to expose {}".format(pltag)) # xxx how to retrieve site['login_base'] rspec_node['expires'] = datetime_to_string(utcparse(sliver['expires'])) # remove interfaces from manifest rspec_node['interfaces'] = [] # add sliver info rspec_sliver = Sliver({'sliver_id': sliver['urn'], - 'name': sliver['name'], - 'type': 'plab-vserver', - 'tags': []}) + 'name': sliver['name'], + 'type': 'plab-vserver', + 'tags': sliver_pltags, + }) rspec_node['sliver_id'] = rspec_sliver['sliver_id'] if sliver['urn'] in sliver_allocations: rspec_node['client_id'] = sliver_allocations[sliver['urn']].client_id @@ -291,15 +302,29 @@ class PlAggregate: rspec_node['services'] = [service] return rspec_node - def get_slice_tags(self, slice): + def get_pltags_by_node_id(self, slice): slice_tag_ids = [] slice_tag_ids.extend(slice['slice_tag_ids']) - tags = self.driver.shell.GetSliceTags({'slice_tag_id': slice_tag_ids}) + tags = self.driver.shell.GetSliceTags({'slice_tag_id': slice_tag_ids}, + ['tagname', 'value', 'node_id', 'nodegroup_id']) # sorted by node_id - tags_dict = defaultdict(list) + pltags_dict = defaultdict(list) for tag in tags: - tags_dict[tag['node_id']] = tag - return tags_dict + # specific to a node + if tag['node_id']: + tag['scope'] = 'sliver' + pltags_dict[tag['node_id']].append(PLTag(tag)) + # restricted to a nodegroup + # for now such tags are not exposed to describe + # xxx we should also expose the nodegroup name in this case to be complete.. + elif tag['nodegroup_id']: + tag['scope'] = 'nodegroup' + pltags_dict['nodegroup'].append(PLTag(tag)) + # this tag is global to the slice + else: + tag['scope'] = 'slice' + pltags_dict['slice-global'].append(PLTag(tag)) + return pltags_dict def get_slice_nodes(self, slice, options=None): if options is None: options={} @@ -474,8 +499,10 @@ class PlAggregate: for sliver in slivers: if sliver['slice_ids_whitelist'] and sliver['slice_id'] not in sliver['slice_ids_whitelist']: continue - rspec_node = self.sliver_to_rspec_node(sliver, sites, interfaces, node_tags, + sliver_pltags = sliver['slice-tags'] + rspec_node = self.sliver_to_rspec_node(sliver, sites, interfaces, node_tags, sliver_pltags, pl_initscripts, sliver_allocation_dict) + logger.debug('rspec of type {}'.format(rspec_node.__class__.__name__)) # manifest node element shouldn't contain available attribute rspec_node.pop('available') rspec_nodes.append(rspec_node) diff --git a/sfa/rspecs/elements/pltag.py b/sfa/rspecs/elements/pltag.py index 0868a941..8234f461 100644 --- a/sfa/rspecs/elements/pltag.py +++ b/sfa/rspecs/elements/pltag.py @@ -5,5 +5,6 @@ class PLTag(Element): fields = [ 'tagname', 'value', + 'scope', ] diff --git a/sfa/rspecs/elements/versions/pgv2SliverType.py b/sfa/rspecs/elements/versions/pgv2SliverType.py index ee9797a3..b8ca2d11 100644 --- a/sfa/rspecs/elements/versions/pgv2SliverType.py +++ b/sfa/rspecs/elements/versions/pgv2SliverType.py @@ -3,6 +3,8 @@ from sfa.rspecs.elements.sliver import Sliver from sfa.rspecs.elements.versions.pgv2DiskImage import PGv2DiskImage from sfa.rspecs.elements.versions.plosv1FWRule import PLOSv1FWRule +from sfa.util.sfalogging import logger + class PGv2SliverType: @staticmethod @@ -29,16 +31,29 @@ class PGv2SliverType: PGv2SliverType.add_sliver_attributes(sliver_elem, sliver.get('tags', [])) @staticmethod - def add_sliver_attributes(xml, attributes): - if attributes: - for attribute in attributes: - if attribute['name'] == 'initscript': - xml.add_element('{%s}initscript' % xml.namespaces['planetlab'], name=attribute['value']) - elif attribute['tagname'] == 'flack_info': - attrib_elem = xml.add_element('{%s}info' % self.namespaces['flack']) + def add_sliver_attributes(xml, tags): + if tags is None: + return + for tag in tags: + tagname = tag['tagname'] if 'tagname' in tag else tag['name'] + if tagname == 'flack_info': + attrib_elem = xml.add_element('{%s}info' % self.namespaces['flack']) + try: attrib_dict = eval(tag['value']) for (key, value) in attrib_dict.items(): attrib_elem.set(key, value) + except Exception as e: + logger.warning("Could not parse dictionary in flack tag -- {}".format(e)) + elif tagname == 'initscript': + xml.add_element('{%s}initscript' % xml.namespaces['planetlab'], + name=tag['value']) + else: + xml.add_element('{%s}attribute' % (xml.namespaces['planetlab']), + name = tagname, + value = tag['value'], + scope = tag.get('scope', 'unknown'), + ) + @staticmethod def get_slivers(xml, filter=None): if filter is None: filter={} -- 2.47.0