working toward full support for sliver urns in the aggregate and registry
Tony Mack [Tue, 8 Jan 2013 18:35:20 +0000 (13:35 -0500)]
sfa/managers/aggregate_manager.py
sfa/managers/registry_manager.py
sfa/methods/Describe.py
sfa/openstack/nova_driver.py
sfa/planetlab/plaggregate.py
sfa/planetlab/pldriver.py
sfa/trust/auth.py
sfa/util/xrn.py

index c0a8b65..0bf5d9f 100644 (file)
@@ -58,7 +58,6 @@ class AggregateManager:
             'geni_api_versions': {'3': 'http://%s:%s' % (socket.gethostname(), api.config.sfa_aggregate_port)},
             'geni_single_allocation': 0, # Accept operations that act on as subset of slivers in a given state.
             'geni_allocate': 'geni_many',# Multiple slivers can exist and be incrementally added, including those which connect or overlap in some way.
-            'geni_best_effort': 'true',
             'geni_credential_types': cred_types,
         }
         version.update(version_generic)
index f3f75f7..f6277ed 100644 (file)
@@ -42,7 +42,13 @@ class RegistryManager:
             hrn = urn_to_hrn(xrn)[0]
         else:
             hrn, type = urn_to_hrn(xrn)
-            
+
+        # Slivers don't have credentials but users should be able to 
+        # specify a sliver xrn and receive the slice's credential
+        if type == 'sliver' or '-' in Xrn(hrn).leaf:
+            slice_xrn = self.driver.sliver_to_slice_xrn(hrn)
+            hrn = slice_xrn.hrn 
+  
         # Is this a root or sub authority
         auth_hrn = api.auth.get_authority(hrn)
         if not auth_hrn or hrn == api.config.SFA_INTERFACE_HRN:
index ff3765d..b66780a 100644 (file)
@@ -37,8 +37,8 @@ class Describe(Method):
             else:
                 raise SfaInvalidArgument('Must specify an rspec version option. geni_rspec_version cannot be null')
  
-        # Find the valid credentials
-        valid_creds = self.api.auth.checkCredentials(creds, 'listnodes', urns)
+        valid_creds = self.api.auth.checkCredentials(creds, 'listnodes', urns, \
+                      check_sliver_callback = self.api.manager.driver.check_sliver_credentials)
 
         # get hrn of the original caller 
         origin_hrn = options.get('origin_hrn', None)
index c3c9f54..da06c84 100644 (file)
@@ -49,6 +49,13 @@ class NovaDriver(Driver):
             if NovaDriver.cache is None:
                 NovaDriver.cache = Cache()
             self.cache = NovaDriver.cache
+
+    def sliver_to_slice_xrn(self, xrn):
+        return xrn
+
+    def check_sliver_credentials(self, creds, urns):
+        #TODO: Implement
+        return
  
     ########################################
     ########## registry oriented
index ef1a5bb..0e32d8f 100644 (file)
@@ -120,13 +120,11 @@ class PlAggregate:
             xrn = PlXrn(xrn=urn)
             if xrn.type == 'sliver':
                  # id: slice_id-node_id
-                id_parts = xrn.leaf.split('-')
-                slice_ids.add(id_parts[0]) 
-                node_ids.append(id_parts[1])
+                sliver_id_parts = xrn.get_sliver_id_parts()
+                slice_ids.add(sliver_id_parts[0]) 
+                node_ids.append(sliver_id_parts[1])
             else:  
                 names.add(xrn.pl_slicename())
-            if xrn.id:
-                ids.add(xrn.id)
 
         filter = {}
         if names:
index c47d170..93949f5 100644 (file)
@@ -2,7 +2,7 @@ import datetime
 #
 from sfa.util.faults import MissingSfaInfo, UnknownSfaType, \
     RecordNotFound, SfaNotImplemented, SliverDoesNotExist, SearchFailed, \
-    UnsupportedOperation 
+    UnsupportedOperation, Forbidden 
 from sfa.util.sfalogging import logger
 from sfa.util.defaultdict import defaultdict
 from sfa.util.sfatime import utcparse, datetime_to_string, datetime_to_epoch
@@ -52,7 +52,41 @@ class PlDriver (Driver):
             if PlDriver.cache is None:
                 PlDriver.cache = Cache()
             self.cache = PlDriver.cache
+
+    def sliver_to_slice_xrn(self, xrn):
+        sliver_id_parts = Xrn(xrn).get_sliver_id_parts()
+        slices = self.shell.GetSlices(sliver_id_parts[0])
+        if not slices:
+            raise Forbidden("Unable to locate slice record for sliver:  %s" % xrn)
+        slice = slices[0]
+        slice_xrn = Xrn(auth=self.hrn, slicename=slice['name'])
+        return slice_xrn 
  
+    def check_sliver_credentials(self, creds, urns):
+        # build list of cred object hrns
+        slice_cred_names = []
+        for cred in creds:
+            slice_cred_hrn = Credential(cred=cred).get_gid_object().get_hrn() 
+            slice_cred_names.append(PlXrn(xrn=slice_cred_hrn).pl_slicename()) 
+
+        # look slice names of slivers listed in urns arg
+        slice_ids = []
+        for urn in urns:
+            sliver_id_parts = Xrn(xrn=urn).get_sliver_id_parts()
+            slice_ids.append(sliver_id_parts[0])
+
+        if not slice_ids:
+             raise Forbidden("sliver urn not provided")
+
+        slices = self.shell.GetSlices(slice_ids)
+        sliver_names = [slice['name'] for slice in slices]
+
+        # make sure we have a credential for every specified sliver ierd
+        for sliver_name in sliver_names:
+            if sliver_name not in slice_cred_names:
+                msg = "Valid credential not found for target: %s" % sliver_name
+                raise Forbidden(msg)
+
     ########################################
     ########## registry oriented
     ########################################
index 4a2fd62..d72c3f8 100644 (file)
@@ -4,7 +4,7 @@
 import sys
 
 from sfa.util.faults import InsufficientRights, MissingCallerGID, MissingTrustedRoots, PermissionError, \
-    BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable
+    BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable, Forbidden
 from sfa.util.sfalogging import logger
 from sfa.util.config import Config
 from sfa.util.xrn import Xrn, get_authority
@@ -34,17 +34,22 @@ class Auth:
         self.trusted_cert_list = TrustedRoots(self.config.get_trustedroots_dir()).get_list()
         self.trusted_cert_file_list = TrustedRoots(self.config.get_trustedroots_dir()).get_file_list()
 
-        
-    def checkCredentials(self, creds, operation, xrns=[]):
+    def checkCredentials(self, creds, operation, xrns=[], check_sliver_callback=None):
         if not isinstance(xrns, list):
             xrns = [xrns]
-        hrns = [Xrn(xrn).hrn for xrn in xrns] 
+
+        slice_xrns = Xrn.filter_type(xrns, 'slice')
+        sliver_xrns = Xrn.filter_type(xrns, 'sliver')
+
+        # we are not able to validate slivers in the traditional way so 
+        # we make sure not to include sliver urns/hrns in the core validation loop
+        hrns = [Xrn(xrn).hrn for xrn in xrns if xrn not in sliver_xrns] 
         valid = []
         if not isinstance(creds, list):
             creds = [creds]
         logger.debug("Auth.checkCredentials with %d creds on hrns=%s"%(len(creds),hrns))
         # won't work if either creds or hrns is empty - let's make it more explicit
-        if not creds: raise InsufficientRights("Access denied - no credential provided")
+        if not creds: raise Forbidden("no credential provided")
         if not hrns: hrns = [None]
         for cred in creds:
             for hrn in hrns:
@@ -56,9 +61,20 @@ class Auth:
                     logger.debug("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
                     error = sys.exc_info()[:2]
                     continue
-            
+        
+        # make sure all sliver xrns are validated against the valid credentials
+        if sliver_xrns:
+            if not check_sliver_callback:
+                msg = "sliver verification callback method not found." 
+                msg += " Unable to validate sliver xrns: %s" % sliver_xrns
+                raise Forbidden(msg)
+            check_sliver_callback(valid, sliver_xrns)
+                
         if not len(valid):
-            raise InsufficientRights('Access denied: %s -- %s' % (error[0],error[1]))
+            msg = "Valid credential not found for method: %s" % operation
+            if xrns:
+                msg += " target: %s" % xrns 
+            raise Forbidden(msg)
         
         return valid
         
index ee587a7..dfcf3e5 100644 (file)
@@ -109,6 +109,26 @@ class Xrn:
     def urn_split (urn):
         return Xrn.urn_meaningful(urn).split('+')
 
+    @staticmethod
+    def filter_type(urns=[], type=None):
+        urn_list = []
+        if not type:
+            return urns
+
+        for urn in urns:
+            xrn = Xrn(xrn=urn)
+            if not xrn.type:
+                # If an xrn doesn't have a type its probably a hrn. 
+                # We have to make some assumptions on the hrn's type
+                # based on the contents of the hrn.  
+                if type == 'sliver' and '-' in xrn.leaf:
+                    urn_list.append(urn) 
+                elif type != 'sliver' and not '-' in xrn.leaf:
+                    urn_list.append(urn)
+            elif (xrn.type == type):
+                # Xrn is probably a urn so we can just compare types  
+                urn_list.append(urn)
+        return urn_list
     ####################
     # the local fields that are kept consistent
     # self.urn
@@ -181,6 +201,15 @@ class Xrn:
         self.hrn = hrn 
         self.hrn_to_urn()
         self._normalize()
+
+    # sliver_id_parts is list that contains the sliver's 
+    # slice id and node id 
+    def get_sliver_id_parts(self):
+        sliver_id_parts = []
+        if self.type == 'sliver' or '-' in self.leaf:
+            sliver_id_parts = self.leaf.split('-')
+        return sliver_id_parts
+        
         
     def urn_to_hrn(self):
         """