SA
[sfa.git] / sfa / senslab / slabdriver.py
index c80f762..b37f8b3 100644 (file)
@@ -13,32 +13,31 @@ from sfa.util.xrn import Xrn, hrn_to_urn, get_authority
 
 
 from sfa.senslab.slabpostgres import SlabDB
-                                                     
-                                                                
+
+
 from sfa.senslab.slabaggregate import SlabAggregate, slab_xrn_to_hostname
-                                                            
+
 from sfa.senslab.slabslices import SlabSlices
 
 
 from sfa.senslab.slabapi import SlabTestbedAPI
 
 
-     
 class SlabDriver(Driver):
     """ Senslab Driver class inherited from Driver generic class.
-    
+
     Contains methods compliant with the SFA standard and the testbed
     infrastructure (calls to LDAP and OAR).
-    
-   .. seealso:: Driver class
-    
+
+    ..seealso:: Driver class
+
     """
     def __init__(self, config):
-        """ 
-        
+        """
+
         Sets the senslab SFA config parameters ,
         instanciates the testbed api and the senslab database.
-        
+
         :param config: senslab SFA configuration object
         :type config: Config object
         """
@@ -48,43 +47,43 @@ class SlabDriver(Driver):
         self.db = SlabDB(config, debug = False)
         self.slab_api = SlabTestbedAPI(config)
         self.cache = None
-        
+
     def augment_records_with_testbed_info (self, record_list ):
-        """ 
-        
-        Adds specific testbed info to the records. 
-        
+        """
+
+        Adds specific testbed info to the records.
+
         :param record_list: list of sfa dictionaries records
         :type record_list: list
         :return: list of records with extended information in each record
         :rtype: list
         """
         return self.fill_record_info (record_list)
-    
+
     def fill_record_info(self, record_list):
         """
         For each SFA record, fill in the senslab specific and SFA specific
-        fields in the record. 
-        
+        fields in the record.
+
         :param record_list: list of sfa dictionaries records
         :type record_list: list
         :return: list of records with extended information in each record
         :rtype: list
-        
+
         .. warnings:: Should not be modifying record_list directly because modi
-        fication are kept outside the method's scope. Howerver, there is no 
+        fication are kept outside the method's scope. Howerver, there is no
         other way to do it given the way it's called in registry manager.
         """
-                    
+
         logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
         if not isinstance(record_list, list):
             record_list = [record_list]
 
-            
+
         try:
             for record in record_list:
-                #If the record is a SFA slice record, then add information 
-                #about the user of this slice. This kind of 
+                #If the record is a SFA slice record, then add information
+                #about the user of this slice. This kind of
                 #information is in the Senslab's DB.
                 if str(record['type']) == 'slice':
                     if 'reg_researchers' in record and \
@@ -93,41 +92,41 @@ class SlabDriver(Driver):
                             record['reg_researchers'][0].__dict__
                         record.update({'PI':[record['reg_researchers']['hrn']],
                             'researcher': [record['reg_researchers']['hrn']],
-                            'name':record['hrn'], 
+                            'name':record['hrn'],
                             'oar_job_id':[],
                             'node_ids': [],
                             'person_ids':[record['reg_researchers']['record_id']],
                             'geni_urn':'',  #For client_helper.py compatibility
                             'keys':'',  #For client_helper.py compatibility
                             'key_ids':''})  #For client_helper.py compatibility
-                        
-                        
+
+
                     #Get slab slice record and oar job id if any.
                     recslice_list = self.slab_api.GetSlices(slice_filter = \
                                                 str(record['hrn']),\
                                                 slice_filter_type = 'slice_hrn')
-                    
-                   
+
+
                     logger.debug("SLABDRIVER \tfill_record_info \
                         TYPE SLICE RECUSER record['hrn'] %s ecord['oar_job_id']\
                          %s " %(record['hrn'], record['oar_job_id']))
                     del record['reg_researchers']
                     try:
-                        for rec in recslice_list: 
+                        for rec in recslice_list:
                             logger.debug("SLABDRIVER\r\n  \t  \
                             fill_record_info oar_job_id %s " \
                             %(rec['oar_job_id']))
