X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Frspecs%2Fversions%2Fsfav1.py;h=9b778371e267df26c2b9d26f8c3a1a6dee8d911f;hb=4a9e6751f9f396f463932133b9d62fc925a99ef6;hp=3917b39bd7e0ec45533cd5597c4f5bb4d4ddcaa5;hpb=0249aa4708e409f2e0aae92417537a0af2041d5e;p=sfa.git diff --git a/sfa/rspecs/versions/sfav1.py b/sfa/rspecs/versions/sfav1.py index 3917b39b..9b778371 100644 --- a/sfa/rspecs/versions/sfav1.py +++ b/sfa/rspecs/versions/sfav1.py @@ -1,239 +1,54 @@ + + from copy import deepcopy from lxml import etree + +from sfa.util.sfalogging import logger from sfa.util.xrn import hrn_to_urn, urn_to_hrn -from sfa.util.plxrn import PlXrn -from sfa.rspecs.rspec_version import BaseVersion -from sfa.rspecs.rspec_elements import RSpecElement, RSpecElements +from sfa.rspecs.version import RSpecVersion +from sfa.rspecs.elements.element import Element from sfa.rspecs.elements.versions.pgv2Link import PGv2Link +from sfa.rspecs.elements.versions.sfav1Node import SFAv1Node +from sfa.rspecs.elements.versions.sfav1Sliver import SFAv1Sliver +from sfa.rspecs.elements.versions.sfav1Lease import SFAv1Lease + -class SFAv1(BaseVersion): +class SFAv1(RSpecVersion): enabled = True type = 'SFA' content_type = '*' version = '1' - schema = None - namespace = None + schema = '' + namespace = '' extensions = {} namespaces = None - elements = [] template = '' % type - def get_network_elements(self): - return self.xml.xpath('//network') - + # Network def get_networks(self): - return self.xml.xpath('//network[@name]/@name') - - def get_node_element(self, hostname, network=None): - if network: - names = self.xml.xpath('//network[@name="%s"]//node/hostname' % network) - else: - names = self.xml.xpath('//node/hostname') - for name in names: - if str(name.text).strip() == hostname: - return name.getparent() - return None - - def get_node_elements(self, network=None): - if network: - return self.xml.xpath('//network[@name="%s"]//node' % network) - else: - return self.xml.xpath('//node') - - def get_nodes(self, network=None): - if network == None: - nodes = self.xml.xpath('//node/hostname/text()') - else: - nodes = self.xml.xpath('//network[@name="%s"]//node/hostname/text()' % network) - - nodes = [node.strip() for node in nodes] - return nodes - - def get_nodes_with_slivers(self, network = None): - if network: - nodes = self.xml.xpath('//network[@name="%s"]//node[sliver]/hostname/text()' % network) - else: - nodes = self.xml.xpath('//node[sliver]/hostname/text()') - - nodes = [node.strip() for node in nodes] - return nodes - - def get_nodes_without_slivers(self, network=None): - xpath_nodes_without_slivers = '//node[not(sliver)]/hostname/text()' - xpath_nodes_without_slivers_in_network = '//network[@name="%s"]//node[not(sliver)]/hostname/text()' - if network: - return self.xml.xpath('//network[@name="%s"]//node[not(sliver)]/hostname/text()' % network) - else: - return self.xml.xpath('//node[not(sliver)]/hostname/text()') - - def attributes_list(self, elem): - # convert a list of attribute tags into list of tuples - # (tagnme, text_value) - opts = [] - if elem is not None: - for e in elem: - opts.append((e.tag, str(e.text).strip())) - return opts - - def get_default_sliver_attributes(self, network=None): - if network: - defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network) - else: - defaults = self.xml.xpath("//sliver_defaults") - if isinstance(defaults, list) and defaults: - defaults = defaults[0] - return self.attributes_list(defaults) - - def get_sliver_attributes(self, hostname, network=None): - attributes = [] - node = self.get_node_element(hostname, network) - #sliver = node.find("sliver") - slivers = node.xpath('./sliver') - if isinstance(slivers, list) and slivers: - attributes = self.attributes_list(slivers[0]) - return attributes - - def get_slice_attributes(self, network=None): - slice_attributes = [] - nodes_with_slivers = self.get_nodes_with_slivers(network) - for default_attribute in self.get_default_sliver_attributes(network): - attribute = {'name': str(default_attribute[0]), 'value': str(default_attribute[1]), 'node_id': None} - slice_attributes.append(attribute) - for node in nodes_with_slivers: - sliver_attributes = self.get_sliver_attributes(node, network) - for sliver_attribute in sliver_attributes: - attribute = {'name': str(sliver_attribute[0]), 'value': str(sliver_attribute[1]), 'node_id': node} - slice_attributes.append(attribute) - return slice_attributes - - def get_site_nodes(self, siteid, network=None): - if network: - nodes = self.xml.xpath('//network[@name="%s"]/site[@id="%s"]/node/hostname/text()' % \ - (network, siteid)) - else: - nodes = self.xml.xpath('//site[@id="%s"]/node/hostname/text()' % siteid) - return nodes - - 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 get_link(self, fromnode, tonode, network=None): - fromsite = fromnode.getparent() - tosite = tonode.getparent() - fromid = fromsite.get("id") - toid = tosite.get("id") - if network: - query = "//network[@name='%s']" % network + "/link[@endpoints = '%s %s']" - else: - query = "//link[@endpoints = '%s %s']" - - results = self.rspec.xpath(query % (fromid, toid)) - if not results: - results = self.rspec.xpath(query % (toid, fromid)) - return results - - def query_links(self, fromnode, tonode, network=None): - return get_link(fromnode, tonode, network) - - def get_vlinks(self, network=None): - vlinklist = [] - if network: - vlinks = self.xml.xpath("//network[@name='%s']//vlink" % network) - else: - vlinks = self.xml.xpath("//vlink") - for vlink in vlinks: - endpoints = vlink.get("endpoints") - (end1, end2) = endpoints.split() - if network: - node1 = self.xml.xpath('//network[@name="%s"]//node[@id="%s"]/hostname/text()' % \ - (network, end1))[0] - node2 = self.xml.xpath('//network[@name="%s"]//node[@id="%s"]/hostname/text()' % \ - (network, end2))[0] - else: - node1 = self.xml.xpath('//node[@id="%s"]/hostname/text()' % end1)[0] - node2 = self.xml.xpath('//node[@id="%s"]/hostname/text()' % end2)[0] - desc = "%s <--> %s" % (node1, node2) - kbps = vlink.find("kbps") - vlinklist.append((endpoints, desc, kbps.text)) - return vlinklist - - def get_vlink(self, endponts, network=None): - if network: - query = "//network[@name='%s']//vlink[@endpoints = '%s']" % (network, endpoints) - else: - query = "//vlink[@endpoints = '%s']" % (network, endpoints) - results = self.rspec.xpath(query) - return results - - def query_vlinks(self, endpoints, network=None): - return get_vlink(endpoints,network) - - - ################## - # Builder - ################## + network_elems = self.xml.xpath('//network') + networks = [network_elem.get_instance(fields=['name', 'slice']) for + network_elem in network_elems] + return networks def add_network(self, network): network_tags = self.xml.xpath('//network[@name="%s"]' % network) if not network_tags: - network_tag = etree.SubElement(self.xml.root, 'network', name=network) + network_tag = self.xml.add_element('network', name=network) else: network_tag = network_tags[0] return network_tag - def add_nodes(self, nodes, network = None, no_dupes=False): - if not isinstance(nodes, list): - nodes = [nodes] - for node in nodes: - if no_dupes and \ - self.get_node_element(node['hostname']): - # node already exists - continue + # Nodes - network_tag = self.xml.root - if 'network' in node: - network = node['network'] - network_tag = self.add_network(network) - - node_tag = etree.SubElement(network_tag, 'node') - if 'network' in node: - node_tag.set('component_manager_id', hrn_to_urn(network, 'authority+sa')) - if 'urn' in node: - node_tag.set('component_id', node['urn']) - if 'site_urn' in node: - node_tag.set('site_id', node['site_urn']) - if 'node_id' in node: - node_tag.set('node_id', 'n'+str(node['node_id'])) - if 'boot_state' in node: - node_tag.set('boot_state', node['boot_state']) - if 'hostname' in node: - node_tag.set('component_name', node['hostname']) - hostname_tag = etree.SubElement(node_tag, 'hostname').text = node['hostname'] - if 'interfaces' in node: - i = 0 - for interface in node['interfaces']: - if 'bwlimit' in interface and interface['bwlimit']: - bwlimit = etree.SubElement(node_tag, 'bw_limit', units='kbps').text = str(interface['bwlimit']/1000) - comp_id = PlXrn(auth=network, interface='node%s:eth%s' % (node['node_id'], i)).get_urn() - ipaddr = interface['ip'] - interface_tag = etree.SubElement(node_tag, 'interface', component_id=comp_id, ipv4=ipaddr) - i+=1 - if 'bw_unallocated' in node: - bw_unallocated = etree.SubElement(node_tag, 'bw_unallocated', units='kbps').text = str(node['bw_unallocated']/1000) - if 'tags' in node: - for tag in node['tags']: - # expose this hard wired list of tags, plus the ones that are marked 'sfa' in their category - if tag['tagname'] in ['fcdistro', 'arch'] or 'sfa' in tag['category'].split('/'): - tag_element = etree.SubElement(node_tag, tag['tagname']).text=tag['value'] - - if 'site' in node: - longitude = str(node['site']['longitude']) - latitude = str(node['site']['latitude']) - location = etree.SubElement(node_tag, 'location', country='unknown', \ - longitude=longitude, latitude=latitude) + def get_nodes(self, filter=None): + return SFAv1Node.get_nodes(self.xml, filter) + + def get_nodes_with_slivers(self): + return SFAv1Node.get_nodes_with_slivers(self.xml) + + def add_nodes(self, nodes, network=None, no_dupes=False, rspec_content_type=None): + SFAv1Node.add_nodes(self.xml, nodes, rspec_content_type) def merge_node(self, source_node_tag, network, no_dupes=False): if no_dupes and self.get_node_element(node['hostname']): @@ -243,109 +58,151 @@ class SFAv1(BaseVersion): network_tag = self.add_network(network) network_tag.append(deepcopy(source_node_tag)) - def add_interfaces(self, interfaces): - pass - - def add_links(self, links): - networks = self.get_network_elements() - if len(networks) > 0: - xml = networks[0] - else: - xml = self.xml - PGv2Link.add_links(xml, links) + # Slivers - def add_link_requests(self, links): - PGv2Link.add_link_requests(self.xml, links) - - def add_slivers(self, slivers, network=None, sliver_urn=None, no_dupes=False, append=False): + def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False): + if attributes is None: + attributes = [] # add slice name to network tag network_tags = self.xml.xpath('//network') if network_tags: network_tag = network_tags[0] network_tag.set('slice', urn_to_hrn(sliver_urn)[0]) - - all_nodes = self.get_nodes() - nodes_with_slivers = [sliver['hostname'] for sliver in slivers] - nodes_without_slivers = set(all_nodes).difference(nodes_with_slivers) - + # add slivers - for sliver in slivers: - node_elem = self.get_node_element(sliver['hostname'], network) - if not node_elem: continue - sliver_elem = etree.SubElement(node_elem, 'sliver') - if 'tags' in sliver: - for tag in sliver['tags']: - etree.SubElement(sliver_elem, tag['tagname']).text = value=tag['value'] - + sliver = {'name': sliver_urn, + 'pl_tags': attributes} + for hostname in hostnames: + if sliver_urn: + sliver['name'] = sliver_urn + node_elems = self.get_nodes({'component_id': '*%s*' % hostname}) + if not node_elems: + continue + node_elem = node_elems[0] + SFAv1Sliver.add_slivers(node_elem.element, sliver) + # remove all nodes without slivers if not append: - for node in nodes_without_slivers: - node_elem = self.get_node_element(node) - parent = node_elem.getparent() - parent.remove(node_elem) + for node_elem in self.get_nodes(): + if not node_elem['slivers']: + parent = node_elem.element.getparent() + parent.remove(node_elem.element) def remove_slivers(self, slivers, network=None, no_dupes=False): - for sliver in slivers: - node_elem = self.get_node_element(sliver['hostname'], network) - sliver_elem = node_elem.find('sliver') - if sliver_elem != None: - node_elem.remove(sliver_elem) + SFAv1Node.remove_slivers(self.xml, slivers) + + def get_slice_attributes(self, network=None): + attributes = [] + nodes_with_slivers = self.get_nodes_with_slivers() + for default_attribute in self.get_default_sliver_attributes(network): + attribute = default_attribute.copy() + attribute['node_id'] = None + attributes.append(attribute) + for node in nodes_with_slivers: + nodename = node['component_name'] + sliver_attributes = self.get_sliver_attributes(nodename, network) + for sliver_attribute in sliver_attributes: + sliver_attribute['node_id'] = nodename + attributes.append(sliver_attribute) + return attributes + + def add_sliver_attribute(self, component_id, name, value, network=None): + nodes = self.get_nodes({'component_id': '*%s*' % component_id}) + if nodes is not None and isinstance(nodes, list) and len(nodes) > 0: + node = nodes[0] + slivers = SFAv1Sliver.get_slivers(node) + if slivers: + sliver = slivers[0] + SFAv1Sliver.add_sliver_attribute(sliver, name, value) + else: + # should this be an assert / raise an exception? + logger.error("WARNING: failed to find component_id %s" % + component_id) + + def get_sliver_attributes(self, component_id, network=None): + nodes = self.get_nodes({'component_id': '*%s*' % component_id}) + attribs = [] + if nodes is not None and isinstance(nodes, list) and len(nodes) > 0: + node = nodes[0] + slivers = SFAv1Sliver.get_slivers(node.element) + if slivers is not None and isinstance(slivers, list) and len(slivers) > 0: + sliver = slivers[0] + attribs = SFAv1Sliver.get_sliver_attributes(sliver.element) + return attribs + + def remove_sliver_attribute(self, component_id, name, value, network=None): + attribs = self.get_sliver_attributes(component_id) + for attrib in attribs: + if attrib['name'] == name and attrib['value'] == value: + # attrib.element.delete() + parent = attrib.element.getparent() + parent.remove(attrib.element) def add_default_sliver_attribute(self, name, value, network=None): if network: - defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network) + defaults = self.xml.xpath( + "//network[@name='%s']/sliver_defaults" % network) else: - defaults = self.xml.xpath("//sliver_defaults" % network) - if not defaults : - network_tag = self.xml.xpath("//network[@name='%s']" % network) + defaults = self.xml.xpath("//sliver_defaults") + if not defaults: + if network: + network_tag = self.xml.xpath("//network[@name='%s']" % network) + else: + network_tag = self.xml.xpath("//network") if isinstance(network_tag, list): network_tag = network_tag[0] - defaults = self.xml.add_element('sliver_defaults', attrs={}, parent=network_tag) + defaults = network_tag.add_element('sliver_defaults') elif isinstance(defaults, list): defaults = defaults[0] - self.xml.add_attribute(defaults, name, value) - - def add_sliver_attribute(self, hostname, name, value, network=None): - node = self.get_node_element(hostname, network) - sliver = node.find("sliver") - self.xml.add_attribute(sliver, name, value) + SFAv1Sliver.add_sliver_attribute(defaults, name, value) - def remove_default_sliver_attribute(self, name, value, network=None): + def get_default_sliver_attributes(self, network=None): if network: - defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network) + defaults = self.xml.xpath( + "//network[@name='%s']/sliver_defaults" % network) else: - defaults = self.xml.xpath("//sliver_defaults" % network) - self.xml.remove_attribute(defaults, name, value) + defaults = self.xml.xpath("//sliver_defaults") + if not defaults: + return [] + return SFAv1Sliver.get_sliver_attributes(defaults[0]) - def remove_sliver_attribute(self, hostname, name, value, network=None): - node = self.get_node_element(hostname, network) - sliver = node.find("sliver") - self.xml.remove_attribute(sliver, name, value) + def remove_default_sliver_attribute(self, name, value, network=None): + attribs = self.get_default_sliver_attributes(network) + for attrib in attribs: + if attrib['name'] == name and attrib['value'] == value: + # attrib.element.delete() + parent = attrib.element.getparent() + parent.remove(attrib.element) - def add_vlink(self, fromhost, tohost, kbps, network=None): - fromnode = self.get_node_element(fromhost, network) - tonode = self.get_node_element(tohost, network) - links = self.get_link(fromnode, tonode, network) + # Links - for link in links: - vlink = etree.SubElement(link, "vlink") - fromid = fromnode.get("id") - toid = tonode.get("id") - vlink.set("endpoints", "%s %s" % (fromid, toid)) - self.xml.add_attribute(vlink, "kbps", kbps) + 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 remove_vlink(self, endpoints, network=None): - vlinks = self.query_vlinks(endpoints, network) - for vlink in vlinks: - vlink.getparent().remove(vlink) + def add_links(self, links): + networks = self.get_networks() + if len(networks) > 0: + xml = networks[0].element + else: + xml = self.xml + PGv2Link.add_links(xml, links) + + def add_link_requests(self, links): + PGv2Link.add_link_requests(self.xml, links) + # utility def merge(self, in_rspec): """ Merge contents for specified rspec with current rspec """ + if not in_rspec: + return + from sfa.rspecs.rspec import RSpec if isinstance(in_rspec, RSpec): rspec = in_rspec @@ -358,16 +215,32 @@ class SFAv1(BaseVersion): # just copy over all networks current_networks = self.get_networks() - networks = rspec.version.get_network_elements() + networks = rspec.version.get_networks() for network in networks: current_network = network.get('name') if current_network and current_network not in current_networks: - self.xml.root.append(network) + self.xml.append(network.element) current_networks.append(current_network) + # Leases + + def get_leases(self, filter=None): + return SFAv1Lease.get_leases(self.xml, filter) + + def add_leases(self, leases, network=None, no_dupes=False): + SFAv1Lease.add_leases(self.xml, leases) + + # Spectrum + + def get_channels(self, filter=None): + return [] + + def add_channels(self, channels, network=None, no_dupes=False): + pass + if __name__ == '__main__': from sfa.rspecs.rspec import RSpec from sfa.rspecs.rspec_elements import * r = RSpec('/tmp/resources.rspec') r.load_rspec_elements(SFAv1.elements) - print r.get(RSpecElements.NODE) + print(r.get(RSpecElements.NODE))