updated renew(), delete(), allocate(), provision()
authorTony Mack <tmack@paris.CS.Princeton.EDU>
Thu, 23 Aug 2012 19:36:34 +0000 (15:36 -0400)
committerTony Mack <tmack@paris.CS.Princeton.EDU>
Thu, 23 Aug 2012 19:36:34 +0000 (15:36 -0400)
sfa/managers/aggregate_manager.py
sfa/managers/slice_manager.py
sfa/methods/DeleteSliver.py
sfa/methods/RenewSliver.py
sfa/openstack/nova_driver.py
sfa/openstack/osaggregate.py
sfa/planetlab/pldriver.py
sfa/util/faults.py

index 20c3d73..f8948fd 100644 (file)
@@ -105,7 +105,7 @@ class AggregateManager:
                 logger.debug("%s.ListResources returning cached advertisement" % (self.driver.__module__))
                 return rspec
        
-        rspec = self.driver.list_resources (creds, version, options) 
+        rspec = self.driver.list_resources (version, options) 
         if self.driver.cache:
             logger.debug("%s.ListResources stores advertisement in cache" % (self.driver.__module__))
             self.driver.cache.add(version_string, rspec)    
@@ -117,65 +117,43 @@ class AggregateManager:
 
         version_manager = VersionManager()
         rspec_version = version_manager.get_version(options.get('geni_rspec_version'))
-        return self.driver.describe(creds, urns, rspec_version, options)
+        return self.driver.describe(urns, rspec_version, options)
         
     
-    def Status (self, api, urns, creds, options):
+    def Status (self, api, urns, options):
         call_id = options.get('call_id')
         if Callids().already_handled(call_id): return {}
         return self.driver.status (urns, options=options)
-    
-    def CreateSliver(self, api, xrn, creds, rspec_string, users, options):
+   
+
+    def Allocate(self, api, xrn, creds, rspec_string, options):
+        """
+        Allocate resources as described in a request RSpec argument 
+        to a slice with the named URN.
+        """
+        call_id = options.get('call_id')
+        if Callids().already_handled(call_id): return ""
+        return self.driver.allocate(xrn, creds, rspec_string, options)
+    def Provision(self, api, xrns, options):
         """
         Create the sliver[s] (slice) at this aggregate.    
         Verify HRN and initialize the slice record in PLC if necessary.
         """
         call_id = options.get('call_id')
         if Callids().already_handled(call_id): return ""
+        return self.driver.provision(xrns, creds, options)
     
-        xrn = Xrn(xrn, 'slice')
-        slice_urn=xrn.get_urn()
-        slice_hrn=xrn.get_hrn()
-
-        return self.driver.create_sliver (slice_urn, slice_hrn, creds, rspec_string, users, options)
-    
-    def DeleteSliver(self, api, xrn, creds, options):
+    def Delete(self, api, xrns, options):
         call_id = options.get('call_id')
         if Callids().already_handled(call_id): return True
+        return self.driver.delete_sliver (xrns, options)
 
-        xrn = Xrn(xrn, 'slice')
-        slice_urn=xrn.get_urn()
-        slice_hrn=xrn.get_hrn()
-        return self.driver.delete_sliver (slice_urn, slice_hrn, creds, options)
-
-    def RenewSliver(self, api, xrn, creds, expiration_time, options):
+    def Renew(self, api, xrns, expiration_time, options):
         call_id = options.get('call_id')
         if Callids().already_handled(call_id): return True
-        
-        xrn = Xrn(xrn, 'slice')
-        slice_urn=xrn.get_urn()
-        slice_hrn=xrn.get_hrn()
-        return self.driver.renew_sliver (slice_urn, slice_hrn, creds, expiration_time, options)
+        return self.driver.renew(xrns, expiration_time, options)
     