-                            
+
                             record['node_ids'] = [ self.slab_api.root_auth + \
                                     hostname for hostname in rec['node_ids']]
                     except KeyError:
                         pass
-                        
-                    
+
+
                     logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
                                     recslice_list  %s \r\n \t RECORD %s \r\n \
-                                    \r\n" %(recslice_list, record)) 
-                                    
+                                    \r\n" %(recslice_list, record))
+
                 if str(record['type']) == 'user':
                     #The record is a SFA user record.
                     #Get the information about his slice from Senslab's DB
@@ -135,84 +134,84 @@ class SlabDriver(Driver):
                     recslice_list = self.slab_api.GetSlices(\
                             slice_filter = record['record_id'],\
                             slice_filter_type = 'record_id_user')
-                                            
+
                     logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
                                 recslice_list %s \r\n \t RECORD %s \r\n" \
-                                %(recslice_list , record)) 
-                    #Append slice record in records list, 
+                                %(recslice_list , record))
+                    #Append slice record in records list,
                     #therefore fetches user and slice info again(one more loop)
                     #Will update PIs and researcher for the slice
-                   
+
                     recuser = recslice_list[0]['reg_researchers']
                     logger.debug( "SLABDRIVER.PY \t fill_record_info USER  \
-                                            recuser %s \r\n \r\n" %(recuser)) 
+                                            recuser %s \r\n \r\n" %(recuser))
                     recslice = {}
                     recslice = recslice_list[0]
                     recslice.update({'PI':[recuser['hrn']],
                         'researcher': [recuser['hrn']],
-                        'name':record['hrn'], 
+                        'name':record['hrn'],
                         'node_ids': [],
                         'oar_job_id': [],
-                        'person_ids':[recuser['record_id']]}) 
+                        'person_ids':[recuser['record_id']]})
                     try:
                         for rec in recslice_list:
                             recslice['oar_job_id'].append(rec['oar_job_id'])
                     except KeyError:
                         pass
-                            
+
                     recslice.update({'type':'slice', \
                                                 'hrn':recslice_list[0]['hrn']})
 
 
-                    #GetPersons takes [] as filters 
+                    #GetPersons takes [] as filters
                     user_slab = self.slab_api.GetPersons([record])
-    
-                    
+
+
                     record.update(user_slab[0])
                     #For client_helper.py compatibility
                     record.update( { 'geni_urn':'',
                     'keys':'',
-                    'key_ids':'' })                
+                    'key_ids':'' })
                     record_list.append(recslice)
-                    
+
                     logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
-                                INFO TO USER records %s" %(record_list)) 
-                  
+                                INFO TO USER records %s" %(record_list))
+
 
         except TypeError, error:
             logger.log_exc("SLABDRIVER \t fill_record_info  EXCEPTION %s"\
                                                                      %(error))
-                              
+
         return record_list
-                    
-                    
+
+
     def sliver_status(self, slice_urn, slice_hrn):
         """
-        Receive a status request for slice named urn/hrn 
+        Receive a status request for slice named urn/hrn
         urn:publicid:IDN+senslab+nturro_slice hrn senslab.nturro_slice
         shall return a structure as described in
         http://groups.geni.net/geni/wiki/GAPI_AM_API_V2#SliverStatus
         NT : not sure if we should implement this or not, but used by sface.
-        
+
         :param slice_urn: slice urn
         :type slice_urn: string
         :param slice_hrn: slice hrn
         :type slice_hrn: string
 
         """
-        
-        
+
+
         #First get the slice with the slice hrn
         slice_list =  self.slab_api.GetSlices(slice_filter = slice_hrn, \
                                     slice_filter_type = 'slice_hrn')
-        
+
         if len(slice_list) is 0:
             raise SliverDoesNotExist("%s  slice_hrn" % (slice_hrn))
-        
-        #Used for fetching the user info witch comes along the slice info 
-        one_slice = slice_list[0] 
 
-        
+        #Used for fetching the user info witch comes along the slice info
+        one_slice = slice_list[0]
+
+
         #Make a list of all the nodes hostnames  in use for this slice
         slice_nodes_list = []
         #for single_slice in slice_list:
@@ -221,18 +220,18 @@ class SlabDriver(Driver):
         #for node in one_slice:
             #slice_nodes_list.append(node['hostname'])
         slice_nodes_list = one_slice['node_ids']
