slice_status is now SliverStatus and handles call_id
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Thu, 14 Apr 2011 13:15:26 +0000 (15:15 +0200)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Thu, 14 Apr 2011 13:15:26 +0000 (15:15 +0200)
first slice manager implementation that merges results
(and turned off the import from registry)

sfa/client/sfi.py
sfa/managers/aggregate_manager_pl.py
sfa/managers/aggregate_manager_vini.py
sfa/managers/component_manager_pl.py
sfa/managers/registry_manager_pl.py
sfa/managers/slice_manager_pl.py
sfa/methods/RenewSliver.py
sfa/methods/SliverStatus.py

index 0107142..bc6cc60 100755 (executable)
@@ -970,7 +970,7 @@ class Sfi:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
         server = self.get_server_from_opts(opts)
-        print server.SliverStatus(slice_urn, creds)
+        print server.SliverStatus(slice_urn, creds, unique_call_id())
 
 
     def shutdown(self, opts, args):
index 5355f97..887d2f3 100644 (file)
@@ -95,8 +95,10 @@ def __get_hostnames(nodes):
         hostnames.append(node.hostname)
     return hostnames
 
-def slice_status(api, slice_xrn, creds):
-    hrn, type = urn_to_hrn(slice_xrn)
+def SliverStatus(api, slice_xrn, creds, call_id):
+    if Callids().already_handled(call_id): return {}
+
+    (hrn, type) = urn_to_hrn(slice_xrn)
     # find out where this slice is currently running
     api.logger.info(hrn)
     slicename = hrn_to_pl_slicename(hrn)
@@ -106,19 +108,12 @@ def slice_status(api, slice_xrn, creds):
         raise Exception("Slice %s not found (used %s as slicename internally)" % slice_xrn, slicename)
     slice = slices[0]
     
-    nodes = api.plshell.GetNodes(api.plauth, slice['node_ids'],
-                                    ['hostname', 'site_id', 'boot_state', 'last_contact'])
+    # report about the local nodes only
+    nodes = api.plshell.GetNodes(api.plauth, {'node_id':slice['node_ids'],'peer_id':None},
+                                 ['hostname', 'site_id', 'boot_state', 'last_contact'])
     site_ids = [node['site_id'] for node in nodes]
     sites = api.plshell.GetSites(api.plauth, site_ids, ['site_id', 'login_base'])
-    sites_dict = {}
-    for site in sites:
-        sites_dict[site['site_id']] = site['login_base']
-
-    # XX remove me
-    #api.logger.info(slice_xrn)
-    #api.logger.info(slice)
-    #api.logger.info(nodes)
-    # XX remove me
+    sites_dict = dict ( [ (site['site_id'],site['login_base'] ) for site in sites ] )
 
     result = {}
     top_level_status = 'unknown'
@@ -134,7 +129,7 @@ def slice_status(api, slice_xrn, creds):
         res['pl_hostname'] = node['hostname']
         res['pl_boot_state'] = node['boot_state']
         res['pl_last_contact'] = node['last_contact']
-        if not node['last_contact'] is None:
+        if node['last_contact'] is not None:
             res['pl_last_contact'] = datetime.datetime.fromtimestamp(node['last_contact']).ctime()
         res['geni_urn'] = hostname_to_urn(api.hrn, sites_dict[node['site_id']], node['hostname'])
         if node['boot_state'] == 'boot':
index 92e0bdc..66fb5cc 100644 (file)
@@ -26,7 +26,7 @@ from sfa.util.callids import Callids
 # VINI aggregate is almost identical to PLC aggregate for many operations, 
 # so lets just import the methods form the PLC manager
 from sfa.managers.aggregate_manager_pl import (
-start_slice, stop_slice, RenewSliver, reset_slice, ListSlices, get_ticket, slice_status)
+start_slice, stop_slice, RenewSliver, reset_slice, ListSlices, get_ticket, SliverStatus)
 
 
 def GetVersion(api):
index 3d4f76a..6100e76 100644 (file)
@@ -21,7 +21,7 @@ def init_server():
         sfa_component_setup.get_credential(force=True)
         sfa_component_setup.get_trusted_certs()
 
-def slice_status(api, slice_xrn, creds):
+def SliverStatus(api, slice_xrn, creds):
     result = {}
     result['geni_urn'] = slice_xrn
     result['geni_status'] = 'unknown'
