+ return slices
+
+def get_rspec(api, creds, options):
+
+ # get slice's hrn from options
+ xrn = options.get('geni_slice_urn', None)
+ hrn, type = urn_to_hrn(xrn)
+
+ # get hrn of the original caller
+ origin_hrn = options.get('origin_hrn', None)
+ if not origin_hrn:
+ origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
+
+ # look in cache first
+ if api.cache and not xrn:
+ rspec = api.cache.get('nodes')
+ if rspec:
+ return rspec
+
+ hrn, type = urn_to_hrn(xrn)
+ rspec = None
+
+ # get the callers hrn
+ valid_cred = api.auth.checkCredentials(creds, 'listnodes', hrn)[0]
+ caller_hrn = Credential(string=valid_cred).get_gid_caller().get_hrn()
+
+ # attempt to use delegated credential first
+ credential = api.getDelegatedCredential(creds)
+ if not credential:
+ credential = api.getCredential()
+ threads = ThreadManager()
+ for aggregate in api.aggregates:
+ # prevent infinite loop. Dont send request back to caller
+ # unless the caller is the aggregate's SM
+ if caller_hrn == aggregate and aggregate != api.hrn:
+ continue
+ # get the rspec from the aggregate
+ server = api.aggregates[aggregate]
+ my_opts = copy(options)
+ my_opts['geni_compressed'] = False
+ threads.run(server.ListResources, credential, my_opts)
+ #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)
+
+ 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))
+
+ rspec = etree.tostring(rspec, xml_declaration=True, pretty_print=True)
+ # cache the result
+ if api.cache and not xrn:
+ api.cache.add('nodes', rspec)
+
+ return rspec