-        #Get all the corresponding nodes details    
+        #Get all the corresponding nodes details
         nodes_all = self.slab_api.GetNodes({'hostname':slice_nodes_list},
                                 ['node_id', 'hostname','site','boot_state'])
         nodeall_byhostname = dict([(one_node['hostname'], one_node) \
-                                            for one_node in nodes_all])  
-          
-          
-          
+                                            for one_node in nodes_all])
+
+
+
         for single_slice in slice_list:
 
               #For compatibility
-            top_level_status = 'empty' 
+            top_level_status = 'empty'
             result = {}
             result.fromkeys(\
                 ['geni_urn','geni_error', 'pl_login','geni_status','geni_resources'], None)
@@ -240,18 +239,18 @@ class SlabDriver(Driver):
             logger.debug("Slabdriver - sliver_status Sliver status \
                                         urn %s hrn %s single_slice  %s \r\n " \
                                         %(slice_urn, slice_hrn, single_slice))
-                                        
+
             if 'node_ids' not in single_slice:
                 #No job in the slice
                 result['geni_status'] = top_level_status
-                result['geni_resources'] = [] 
+                result['geni_resources'] = []
                 return result
-           
-            top_level_status = 'ready' 
+
+            top_level_status = 'ready'
 
             #A job is running on Senslab for this slice
             # report about the local nodes that are in the slice only
-         
+
             result['geni_urn'] = slice_urn
 
             resources = []
@@ -259,7 +258,7 @@ class SlabDriver(Driver):
                 res = {}
                 res['slab_hostname'] = node_hostname
                 res['slab_boot_state'] = nodeall_byhostname[node_hostname]['boot_state']
-                
+
                 #res['pl_hostname'] = node['hostname']
                 #res['pl_boot_state'] = \
                             #nodeall_byhostname[node['hostname']]['boot_state']
@@ -268,55 +267,55 @@ class SlabDriver(Driver):
                 sliver_id =  Xrn(slice_urn, type='slice', \
                         id=nodeall_byhostname[node_hostname]['node_id'], \
                         authority=self.hrn).urn
-    
-                res['geni_urn'] = sliver_id 
+
+                res['geni_urn'] = sliver_id
                 #node_name  = node['hostname']
                 if nodeall_byhostname[node_hostname]['boot_state'] == 'Alive':
 
                     res['geni_status'] = 'ready'
                 else:
                     res['geni_status'] = 'failed'
-                    top_level_status = 'failed' 
-                    
+                    top_level_status = 'failed'
+
                 res['geni_error'] = ''
-        
+
                 resources.append(res)
-                
+
             result['geni_status'] = top_level_status
-            result['geni_resources'] = resources 
+            result['geni_resources'] = resources
             logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
                                                     %(resources,res))
-            return result  
-                
-    @staticmethod                
-    def get_user_record(hrn):        
-        """ 
+            return result
+
+    @staticmethod
+    def get_user_record(hrn):
+        """
         Returns the user record based on the hrn from the SFA DB .
-        
+
         :param hrn: user's hrn
         :type hrn: string
         :return : user record from SFA database
         :rtype: RegUser
-        
-        """
-        return dbsession.query(RegRecord).filter_by(hrn = hrn).first() 
-         
-     
-    def testbed_name (self): 
-        """ 
-        Returns testbed's name. 
-        
+
+        """
+        return dbsession.query(RegRecord).filter_by(hrn = hrn).first()
+
+
+    def testbed_name (self):
+        """
+        Returns testbed's name.
+
         :rtype: string
         """
         return self.hrn
-         
+
     # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
     def aggregate_version (self):
         """
-        
-        Returns the testbed's supported rspec advertisement and 
+
+        Returns the testbed's supported rspec advertisement and
         request versions.