-    ### these methods could use an options extension for at least call_id
-    def start_slice(self, api, xrn, creds):
-        xrn = Xrn(xrn)
-        slice_urn=xrn.get_urn()
-        slice_hrn=xrn.get_hrn()
-        return self.driver.start_slice (slice_urn, slice_hrn, creds)
-     
-    def stop_slice(self, api, xrn, creds):
-        xrn = Xrn(xrn)
-        slice_urn=xrn.get_urn()
-        slice_hrn=xrn.get_hrn()
-        return self.driver.stop_slice (slice_urn, slice_hrn, creds)
-
-    def reset_slice(self, api, xrn):
-        xrn = Xrn(xrn)
-        slice_urn=xrn.get_urn()
-        slice_hrn=xrn.get_hrn()
-        return self.driver.reset_slice (slice_urn, slice_hrn)
-
     def GetTicket(self, api, xrn, creds, rspec, users, options):
     
         xrn = Xrn(xrn)
index 02729b0..dcd5e5e 100644 (file)
@@ -337,9 +337,9 @@ class SliceManager:
     
     
     # first draft at a merging SliverStatus
-    def SliverStatus(self, api, slice_xrn, creds, options):
-        def _SliverStatus(server, xrn, creds, options):
-            return server.SliverStatus(xrn, creds, options)
+    def Status(self, api, slice_xrn, creds, options):
+        def _Status(server, xrn, creds, options):
+            return server.Status(xrn, creds, options)
 
         call_id = options.get('call_id') 
         if Callids().already_handled(call_id): return {}
@@ -351,7 +351,7 @@ class SliceManager:
         for aggregate in api.aggregates:
             interface = api.aggregates[aggregate]
             server = api.server_proxy(interface, cred)
-            threads.run (_SliverStatus, server, slice_xrn, [cred], options)
+            threads.run (_Status, server, slice_xrn, [cred], options)
         results = [ReturnValue.get_value(result) for result in threads.get_results()]
     
         # get rid of any void result - e.g. when call_id was hit, where by convention we return {}
index 697b6d3..9dfebda 100644 (file)
@@ -4,19 +4,19 @@ from sfa.storage.parameter import Parameter, Mixed
 from sfa.trust.auth import Auth
 from sfa.trust.credential import Credential
 
-class DeleteSliver(Method):
+class Delete(Method):
     """
-    Remove the slice from all nodes and free the allocated resources        
+    Remove the slice or slivers and free the allocated resources        
 
-    @param xrn human readable name of slice to instantiate (hrn or urn)
-    @param cred credential string specifying the rights of the caller
+    @param xrns human readable name of slice to instantiate (hrn or urn)
+    @param creds credential string specifying the rights of the caller
     @return 1 is successful, faults otherwise  
     """
 
     interfaces = ['aggregate', 'slicemgr', 'component']
     
     accepts = [
-        Parameter(str, "Human readable name of slice to delete (hrn or urn)"),
+        Parameter([str], "Human readable name of slice to delete (hrn or urn)"),
         Mixed(Parameter(str, "Credential string"),
               Parameter(type([str]), "List of credentials")),
         Parameter(dict, "options"),
@@ -24,14 +24,13 @@ class DeleteSliver(Method):
 
     returns = Parameter(int, "1 if successful")
     
-    def call(self, xrn, creds, options):
-        (hrn, type) = urn_to_hrn(xrn)
-        valid_creds = self.api.auth.checkCredentials(creds, 'deletesliver', hrn)
+    def call(self, xrns, creds, options):
+        valid_creds = self.api.auth.checkCredentials(creds, 'deletesliver', xrns)
 
         #log the call
         origin_hrn = Credential(string=valid_creds[0]).get_gid_caller().get_hrn()
-        self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, hrn, self.name))
+        self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, xrns, self.name))
 
-        self.api.manager.DeleteSliver(self.api, xrn, creds, options)
+        self.api.manager.Delete(self.api, xrns, options)
  
         return 1 
index c64b884..ee951c0 100644 (file)
@@ -9,13 +9,15 @@ from sfa.trust.credential import Credential
 
 from sfa.storage.parameter import Parameter
 
-class RenewSliver(Method):
+class Renew(Method):
     """
-    Renews the resources in a sliver, extending the lifetime of the slice.    
-    @param slice_urn (string) URN of slice to renew
+    Renews the resources in the specified slice or slivers by 
+    extending the lifetime.
+    
+    @param surn ([string]) List of URNs of to renew
     @param credentials ([string]) of credentials
     @param expiration_time (string) requested time of expiration
-    
+    @param options (dict) options
     """
     interfaces = ['aggregate', 'slicemgr']
     accepts = [
@@ -26,14 +28,12 @@ class RenewSliver(Method):
         ]
     returns = Parameter(bool, "Success or Failure")
 
