merging rspecs avoid duplicated networks
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Wed, 15 Dec 2010 15:55:29 +0000 (16:55 +0100)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Wed, 15 Dec 2010 15:55:29 +0000 (16:55 +0100)
slice manager to use the helper function for merging for get_rspecs as well

sfa/managers/slice_manager_pl.py
sfa/util/rspecHelper.py

index 756800c..a58bc80 100644 (file)
@@ -363,7 +363,6 @@ def get_rspec(api, creds, options):
             return rspec
 
     hrn, type = urn_to_hrn(xrn)
             return rspec
 
     hrn, type = urn_to_hrn(xrn)
-    rspec = None
 
     # get the callers hrn
     valid_cred = api.auth.checkCredentials(creds, 'listnodes', hrn)[0]
 
     # get the callers hrn
     valid_cred = api.auth.checkCredentials(creds, 'listnodes', hrn)[0]
@@ -387,31 +386,13 @@ def get_rspec(api, creds, options):
         #threads.run(server.get_resources, cred, xrn, origin_hrn)
                     
     results = threads.get_results()
         #threads.run(server.get_resources, cred, xrn, origin_hrn)
                     
     results = threads.get_results()
-    # combine the rspecs into a single rspec 
-    for agg_rspec in results:
-        try:
-            tree = etree.parse(StringIO(agg_rspec))
-        except etree.XMLSyntaxError:
-            message = str(agg_rspec) + ": " + str(sys.exc_info()[1])
-            raise InvalidRSpec(message)
+    merged_rspec = merge_rspecs(results)
 
 
-        root = tree.getroot()
-        if root.get("type") in ["SFA"]:
-            if rspec == None:
-                rspec = root
-            else:
-                for network in root.iterfind("./network"):
-                    rspec.append(deepcopy(network))
-                for request in root.iterfind("./request"):
-                    rspec.append(deepcopy(request))
-    
-    sfa_logger().debug('get_rspec: rspec=%r'%rspec)
-    rspec =  etree.tostring(rspec, xml_declaration=True, pretty_print=True)
     # cache the result
     if api.cache and not xrn:
     # cache the result
     if api.cache and not xrn:
-        api.cache.add('nodes', rspec)
+        api.cache.add('nodes', merged_rspec)
  
  
-    return rspec
+    return merged_rspec
 
 def main():
     r = RSpec()
 
 def main():
     r = RSpec()
index a943190..8174e6b 100755 (executable)
@@ -1,11 +1,14 @@
 #! /usr/bin/env python
 
 import sys
 #! /usr/bin/env python
 
 import sys
+
 from copy import deepcopy
 from lxml import etree
 from StringIO import StringIO
 from optparse import OptionParser
 
 from copy import deepcopy
 from lxml import etree
 from StringIO import StringIO
 from optparse import OptionParser
 
+from sfa.util.faults import *
+from sfa.util.sfalogging import sfa_logger
 
 def merge_rspecs(rspecs):
     """
 
 def merge_rspecs(rspecs):
     """
@@ -15,24 +18,53 @@ def merge_rspecs(rspecs):
     if not rspecs or not isinstance(rspecs, list):
         return rspecs
 
     if not rspecs or not isinstance(rspecs, list):
         return rspecs
 
+    # ugly hack to avoid sending the same info twice, when the call graph has dags
+    known_networks={}
+    def register_network (network):
+        try:
+            known_networks[network.get('name')]=True
+        except:
+            sfa_logger().error("merge_rspecs: cannot register network with no name in rspec")
+            pass
+    def is_registered_network (network):
+        try:
+            return network.get('name') in known_networks
+        except:
+            sfa_logger().error("merge_rspecs: cannot retrieve network with no name in rspec")
+            return False
+
+    # the resulting tree
     rspec = None
     rspec = None
-    for tmp_rspec in rspecs:
+    for input_rspec in rspecs:
         try:
         try:
-            tree = etree.parse(StringIO(tmp_rspec))
+            tree = etree.parse(StringIO(input_rspec))
         except etree.XMLSyntaxError:
             # consider failing silently here
         except etree.XMLSyntaxError:
             # consider failing silently here
-            message = str(agg_rspec) + ": " + str(sys.exc_info()[1])
+            sfa_logger().log_exc("merge_rspecs, parse error")
+            message = str(sys.exc_info()[1]) + ' with ' + input_rspec
             raise InvalidRSpec(message)
 
         root = tree.getroot()
             raise InvalidRSpec(message)
 
         root = tree.getroot()
-        if root.get("type") in ["SFA"]:
-            if rspec == None:
-                rspec = root
-            else:
-                for network in root.iterfind("./network"):
+        if not root.get("type") in ["SFA"]:
+            sfa_logger().error("merge_rspecs: unexpected type for rspec root, %s"%root.get('type'))
+            continue
+        if rspec == None:
+            # we scan the first input, register all networks
+            # in addition we remove duplicates - needed until everyone runs 1.0-10
+            rspec = root
+            for network in root.iterfind("./network"):
+                if not is_registered_network(network):
+                    register_network(network)
+                else:
+                    # duplicate in the first input - trash it
+                    root.remove(network)
+        else:
+            for network in root.iterfind("./network"):
+                if not is_registered_network(network):
                     rspec.append(deepcopy(network))
                     rspec.append(deepcopy(network))
-                for request in root.iterfind("./request"):
-                    rspec.append(deepcopy(request))
+                    register_network(network)
+            for request in root.iterfind("./request"):
+                rspec.append(deepcopy(request))
     return etree.tostring(rspec, xml_declaration=True, pretty_print=True)
 
 class RSpec:
     return etree.tostring(rspec, xml_declaration=True, pretty_print=True)
 
 class RSpec: