X-Git-Url: http://git.onelab.eu/?p=sfa.git;a=blobdiff_plain;f=sfa%2Frspecs%2Fversions%2Fpgv2.py;h=a4f59630beb2f61bbd09a65ecc1b4be435a1cd40;hp=162a1c4a1e8204d1de614448d6039cb62f6c402a;hb=796d35d54ab31e209ddf76b4584b6508b309c6c1;hpb=7428e163f0ea46daf1d2eac3422a822dcdb25652 diff --git a/sfa/rspecs/versions/pgv2.py b/sfa/rspecs/versions/pgv2.py index 162a1c4a..a4f59630 100644 --- a/sfa/rspecs/versions/pgv2.py +++ b/sfa/rspecs/versions/pgv2.py @@ -1,32 +1,261 @@ -from sfa.rspecs.rspec_elements import RSpecElement, RSpecElements +from __future__ import print_function -class PGv2: +from copy import deepcopy +from sfa.util.xrn import Xrn +from sfa.rspecs.version import RSpecVersion +from sfa.rspecs.elements.versions.pgv2Link import PGv2Link +from sfa.rspecs.elements.versions.pgv2Node import PGv2Node +from sfa.rspecs.elements.versions.pgv2SliverType import PGv2SliverType +from sfa.rspecs.elements.versions.pgv2Lease import PGv2Lease +from sfa.util.sfalogging import logger + +class PGv2(RSpecVersion): type = 'ProtoGENI' - content_type = '*' + content_type = 'ad' version = '2' - schema = 'http://www.protogeni.net/resources/rspec/2/*.xsd' - namespaces = { - 'default' : 'http://www.protogeni.net/resources/rspec/2', + schema = 'http://www.protogeni.net/resources/rspec/2/ad.xsd' + namespace = 'http://www.protogeni.net/resources/rspec/2' + extensions = { 'flack': "http://www.protogeni.net/resources/rspec/ext/flack/1", - 'planetlab': "http://www.planet-lab.org/resources/sfa/ext/planetlab/1", + 'planetlab': "http://www.planet-lab.org/resources/sfa/ext/planetlab/1", + 'plos': "http://www.planet-lab.org/resources/sfa/ext/plos/1", } - elements = [ - RSpecElement(RSpecElements.NETWORK, 'network', '//default:node[@component_manager_id][1]'), - RSpecElement(RSpecElements.NODE, 'node', '//default:node | //node'), - RSpecElement(RSpecElements.SLIVER, 'sliver', '//default:node/default:sliver_type | //node/sliver_type'), - ] - template = '' + namespaces = dict(list(extensions.items()) + [('default', namespace)]) + + # Networks + def get_networks(self): + network_names = set() + nodes = self.xml.xpath('//default:node[@component_manager_id] | //node[@component_manager_id]', + namespaces=self.namespaces) + for node in nodes: + if 'component_manager_id' in node.attrib: + network_urn = node.get('component_manager_id') + if network_urn.startswith("urn:"): + network_hrn = Xrn(network_urn).get_hrn() + else: + # some component_manager_ids are hrns instead of urns?? + network_hrn = network_urn + network_names.add(network_hrn) + network_names = list(network_names) + networks = [{"name": x} for x in network_names] + return networks + + # Nodes + + def get_nodes(self, filter=None): + return PGv2Node.get_nodes(self.xml, filter) + + def get_nodes_with_slivers(self): + return PGv2Node.get_nodes_with_slivers(self.xml) + + def add_nodes(self, nodes, check_for_dupes=False, rspec_content_type=None): + return PGv2Node.add_nodes(self.xml, nodes, rspec_content_type) + + def merge_node(self, source_node_tag): + # this is untested + self.xml.root.append(deepcopy(source_node_tag)) + + # Slivers + + def get_sliver_attributes(self, component_id, network=None): + nodes = self.get_nodes({'component_id': '*%s*' %component_id}) + try: + node = nodes[0] + sliver = node.xpath('./default:sliver_type', namespaces=self.namespaces) + if sliver is not None and isinstance(sliver, list) and len(sliver) > 0: + sliver = sliver[0] + return self.attributes_list(sliver) + else: + return [] + except: + return [] + + def get_slice_attributes(self, network=None): + slice_attributes = [] + nodes_with_slivers = self.get_nodes_with_slivers() + # TODO: default sliver attributes in the PG rspec? + default_ns_prefix = self.namespaces['default'] + for node in nodes_with_slivers: + sliver_attributes = self.get_sliver_attributes(node['component_id'], network) + for sliver_attribute in sliver_attributes: + name=str(sliver_attribute[0]) + text =str(sliver_attribute[1]) + attribs = sliver_attribute[2] + # we currently only suppor the and attributes + if 'info' in name: + attribute = {'name': 'flack_info', 'value': str(attribs), 'node_id': node} + slice_attributes.append(attribute) + elif 'initscript' in name: + if attribs is not None and 'name' in attribs: + value = attribs['name'] + else: + value = text + attribute = {'name': 'initscript', 'value': value, 'node_id': node} + slice_attributes.append(attribute) + + return slice_attributes + + def attributes_list(self, elem): + opts = [] + if elem is not None: + for e in elem: + opts.append((e.tag, str(e.text).strip(), e.attrib)) + return opts + + def get_default_sliver_attributes(self, network=None): + return [] + + def add_default_sliver_attribute(self, name, value, network=None): + pass + + def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False): + if attributes is None: attributes=[] + # all nodes hould already be present in the rspec. Remove all + # nodes that done have slivers + for hostname in hostnames: + node_elems = self.get_nodes({'component_id': '*%s*' % hostname}) + if not node_elems: + continue + node_elem = node_elems[0] + + # determine sliver types for this node + valid_sliver_types = ['emulab-openvz', 'raw-pc', 'plab-vserver', 'plab-vnode'] + requested_sliver_type = None + for sliver_type in node_elem.get('slivers', []): + if sliver_type.get('type') in valid_sliver_types: + requested_sliver_type = sliver_type['type'] + + if not requested_sliver_type: + continue + sliver = {'type': requested_sliver_type, + 'pl_tags': attributes} + + # remove available element + for available_elem in node_elem.xpath('./default:available | ./available'): + node_elem.remove(available_elem) + + # remove interface elements + for interface_elem in node_elem.xpath('./default:interface | ./interface'): + node_elem.remove(interface_elem) + + # remove existing sliver_type elements + for sliver_type in node_elem.get('slivers', []): + node_elem.element.remove(sliver_type.element) + + # set the client id + node_elem.element.set('client_id', hostname) + if sliver_urn: + pass + # TODO + # set the sliver id + #slice_id = sliver_info.get('slice_id', -1) + #node_id = sliver_info.get('node_id', -1) + #sliver_id = Xrn(xrn=sliver_urn, type='slice', id=str(node_id)).get_urn() + #node_elem.set('sliver_id', sliver_id) + + # add the sliver type elemnt + PGv2SliverType.add_slivers(node_elem.element, sliver) + + # remove all nodes without slivers + if not append: + for node_elem in self.get_nodes(): + if not node_elem['client_id']: + parent = node_elem.element.getparent() + parent.remove(node_elem.element) + + def remove_slivers(self, slivers, network=None, no_dupes=False): + PGv2Node.remove_slivers(self.xml, slivers) + + # Links + def get_links(self, network=None): + return PGv2Link.get_links(self.xml) + + def get_link_requests(self): + return PGv2Link.get_link_requests(self.xml) + + def add_links(self, links): + PGv2Link.add_links(self.xml.root, links) + + def add_link_requests(self, link_tuples, append=False): + PGv2Link.add_link_requests(self.xml.root, link_tuples, append) + + # Leases + + def get_leases(self, filter=None): + return PGv2Lease.get_leases(self.xml, filter) + + def add_leases(self, leases, network = None, no_dupes=False): + PGv2Lease.add_leases(self.xml, leases) + + # Spectrum + + def get_channels(self, filter=None): + return [] + + def add_channels(self, channels, network = None, no_dupes=False): + pass + + # Utility + + def merge(self, in_rspec): + """ + Merge contents for specified rspec with current rspec + """ + from sfa.rspecs.rspec import RSpec + # just copy over all the child elements under the root element + if isinstance(in_rspec, basestring): + in_rspec = RSpec(in_rspec) + + nodes = in_rspec.version.get_nodes() + # protogeni rspecs need to advertise the availabel sliver types + main_nodes = [] + for node in nodes: + if not node['component_name']: + # this node element is part of a lease + continue + if 'sliver' not in node or not node['sliver']: + node['sliver'] = {'name': 'plab-vserver'} + main_nodes.append(node) + self.add_nodes(main_nodes) + self.add_links(in_rspec.version.get_links()) + + # Leases + leases = in_rspec.version.get_leases() + self.add_leases(leases) + # + #rspec = RSpec(in_rspec) + #for child in rspec.xml.iterchildren(): + # self.xml.root.append(child) + + + + def cleanup(self): + # remove unncecessary elements, attributes + if self.type in ['request', 'manifest']: + # remove 'available' element from remaining node elements + self.xml.remove_element('//default:available | //available') class PGv2Ad(PGv2): - schema = 'http://www.protogeni.net/resources/rspec/2/ad.xsd' + enabled = True content_type = 'ad' - template = PGv2.template % content_type + schema = 'http://www.protogeni.net/resources/rspec/2/ad.xsd' + template = '' + +class PGv2Request(PGv2): + enabled = True + content_type = 'request' + schema = 'http://www.protogeni.net/resources/rspec/2/request.xsd' + template = '' class PGv2Manifest(PGv2): - schema = 'http://www.protogeni.net/resources/rspec/2/manifest.xsd' + enabled = True content_type = 'manifest' - template = PGv2.template % content_type + schema = 'http://www.protogeni.net/resources/rspec/2/manifest.xsd' + template = '' + + + if __name__ == '__main__': from sfa.rspecs.rspec import RSpec @@ -34,4 +263,4 @@ if __name__ == '__main__': r = RSpec('/tmp/pg.rspec') r.load_rspec_elements(PGv2.elements) r.namespaces = PGv2.namespaces - print r.get(RSpecElements.NODE) + print(r.get(RSpecElements.NODE))