-    def call(self, slice_xrn, creds, expiration_time, options):
-
-        (hrn, type) = urn_to_hrn(slice_xrn)
+    def call(self, urns, creds, expiration_time, options):
 
-        self.api.logger.info("interface: %s\ttarget-hrn: %s\tcaller-creds: %s\tmethod-name: %s"%(self.api.interface, hrn, creds, self.name))
+        self.api.logger.info("interface: %s\ttarget-hrn: %s\tcaller-creds: %s\tmethod-name: %s"%(self.api.interface, urns, creds, self.name))
 
         # Find the valid credentials
-        valid_creds = self.api.auth.checkCredentials(creds, 'renewsliver', hrn)
+        valid_creds = self.api.auth.checkCredentials(creds, 'renewsliver', urns)
 
         # Validate that the time does not go beyond the credential's expiration time
         requested_time = utcparse(expiration_time)
@@ -42,5 +42,5 @@ class RenewSliver(Method):
             raise InsufficientRights('Renewsliver: Credential expires before requested expiration time')
         if requested_time > datetime.datetime.utcnow() + datetime.timedelta(days=max_renew_days):
             raise Exception('Cannot renew > %s days from now' % max_renew_days)
-        return self.api.manager.RenewSliver(self.api, slice_xrn, valid_creds, expiration_time, options)
+        return self.api.manager.Renew(self.api, urns, expiration_time, options)
     
index af9ce4d..7a84c2e 100644 (file)
@@ -318,22 +318,13 @@ class NovaDriver(Driver):
     def aggregate_version (self):
         return {}
 
-    def list_slices (self, creds, options):
-        # get data from db
-        instance_urns = []
-        instances = self.shell.nova_manager.servers.findall()
-        for instance in instances:
-            if instance.name not in instance_urns:
-                instance_urns.append(OSXrn(instance.name, type='slice').urn)
-        return instance_urns
-        
     # first 2 args are None in case of resource discovery
-    def list_resources (self, creds, version, options):
+    def list_resources (self, version, options):
         aggregate = OSAggregate(self)
         rspec =  aggregate.list_resources(version=version, options=options)
         return rspec
 
-    def describe(self, creds, urns, version, options):
+    def describe(self, urns, version, options):
         aggregate = OSAggregate(self)
         return aggregate.describe(urns, version=version, options=options)
     
@@ -342,8 +333,8 @@ class NovaDriver(Driver):
         desc =  aggregate.describe(urns)
         return desc['geni_slivers']
 
-    def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
-
+    def allocate (self, urn, rspec_string, options):
+        xrn = Xrn(urn) 
         aggregate = OSAggregate(self)
 
         # assume first user is the caller and use their context
@@ -351,9 +342,10 @@ class NovaDriver(Driver):
         # key as the project key.
         key_name = None
         if len(users) > 1:
-            key_name = aggregate.create_instance_key(slice_hrn, users[0])
+            key_name = aggregate.create_instance_key(xrn.get_hrn(), users[0])
 
         # collect public keys
+        users = options.get('geni_users', [])
         pubkeys = []
         for user in users:
             pubkeys.extend(user['keys'])
@@ -365,33 +357,29 @@ class NovaDriver(Driver):
    
         return aggregate.describe(slice_xrn=slice_urn, version=rspec.version)
 
-    def delete_sliver (self, slice_urn, slice_hrn, creds, options):
+    def provision(self, urns, version, options):
         aggregate = OSAggregate(self)
-        tenant_name = OSXrn(xrn=slice_hrn, type='slice').get_tenant_name()
-        project_name = hrn_to_os_slicename(slice_hrn)
-        return aggregate.delete_instances(project_name, tenant_name)   
+        return aggregate.describe(urns, version=version, options=options) 
 
-    def update_sliver(self, slice_urn, slice_hrn, rspec, creds, options):
-        name = hrn_to_os_slicename(slice_hrn)
-        tenant_name = OSXrn(xrn=slice_hrn, type='slice').get_tenant_name()
+    def delete (self, urns, options):
         aggregate = OSAggregate(self)