index dc364b3..9dba54d 100644 (file)
@@ -13,7 +13,8 @@ from sfa.trust.credential import Credential
 from sfa.trust.certificate import Certificate, Keypair
 from sfa.trust.gid import create_uuid
 from sfa.util.version import version_core
-from sfa.managers.aggregate_manager_pl import slice_status
+# Thierry - turning this off, it's a slice interface not a registry one ?!?
+#from sfa.managers.aggregate_manager_pl import SliverStatus
 
 # The GENI GetVersion call
 def GetVersion(api):
index 44b1a5e..8991097 100644 (file)
@@ -25,10 +25,6 @@ import sfa.plc.peers as peers
 from sfa.util.version import version_core
 from sfa.util.callids import Callids
 
-# XX FIX ME:  should merge result from multiple aggregates instead of 
-# calling aggregate implementation
-from sfa.managers.aggregate_manager_pl import slice_status
-
 # we have specialized xmlrpclib.ServerProxy to remember the input url
 # OTOH it's not clear if we're only dealing with XMLRPCServerProxy instances
 def get_serverproxy_url (server):
@@ -384,6 +380,46 @@ def ListResources(api, creds, options, call_id):
  
     return merged_rspec
 
+# first draft at a merging SliverStatus
+def SliverStatus(api, slice_xrn, creds, call_id):
+    if Callids().already_handled(call_id): return {}
+    # attempt to use delegated credential first
+    credential = api.getDelegatedCredential(creds)
+    if not credential:
+        credential = api.getCredential()
+    threads = ThreadManager()
+    for aggregate in api.aggregates:
+        server = api.aggregates[aggregate]
+        threads.run (server.SliverStatus, slice_xrn, credential, call_id)
+    results = threads.get_results()
+
+    # get rid of any void result - e.g. when call_id was hit where by convention we return {}
+    results = [ result in results if result and result['geni_resources']]
+
+    # do not try to combine if there's no result
+    if not results : return {}
+
+    # otherwise let's merge stuff
+    overall = {}
+
+    # mmh, it is expected that all results carry the same urn
+    overall['geni_urn'] = results[0]['geni_urn']
+
+    # consolidate geni_status - simple model using max on a total order
+    states = [ 'ready', 'configuring', 'failed', 'unknown' ]
+    # hash name to index
+    shash = dict ( zip ( states, range(len(states)) ) )
+    def combine_status (x,y):
+        return shash [ max (shash(x),shash(y)) ]
+    overall['geni_status'] = reduce (combine_status, [ result['geni_status'] for result in results], 'ready' )
+
+    # {'ready':0,'configuring':1,'failed':2,'unknown':3}
+    # append all geni_resources
+    overall['geni_resources'] = \
+        reduce (lambda x,y: x+y, [ result['geni_resources'] for result in results] , [])
+
+    return overall
+
 def main():
     r = RSpec()
     r.parseFile(sys.argv[1])
index b426a3d..6cbde77 100644 (file)
@@ -35,7 +35,7 @@ class RenewSliver(Method):
         # Validate that the time does not go beyond the credential's expiration time
         requested_time = utcparse(expiration_time)
         if requested_time > Credential(string=valid_creds[0]).get_expiration():
-            raise InsufficientRights('SliverStatus: Credential expires before requested expiration time')
+            raise InsufficientRights('Renewsliver: Credential expires before requested expiration time')
         if requested_time > datetime.datetime.utcnow() + datetime.timedelta(days=60):
             raise Exception('Cannot renew > 60 days from now')
         manager = self.api.get_interface_manager()
index 842c3e4..231bec5 100644 (file)
@@ -15,17 +15,18 @@ class SliverStatus(Method):
         Parameter(str, "Slice URN"),
         Mixed(Parameter(str, "Credential string"),
               Parameter(type([str]), "List of credentials")),
+        Parameter(str, "call_id"),
         ]
     returns = Parameter(dict, "Status details")
 
-    def call(self, slice_xrn, creds):
+    def call(self, slice_xrn, creds, call_id=""):
         hrn, type = urn_to_hrn(slice_xrn)
         valid_creds = self.api.auth.checkCredentials(creds, 'sliverstatus', hrn)
 
         self.api.logger.info("interface: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, hrn, self.name))
     
         manager = self.api.get_interface_manager()
-        status = manager.slice_status(self.api, hrn, valid_creds)
+        status = manager.SliverStatus(self.api, hrn, valid_creds, call_id)
 
         return status