-        
+
         :rtype: dict
         """
         version_manager = VersionManager()
@@ -326,15 +325,15 @@ class SlabDriver(Driver):
             if rspec_version.content_type in ['*', 'ad']:
                 ad_rspec_versions.append(rspec_version.to_dict())
             if rspec_version.content_type in ['*', 'request']:
-                request_rspec_versions.append(rspec_version.to_dict()) 
+                request_rspec_versions.append(rspec_version.to_dict())
         return {
             'testbed':self.testbed_name(),
             'geni_request_rspec_versions': request_rspec_versions,
             'geni_ad_rspec_versions': ad_rspec_versions,
-            }  
-            
-   
-         
+            }
+
+
+
     def _get_requested_leases_list(self, rspec):
         """
         Process leases in rspec depending on the rspec version (format)
@@ -342,8 +341,8 @@ class SlabDriver(Driver):
         a lease request list with the mandatory information ( nodes,
         start time and duration) of the valid leases (duration above or equal
         to the senslab experiment minimum duration).
-        
-        :param rspec: rspec request received. 
+
+        :param rspec: rspec request received.
         :type rspec: RSpec
         :return: list of lease requests found in the rspec
         :rtype: list
@@ -351,8 +350,8 @@ class SlabDriver(Driver):
         requested_lease_list = []
         for lease in rspec.version.get_leases():
             single_requested_lease = {}
-            logger.debug("SLABDRIVER.PY \tcreate_sliver lease %s " %(lease))
-            
+            logger.debug("SLABDRIVER.PY \t_get_requested_leases_list lease %s " %(lease))
+
             if not lease.get('lease_id'):
                 if get_authority(lease['component_id']) == \
                                             self.slab_api.root_auth:
@@ -366,99 +365,99 @@ class SlabDriver(Driver):
                     #the lease to the requested leases list
                     duration_in_seconds = \
                             int(single_requested_lease['duration'])
-                    if duration_in_seconds > self.slab_api.GetMinExperimentDurationInSec() :
+                    if duration_in_seconds >= self.slab_api.GetMinExperimentDurationInSec() :
                         requested_lease_list.append(single_requested_lease)
-                        
+
         return requested_lease_list
-                        
-    @staticmethod                    
+
+    @staticmethod
     def _group_leases_by_start_time(requested_lease_list):
         """
         Create dict of leases by start_time, regrouping nodes reserved
-        at the same time, for the same amount of time so as to 
+        at the same time, for the same amount of time so as to
         define one job on OAR.
-        
+
         :param requested_lease_list: list of leases
         :type requested_lease_list: list
         :return: Dictionary with key = start time, value = list of leases
-        with the same start time. 
+        with the same start time.
         :rtype: dictionary
         """
 
         requested_job_dict = {}
         for lease in requested_lease_list:
-            
+
             #In case it is an asap experiment start_time is empty
             if lease['start_time'] == '':
-                lease['start_time'] = '0' 
-                
+                lease['start_time'] = '0'
+
             if lease['start_time'] not in requested_job_dict:
                 if isinstance(lease['hostname'], str):
                     lease['hostname'] = [lease['hostname']]
 
-                    
+
                 requested_job_dict[lease['start_time']] = lease
-                
+
             else :
                 job_lease = requested_job_dict[lease['start_time']]
                 if lease['duration'] == job_lease['duration'] :
-                    job_lease['hostname'].append(lease['hostname'])  
-                                 
+                    job_lease['hostname'].append(lease['hostname'])
+
         return requested_job_dict
-                
+
     def _process_requested_jobs(self, rspec):
         """
-        Turns the requested leases and information into a dictionary 
+        Turns the requested leases and information into a dictionary
         of requested jobs, grouped by starting time.
-        
+
         :param rspec: RSpec received
         :type rspec : RSpec
-        :rtype: dictionary 
+        :rtype: dictionary
         """
         requested_lease_list = self._get_requested_leases_list(rspec)
         logger.debug("SLABDRIVER _process_requested_jobs requested_lease_list \
         %s"%(requested_lease_list))
-        job_dict =  self._group_leases_by_start_time(requested_lease_list) 
+        job_dict =  self._group_leases_by_start_time(requested_lease_list)
         logger.debug("SLABDRIVER _process_requested_jobs  job_dict\
         %s"%(job_dict))
-        
+
         return job_dict
-                
+
     def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
                                                              users, options):
-        """ 
+        """
         Answer to CreateSliver.