-        return aggregate.update_instances(name)
-    
-    def renew_sliver (self, slice_urn, slice_hrn, creds, expiration_time, options):
-        return True
-
-    def start_slice (self, slice_urn, slice_hrn, creds):
+        for urn in urns:
+            xrn = OSXrn(xrn=urn, type='slice')
+            tenant_name = xrn.get_tenant_name()
+            project_name = xrn.get_slicename()
+            id = xrn.id
+            aggregate.delete_instance(tenant_name, project_name, id)   
         return 1
 
-    def stop_slice (self, slice_urn, slice_hrn, creds):
+    def renew (self, urns, expiration_time, options):
+        return True
+
+    def perform_operational_action  (self, urns, action, options):
         tenant_name = OSXrn(xrn=slice_hrn, type='slice').get_tenant_name()
         name = OSXrn(xrn=slice_urn).name
         aggregate = OSAggregate(self)
         return aggregate.stop_instances(name, tenant_name) 
 
-    def reset_slice (self, slice_urn, slice_hrn, creds):
-        raise SfaNotImplemented ("reset_slice not available at this interface")
-    
     # xxx this code is quite old and has not run for ages
     # it is obviously totally broken and needs a rewrite
     def get_ticket (self, slice_urn, slice_hrn, creds, rspec_string, options):
index 032fd17..0e4be84 100644 (file)
@@ -351,9 +351,12 @@ class OSAggregate:
                            
 
 
-    def delete_instances(self, instance_name, tenant_name):
+    def delete_instance(self, tenant_name, instance_name, id=None):
         self.driver.shell.nova_manager.connect(tenant=tenant_name)
-        instances = self.driver.shell.nova_manager.servers.findall(name=instance_name)
+        args = {'name': instance_name}
+        if id:
+            args['id'] = id
+        instances = self.driver.shell.nova_manager.servers.findall(**args)
         security_group_manager = SecurityGroup(self.driver)
         for instance in instances:
             # deleate this instance's security groups
index f73410e..d4f1243 100644 (file)
@@ -2,7 +2,7 @@ import time
 import datetime
 #
 from sfa.util.faults import MissingSfaInfo, UnknownSfaType, \
-    RecordNotFound, SfaNotImplemented, SliverDoesNotExist
+    RecordNotFound, SfaNotImplemented, SliverDoesNotExist, SearchFailed
 from sfa.util.sfalogging import logger
 from sfa.util.defaultdict import defaultdict
 from sfa.util.sfatime import utcparse, datetime_to_string, datetime_to_epoch
@@ -571,12 +571,12 @@ class PlDriver (Driver):
         return slice_urns
         
     # first 2 args are None in case of resource discovery
-    def list_resources (self, creds, options):
+    def list_resources (self, version, options):
         aggregate = PlAggregate(self)
-        rspec =  aggregate.list_resources(version=rspec_version, options=options)
+        rspec =  aggregate.list_resources(version=version, options=options)
         return rspec
 
-    def describe(self, creds, urns, version, options):
+    def describe(self, urns, version, options):
         aggregate = PlAggregate(self)
         return aggregate.describe(urns, version=version, options=options)
     
@@ -649,13 +649,14 @@ class PlDriver (Driver):
         result['geni_resources'] = resources
         return result
 
-    def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
-
+    def allocate (self, urn, rspec_string, options):
+        xrn = Xrn(urn)
         aggregate = PlAggregate(self)
         slices = PlSlices(self)
-        peer = slices.get_peer(slice_hrn)
-        sfa_peer = slices.get_sfa_peer(slice_hrn)
+        peer = slices.get_peer(xrn.get_hrn())
+        sfa_peer = slices.get_sfa_peer(xrn.get_hrn())
         slice_record=None    
+        users = options.get('geni_users', [])
         if users:
             slice_record = users[0].get('slice_record', {})
     
@@ -664,11 +665,11 @@ class PlDriver (Driver):
         requested_attributes = rspec.version.get_slice_attributes()
         
         # ensure site record exists
