Merge branch 'senslab2' of ssh://flab-git.pl.sophia.inria.fr/git/sfa into senslab2
[sfa.git] / sfa / rspecs / versions / sfav1.py
index 7cd8a14..3917b39 100644 (file)
@@ -1,7 +1,10 @@
+from copy import deepcopy
 from lxml import etree
 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.elements.versions.pgv2Link import PGv2Link
 
 class SFAv1(BaseVersion):
     enabled = True
@@ -12,11 +15,7 @@ class SFAv1(BaseVersion):
     namespace = None
     extensions = {}
     namespaces = None
-    elements = [
-        RSpecElement(RSpecElements.NETWORK, 'network', '//network'),
-        RSpecElement(RSpecElements.NODE, 'node', '//node'),
-        RSpecElement(RSpecElements.SLIVER, 'sliver', '//node/sliver'),
-    ] 
+    elements = [] 
     template = '<RSpec type="%s"></RSpec>' % type
 
     def get_network_elements(self):
@@ -116,18 +115,10 @@ class SFAv1(BaseVersion):
         return nodes
 
     def get_links(self, network=None):
-        if network:
-            links = self.xml.xpath('//network[@name="%s"]/link' % network)
-        else:
-            links = self.xml.xpath('//link')
-        linklist = []
-        for link in links:
-            (end1, end2) = link.get("endpoints").split()
-            name = link.find("description")
-            linklist.append((name.text,
-                             self.get_site_nodes(end1, network),
-                             self.get_site_nodes(end2, network)))
-        return linklist
+        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()
@@ -188,7 +179,7 @@ class SFAv1(BaseVersion):
     def add_network(self, network):
         network_tags = self.xml.xpath('//network[@name="%s"]' % network)
         if not network_tags:
-            network_tag = etree.SubElement(self.xml, 'network', name=network)
+            network_tag = etree.SubElement(self.xml.root, 'network', name=network)
         else:
             network_tag = network_tags[0]
         return network_tag
@@ -202,7 +193,7 @@ class SFAv1(BaseVersion):
                 # node already exists
                 continue
 
-            network_tag = self.xml
+            network_tag = self.xml.root
             if 'network' in node:
                 network = node['network']
                 network_tag = self.add_network(network)
@@ -219,11 +210,19 @@ class SFAv1(BaseVersion):
             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
@@ -248,30 +247,44 @@ class SFAv1(BaseVersion):
         pass
 
     def add_links(self, links):
-        pass
+        networks = self.get_network_elements()
+        if len(networks) > 0:
+            xml = networks[0]
+        else:
+            xml = self.xml    
+        PGv2Link.add_links(xml, links)
 
-    def add_slivers(self, slivers, network=None, sliver_urn=None, no_dupes=False):
+    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):
         # 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])
         
-        nodes_with_slivers = self.get_nodes_with_slivers(network)
+        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:
-            if isinstance(sliver, basestring):
-                sliver = {'hostname': sliver}
-            if sliver['hostname'] in nodes_with_slivers:
-                continue
             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']
-
+            
+        # 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)
 
     def remove_slivers(self, slivers, network=None, no_dupes=False):
-        slivers = self._process_slivers(slivers)
         for sliver in slivers:
             node_elem = self.get_node_element(sliver['hostname'], network)
             sliver_elem = node_elem.find('sliver')
@@ -287,27 +300,27 @@ class SFAv1(BaseVersion):
             network_tag = self.xml.xpath("//network[@name='%s']" % network)
             if isinstance(network_tag, list):
                 network_tag = network_tag[0]
-            defaults = self.add_element('sliver_defaults', attrs={}, parent=network_tag)
+            defaults = self.xml.add_element('sliver_defaults', attrs={}, parent=network_tag)
         elif isinstance(defaults, list):
             defaults = defaults[0]
-        self.add_attribute(defaults, name, value)
+        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.add_attribute(sliver, name, value)
+        self.xml.add_attribute(sliver, name, value)
 
     def remove_default_sliver_attribute(self, name, value, network=None):
         if network:
             defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network)
         else:
             defaults = self.xml.xpath("//sliver_defaults" % network)
-        self.remove_attribute(defaults, name, value)
+        self.xml.remove_attribute(defaults, name, value)
 
     def remove_sliver_attribute(self, hostname, name, value, network=None):
         node = self.get_node_element(hostname, network)
         sliver = node.find("sliver")
-        self.remove_attribute(sliver, name, value)
+        self.xml.remove_attribute(sliver, name, value)
 
     def add_vlink(self, fromhost, tohost, kbps, network=None):
         fromnode = self.get_node_element(fromhost, network)
@@ -319,7 +332,7 @@ class SFAv1(BaseVersion):
             fromid = fromnode.get("id")
             toid = tonode.get("id")
             vlink.set("endpoints", "%s %s" % (fromid, toid))
-            self.add_attribute(vlink, "kbps", kbps)
+            self.xml.add_attribute(vlink, "kbps", kbps)
 
 
     def remove_vlink(self, endpoints, network=None):
@@ -333,20 +346,23 @@ class SFAv1(BaseVersion):
         Merge contents for specified rspec with current rspec
         """
 
-        from sfa.rspecs.rspec_parser import parse_rspec
-        rspec = parse_rspec(in_rspec)
-        if rspec.type.lower() == 'protogeni':
+        from sfa.rspecs.rspec import RSpec
+        if isinstance(in_rspec, RSpec):
+            rspec = in_rspec
+        else:
+            rspec = RSpec(in_rspec)
+        if rspec.version.type.lower() == 'protogeni':
             from sfa.rspecs.rspec_converter import RSpecConverter
-            in_rspec = RSpecConverter.to_sfa_rspec(in_rspec)
+            in_rspec = RSpecConverter.to_sfa_rspec(rspec.toxml())
+            rspec = RSpec(in_rspec)
 
         # just copy over all networks
         current_networks = self.get_networks()
-        rspec = SfaRSpec(rspec=in_rspec)
-        networks = rspec.get_network_elements()
+        networks = rspec.version.get_network_elements()
         for network in networks:
             current_network = network.get('name')
             if current_network and current_network not in current_networks:
-                self.xml.append(network)
+                self.xml.root.append(network)
                 current_networks.append(current_network)
 
 if __name__ == '__main__':