-        Creates the leases and slivers for the users from the information 
+        Creates the leases and slivers for the users from the information
         found in the rspec string.
         Launch experiment on OAR if the requested leases is valid. Delete
         no longer requested leases.
-        
 
-        :param creds: user's credentials 
+
+        :param creds: user's credentials
         :type creds: string
         :param users: user record list
         :type users: list
         :param options:
         :type options:
-        
-        :return: a valid Rspec for the slice which has just been 
+
+        :return: a valid Rspec for the slice which has just been
         modified.
         :rtype: RSpec
-        
-        
+
+
         """
         aggregate = SlabAggregate(self)
-        
+
         slices = SlabSlices(self)
         peer = slices.get_peer(slice_hrn)
         sfa_peer = slices.get_sfa_peer(slice_hrn)
-        slice_record = None 
+        slice_record = None
+
         if not isinstance(creds, list):
             creds = [creds]
-    
+
         if users:
-            slice_record = users[0].get('slice_record', {}) 
+            slice_record = users[0].get('slice_record', {})
             logger.debug("SLABDRIVER.PY \t ===============create_sliver \t\
                                         creds %s \r\n \r\n users %s" \
                                         %(creds, users))
@@ -470,27 +469,27 @@ class SlabDriver(Driver):
         logger.debug("SLABDRIVER.PY \t create_sliver \trspec.version \
                                         %s slice_record %s users %s" \
                                         %(rspec.version,slice_record, users))
-                                            
+
 
         # ensure site record exists?
         # ensure slice record exists
         #Removed options to verify_slice SA 14/08/12
         sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
                                                     sfa_peer)
-                                                    
+
         # ensure person records exists
         #verify_persons returns added persons but since the return value
-        #is not used 
+        #is not used
         slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
-                                                    sfa_peer, options=options)                                           
-        #requested_attributes returned by rspec.version.get_slice_attributes() 
+                                                    sfa_peer, options=options)
+        #requested_attributes returned by rspec.version.get_slice_attributes()
         #unused, removed SA 13/08/12
         #rspec.version.get_slice_attributes()
 
         logger.debug("SLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
 
-        # add/remove slice from nodes 
-       
+        # add/remove slice from nodes
+
         #requested_slivers = [node.get('component_id') \
                             #for node in rspec.version.get_nodes_with_slivers()\
                             #if node.get('authority_id') is self.slab_api.root_auth]
@@ -499,131 +498,131 @@ class SlabDriver(Driver):
                                     #requested_slivers %s  listnodes %s" \
                                     #%(requested_slivers,l))
         #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
-        #slices.verify_slice_nodes(sfa_slice, requested_slivers, peer) 
-        
+        #slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
+
 
         requested_job_dict = self._process_requested_jobs(rspec)
-                   
-             
+
+
         logger.debug("SLABDRIVER.PY \tcreate_sliver  requested_job_dict %s "\
-                                                     %(requested_job_dict))    
+                                                     %(requested_job_dict))
         #verify_slice_leases returns the leases , but the return value is unused
-        #here. Removed SA 13/08/12           
+        #here. Removed SA 13/08/12
         slices.verify_slice_leases(sfa_slice, \
                                     requested_job_dict, peer)
-        
+
         return aggregate.get_rspec(slice_xrn=slice_urn, \
                 login=sfa_slice['login'], version=rspec.version)
-        
-        
+
+
     def delete_sliver (self, slice_urn, slice_hrn, creds, options):
         """
         Deletes the lease associated with the slice hrn and the credentials
         if the slice belongs to senslab. Answer to DeleteSliver.
-        
-        :return: 1 if the slice to delete was not found on senslab, 
-        True if the deletion was successful, False otherwise otherwise. 
-        
-        .. note:: Should really be named delete_leases because senslab does 
+
+        :return: 1 if the slice to delete was not found on senslab,
+        True if the deletion was successful, False otherwise otherwise.
+
+        .. note:: Should really be named delete_leases because senslab does
         not have any slivers, but only deals with leases. However, SFA api only
         have delete_sliver define so far. SA 13.05/2013
         """
-        
+
         sfa_slice_list  = self.slab_api.GetSlices(slice_filter = slice_hrn, \
                                             slice_filter_type = 'slice_hrn')
-        
+
         if not sfa_slice_list:
             return 1
-        
+
         #Delete all leases in the slice
         for sfa_slice in sfa_slice_list:
 
-        
+
             logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
             slices = SlabSlices(self)
             # determine if this is a peer slice
-        
-            peer = slices.get_peer(slice_hrn) 
+
+            peer = slices.get_peer(slice_hrn)
 
             logger.debug("SLABDRIVER.PY delete_sliver peer %s \
             \r\n \t sfa_slice %s " %(peer, sfa_slice))
             try:
-              
+
                 self.slab_api.DeleteSliceFromNodes(sfa_slice)
                 return True
             except :
                 return False
-           
-    
+
+
     def list_resources (self, slice_urn, slice_hrn, creds, options):
         """
-        List resources from the senslab aggregate and returns a Rspec 
-        advertisement with resources found when slice_urn and slice_hrn are None 
+        List resources from the senslab aggregate and returns a Rspec
+        advertisement with resources found when slice_urn and slice_hrn are None
         (in case of resource discovery).
         If a slice hrn and urn are provided, list experiment's slice
         nodes in a rspec format. Answer to ListResources.
-        Caching unused. 
+        Caching unused.
         :param options: options used when listing resources (list_leases, info,
-        geni_available) 
+        geni_available)
         :return: rspec string in xml
-        :rtype: string 
+        :rtype: string
         """
-        
-        #cached_requested = options.get('cached', True) 
-    
+
+        #cached_requested = options.get('cached', True)
+
         version_manager = VersionManager()
         # get the rspec's return format from options
         rspec_version = \
                 version_manager.get_version(options.get('geni_rspec_version'))
         version_string = "rspec_%s" % (rspec_version)
-    
+
         #panos adding the info option to the caching key (can be improved)
         if options.get('info'):
             version_string = version_string + "_" + \
                                         options.get('info', 'default')
-                                        
+
         # Adding the list_leases option to the caching key
         if options.get('list_leases'):
             version_string = version_string + "_" + \
             options.get('list_leases', 'default')
-            
+
         # Adding geni_available to caching key
         if options.get('geni_available'):
             version_string = version_string + "_" + \
                 str(options.get('geni_available'))
-    
+
         # look in cache first
         #if cached_requested and self.cache and not slice_hrn:
             #rspec = self.cache.get(version_string)
             #if rspec:
                 #logger.debug("SlabDriver.ListResources: \
                                     #returning cached advertisement")
-                #return rspec 
-    
+                #return rspec
+
         #panos: passing user-defined options
         aggregate = SlabAggregate(self)
-       
+
         rspec =  aggregate.get_rspec(slice_xrn=slice_urn, \
                                         version=rspec_version, options=options)
-       
+
         # cache the result
         #if self.cache and not slice_hrn:
             #logger.debug("Slab.ListResources: stores advertisement in cache")
             #self.cache.add(version_string, rspec)
-    
+
         return rspec
-        
-        
+
+
     def list_slices (self, creds, options):
         """
         Answer to ListSlices.
-        List slices belonging to senslab, returns slice urns list. 
+        List slices belonging to senslab, returns slice urns list.
         No caching used. Options unused but are defined in the SFA method
-        api prototype. 
-        
+        api prototype.
+
         :return: slice urns list
         :rtype: list
-        
+
         """
         # look in cache first
         #if self.cache:
@@ -631,11 +630,11 @@ class SlabDriver(Driver):
             #if slices:
                 #logger.debug("PlDriver.list_slices returns from cache")
                 #return slices
-    
-        # get data from db 
 
-        slices = self.slab_api.GetSlices()        
-        logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))        
+        # get data from db
+
+        slices = self.slab_api.GetSlices()
+        logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
         slice_hrns = [slab_slice['hrn'] for slab_slice in slices]
 
         slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
@@ -644,62 +643,62 @@ class SlabDriver(Driver):
         # cache the result
         #if self.cache:
             #logger.debug ("SlabDriver.list_slices stores value in cache")
-            #self.cache.add('slices', slice_urns) 
-    
+            #self.cache.add('slices', slice_urns)
+
         return slice_urns
-    
-   
+
+
     def register (self, sfa_record, hrn, pub_key):
-        """ 
+        """
         Adding new user, slice, node or site should not be handled
         by SFA.
-        
-        ..warnings:: should not be used. Different components are in charge of 
+
+        ..warnings:: should not be used. Different components are in charge of
         doing this task. Adding nodes = OAR
         Adding users = LDAP Senslab
         Adding slice = Import from LDAP users
         Adding site = OAR
-        
-        :param sfa_record: record provided by the client of the 
-        Register API call. 
+
+        :param sfa_record: record provided by the client of the
+        Register API call.
         :type sfa_record: dict
         """
         return -1
-            
-      
+
+
     def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
         """No site or node record update allowed in Senslab.
-        The only modifications authorized here are key deletion/addition 
+        The only modifications authorized here are key deletion/addition
         on an existing user and password change.
         On an existing user, CAN NOT BE MODIFIED:
         'first_name', 'last_name', 'email'
          DOES NOT EXIST IN SENSLAB:
          'phone', 'url', 'bio','title', 'accepted_aup',
         A slice is bound to its user, so modifying the user's ssh key should
-        modify the slice's GID after an import procedure. 
-        
+        modify the slice's GID after an import procedure.
+
         :param old_sfa_record: what is in the db for this hrn
         :param new_sfa_record: what was passed to the Update call
-        
-        ..seealso:: update in driver.py. 
+
+        ..seealso:: update in driver.py.
         """
-        
+
         pointer = old_sfa_record['pointer']
         old_sfa_record_type = old_sfa_record['type']
 
         # new_key implemented for users only
         if new_key and old_sfa_record_type not in [ 'user' ]:
             raise UnknownSfaType(old_sfa_record_type)
-        
-    
+
+
         if old_sfa_record_type == "user":
             update_fields = {}
             all_fields = new_sfa_record
             for key in all_fields.keys():
                 if key in ['key', 'password']:
                     update_fields[key] = all_fields[key]
-           
-    
+
+
             if new_key:
                 # must check this key against the previous one if it exists
                 persons = self.slab_api.GetPersons([old_sfa_record])
@@ -707,11 +706,11 @@ class SlabDriver(Driver):
                 keys = [person['pkey']]
                 #Get all the person's keys
                 keys_dict = self.slab_api.GetKeys(keys)
-                
+
                 # Delete all stale keys, meaning the user has only one key
                 #at a time
                 #TODO: do we really want to delete all the other keys?
-                #Is this a problem with the GID generation to have multiple 
+                #Is this a problem with the GID generation to have multiple
                 #keys? SA 30/05/13
                 key_exists = False
                 if key in keys_dict:
@@ -725,31 +724,31 @@ class SlabDriver(Driver):
                     #self.slab_api.AddPersonKey(person, {'key_type': 'ssh', \
                                                     #'key': new_key})
         return True
-        
+
 
     def remove (self, sfa_record):
         """
         Removes users only. Mark the user as disabled in
-        LDAP. The user and his slice are then deleted from the db by running an 
+        LDAP. The user and his slice are then deleted from the db by running an
         import on the registry.
-        
-       
-        
-        :param sfa_record: record is the existing sfa record in the db 
+
+
+
+        :param sfa_record: record is the existing sfa record in the db
         :type sfa_record: dict
-        
+
         ..warning::As fas as the slice is concerned, here only the leases are
-        removed from the slice. The slice is record itself is not removed from 
-        the db. 
-        TODO : REMOVE SLICE FROM THE DB AS WELL? SA 14/05/2013, 
-        
-        TODO: return boolean for the slice part 
+        removed from the slice. The slice is record itself is not removed from
+        the db.
+        TODO : REMOVE SLICE FROM THE DB AS WELL? SA 14/05/2013,
+
+        TODO: return boolean for the slice part
         """
         sfa_record_type = sfa_record['type']
         hrn = sfa_record['hrn']
         if sfa_record_type == 'user':
 
-            #get user from senslab ldap  
+            #get user from senslab ldap
             person = self.slab_api.GetPersons(sfa_record)
             #No registering at a given site in Senslab.
             #Once registered to the LDAP, all senslab sites are
@@ -766,5 +765,5 @@ class SlabDriver(Driver):
 
 
             return True
-            
-            
+
+