-        site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer, options=options)
+        site = slices.verify_site(xrn.hrn, slice_record, peer, sfa_peer, options=options)
         # ensure slice record exists
-        slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer, options=options)
+        slice = slices.verify_slice(xrn.hrn, slice_record, peer, sfa_peer, options=options)
         # ensure person records exists
-        persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer, options=options)
+        persons = slices.verify_persons(xrn.hrn, slice, users, peer, sfa_peer, options=options)
         # ensure slice attributes exists
         slices.verify_slice_attributes(slice, requested_attributes, options=options)
         
@@ -707,15 +708,25 @@ class PlDriver (Driver):
         # only used by plc and ple.
         slices.handle_peer(site, slice, persons, peer)
         
-        return aggregate.describe_rspec(slice_xrn=slice_urn, version=rspec.version)
-
-    def delete_sliver (self, slice_urn, slice_hrn, creds, options):
-        slicename = hrn_to_pl_slicename(slice_hrn)
-        slices = self.shell.GetSlices({'name': slicename})
+        return aggregate.describe(slice_xrn=xrn.get_urn(), version=rspec.version)
+
+    def delete(self, urns, options):
+        names = []
+        ids = []
+        for urn in urns:
+            xrn = PlXrn(xrn=urn, type='slice')
+            names.append(xrn.pl_slicename())
+            if xrn.id:
+                ids.append(xrn.id)    
+        slices = self.shell.GetSlices({'name': names})
         if not slices:
-            return 1
+            raise SearchFailed(urns)
         slice = slices[0]
-    
+        if ids:
+            node_ids = ids
+        else:
+            node_ids = slice['node_ids']
+     
         # determine if this is a peer slice
         # xxx I wonder if this would not need to use PlSlices.get_peer instead 
         # in which case plc.peers could be deprecated as this here
@@ -724,17 +735,22 @@ class PlDriver (Driver):
         try:
             if peer:
                 self.shell.UnBindObjectFromPeer('slice', slice['slice_id'], peer)
-            self.shell.DeleteSliceFromNodes(slicename, slice['node_ids'])
+            self.shell.DeleteSliceFromNodes(slice['slice_id'], node_ids)
         finally:
             if peer:
                 self.shell.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id'])
         return 1
     
-    def renew_sliver (self, slice_urn, slice_hrn, creds, expiration_time, options):
-        slicename = hrn_to_pl_slicename(slice_hrn)
-        slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
+    def renew (self, urns, expiration_time, options):
+        # we can only renew slices, not individual slivers. ignore sliver
+        # ids in the urn 
+        names = []
+        for urn in urns:
+            xrn = PlXrn(urn=urn, type='slice')
+            names.append(xrn.pl_slicename())
+        slices = self.shell.GetSlices(names, ['slice_id'])
         if not slices:
-            raise RecordNotFound(slice_hrn)
+            raise SearchFailed(urns)
         slice = slices[0]
         requested_time = utcparse(expiration_time)
         record = {'expires': int(datetime_to_epoch(requested_time))}
index 848d818..df19264 100644 (file)
@@ -101,6 +101,14 @@ class TreeException(SfaFault):
     def __str__(self):\r
         return repr(self.value)\r
 \r
+class SearchFailed(SfaFault):\r
+    def __init__(self, value, extra = None):\r
+        self.value = value\r
+        faultString = "%s does not exist here " % self.value\r
+        SfaFault.__init__(self, GENICODE.SEARCHFAILED, faultString, extra)\r
+    def __str__(self):\r
+        return repr(self.value)\r
+\r
 class NonExistingRecord(SfaFault):\r
     def __init__(self, value, extra = None):\r
         self.value = value\r
@@ -329,4 +337,9 @@ class CertExpired(SfaFault):
         self.value = value\r
         faultString = "%s cert is expired" % value\r
         SfaFault.__init__(self, GENICODE.ERROR, faultString, extra)\r
-   \r
+  \r
+class SfatablesRejected(SfaFault):\r
+    def __init__(self, value, extra=None):\r
+        self.value =value\r
+        faultString = "%s rejected by sfatables"\r
+        SfaFault.__init__(self, GENICODE.FORBIDDEN, faultString, extra)  \r