return rspec
hrn, type = urn_to_hrn(xrn)
- rspec = None
# get the callers hrn
valid_cred = api.auth.checkCredentials(creds, 'listnodes', hrn)[0]
#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:
- api.cache.add('nodes', rspec)
+ api.cache.add('nodes', merged_rspec)
- return rspec
+ return merged_rspec
def main():
r = RSpec()
#! /usr/bin/env python
import sys
+
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):
"""
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
- for tmp_rspec in rspecs:
+ for input_rspec in rspecs:
try:
- tree = etree.parse(StringIO(tmp_rspec))
+ tree = etree.parse(StringIO(input_rspec))
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()
- 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))
- 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: