-import sys
-
-from sfa.util.faults import MissingSfaInfo
+from sfa.util.faults import SliverDoesNotExist, UnknownSfaType
from sfa.util.sfalogging import logger
-from sfa.storage.table import SfaTable
-from sfa.util.defaultdict import defaultdict
+from sfa.storage.alchemy import dbsession
+from sfa.storage.model import RegRecord
+
-from sfa.trust.certificate import *
-from sfa.trust.credential import *
-from sfa.trust.gid import GID
from sfa.managers.driver import Driver
from sfa.rspecs.version_manager import VersionManager
from sfa.rspecs.rspec import RSpec
-from sfa.util.xrn import hrn_to_urn
-from sfa.util.plxrn import slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, hrn_to_pl_login_base
+from sfa.util.xrn import Xrn, hrn_to_urn, get_authority
-## thierry: everything that is API-related (i.e. handling incoming requests)
-# is taken care of
-# SlabDriver should be really only about talking to the senslab testbed
-## thierry : please avoid wildcard imports :)
-from sfa.senslab.OARrestapi import OARapi, OARrestapi
-from sfa.senslab.LDAPapi import LDAPapi
-from sfa.senslab.SenslabImportUsers import SenslabImportUsers
-from sfa.senslab.parsing import parse_filter
from sfa.senslab.slabpostgres import SlabDB
-from sfa.senslab.slabaggregate import SlabAggregate
+
+
+from sfa.senslab.slabaggregate import SlabAggregate, slab_xrn_to_hostname
+
from sfa.senslab.slabslices import SlabSlices
-def list_to_dict(recs, key):
- """
- convert a list of dictionaries into a dictionary keyed on the
- specified dictionary key
- """
- # print>>sys.stderr, " \r\n \t\t 1list_to_dict : rec %s \r\n \t\t list_to_dict key %s" %(recs,key)
- keys = [rec[key] for rec in recs]
- #print>>sys.stderr, " \r\n \t\t list_to_dict : rec %s \r\n \t\t list_to_dict keys %s" %(recs,keys)
- return dict(zip(keys, recs))
-
-# thierry : note
-# this inheritance scheme is so that the driver object can receive
-# GetNodes or GetSites sorts of calls directly
-# and thus minimize the differences in the managers with the pl version
+
+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
+
+ """
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
+ """
Driver.__init__ (self, config)
- self.config=config
- self.hrn = config.SFA_INTERFACE_HRN
-
- self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
-
-
- print >>sys.stderr, "\r\n_____________ SFA SENSLAB DRIVER \r\n"
- # thierry - just to not break the rest of this code
-
-
- self.oar = OARapi()
- self.ldap = LDAPapi()
- self.users = SenslabImportUsers()
- self.time_format = "%Y-%m-%d %H:%M:%S"
- self.db = SlabDB()
- #self.logger=sfa_logger()
- self.cache=None
-
-
-
- def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
+ self.config = config
+
+ 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.
+
+ :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.
+
+ :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
+ 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
+ #information is in the Senslab's DB.
+ if str(record['type']) == 'slice':
+ if 'reg_researchers' in record and \
+ isinstance(record['reg_researchers'], list) :
+ record['reg_researchers'] = \
+ record['reg_researchers'][0].__dict__
+ record.update({'PI':[record['reg_researchers']['hrn']],
+ 'researcher': [record['reg_researchers']['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:
+ 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))
+
+ if str(record['type']) == 'user':
+ #The record is a SFA user record.
+ #Get the information about his slice from Senslab's DB
+ #and add it to the user record.
+ 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,
+ #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))
+ recslice = {}
+ recslice = recslice_list[0]
+ recslice.update({'PI':[recuser['hrn']],
+ 'researcher': [recuser['hrn']],
+ 'name':record['hrn'],
+ 'node_ids': [],
+ 'oar_job_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
+ user_slab = self.slab_api.GetPersons([record])
+
+
+ record.update(user_slab[0])
+ #For client_helper.py compatibility
+ record.update( { 'geni_urn':'',
+ 'keys':'',
+ 'key_ids':'' })
+ record_list.append(recslice)
+
+ logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
+ 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
+ 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]
+
+
+ #Make a list of all the nodes hostnames in use for this slice
+ slice_nodes_list = []
+ #for single_slice in slice_list:
+ #for node in single_slice['node_ids']:
+ #slice_nodes_list.append(node['hostname'])
+ #for node in one_slice:
+ #slice_nodes_list.append(node['hostname'])
+ slice_nodes_list = one_slice['node_ids']
+ #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 single_slice in slice_list:
+
+ #For compatibility
+ top_level_status = 'empty'
+ result = {}
+ result.fromkeys(\
+ ['geni_urn','geni_error', 'pl_login','geni_status','geni_resources'], None)
+ result['pl_login'] = one_slice['reg_researchers'][0].hrn
+ 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'] = []
+ return result
+
+ 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 = []
+ for node_hostname in single_slice['node_ids']:
+ 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']
+ #res['pl_last_contact'] = strftime(self.time_format, \
+ #gmtime(float(timestamp)))
+ sliver_id = Xrn(slice_urn, type='slice', \
+ id=nodeall_byhostname[node_hostname]['node_id'], \
+ authority=self.hrn).urn
+
+ 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'
+
+ res['geni_error'] = ''
+
+ resources.append(res)
+
+ result['geni_status'] = top_level_status
+ result['geni_resources'] = resources
+ logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
+ %(resources,res))
+ 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.
+
+ :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
+ request versions.
+
+ :rtype: dict
+ """
+ version_manager = VersionManager()
+ ad_rspec_versions = []
+ request_rspec_versions = []
+ for rspec_version in version_manager.versions:
+ 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())
+ 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)
+ type. Find the lease requests in the rspec and creates
+ 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.
+ :type rspec: RSpec
+ :return: list of lease requests found in the rspec
+ :rtype: list
+ """
+ requested_lease_list = []
+ for lease in rspec.version.get_leases():
+ single_requested_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:
+ single_requested_lease['hostname'] = \
+ slab_xrn_to_hostname(\
+ lease.get('component_id').strip())
+ single_requested_lease['start_time'] = \
+ lease.get('start_time')
+ single_requested_lease['duration'] = lease.get('duration')
+ #Check the experiment's duration is valid before adding
+ #the lease to the requested leases list
+ duration_in_seconds = \
+ int(single_requested_lease['duration'])
+ if duration_in_seconds >= self.slab_api.GetMinExperimentDurationInSec() :
+ requested_lease_list.append(single_requested_lease)
+
+ return requested_lease_list
+
+ @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
+ 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.
+ :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'
+
+ 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'])
+
+ return requested_job_dict
+
+ def _process_requested_jobs(self, rspec):
+ """
+ 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
+ """
+ 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)
+ 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
+ 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
+ :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
+ modified.
+ :rtype: RSpec
+
+
+ """
aggregate = SlabAggregate(self)
- #aggregate = SlabAggregate(self)
+
slices = SlabSlices(self)
peer = slices.get_peer(slice_hrn)
sfa_peer = slices.get_sfa_peer(slice_hrn)
- slice_record=None
- #print>>sys.stderr, " \r\n \r\n create_sliver creds %s \r\n \r\n users %s " %(creds,users)
-
+ slice_record = None
+
if not isinstance(creds, list):
creds = [creds]
- #for cred in creds:
- #cred_obj=Credential(string=cred)
- #print >>sys.stderr," \r\n \r\n create_sliver cred %s " %(cred)
- #GIDcall = cred_obj.get_gid_caller()
- #GIDobj = cred_obj.get_gid_object()
- #print >>sys.stderr," \r\n \r\n create_sliver GIDobj pubkey %s hrn %s " %(GIDobj.get_pubkey().get_pubkey_string(), GIDobj.get_hrn())
- #print >>sys.stderr," \r\n \r\n create_sliver GIDcall pubkey %s hrn %s" %(GIDcall.get_pubkey().get_pubkey_string(),GIDobj.get_hrn())
-
-
- #tmpcert = GID(string = users[0]['gid'])
- #print >>sys.stderr," \r\n \r\n create_sliver tmpcer pubkey %s hrn %s " %(tmpcert.get_pubkey().get_pubkey_string(), tmpcert.get_hrn())
-
if users:
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))
+ slice_record['user'] = {'keys':users[0]['keys'], \
+ 'email':users[0]['email'], \
+ 'hrn':slice_record['reg-researchers'][0]}
# parse rspec
rspec = RSpec(rspec_string)
- requested_attributes = rspec.version.get_slice_attributes()
-
- # ensure site record exists
- #site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer, options=options)
+ 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
- slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer, options=options)
+ #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
- persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer, options=options)
- # ensure slice attributes exists
- #slices.verify_slice_attributes(slice, requested_attributes, options=options)
-
+ #verify_persons returns added persons but since the return value
+ #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()
+ #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
- requested_slivers = [node.get('component_name') for node in rspec.version.get_nodes_with_slivers()]
- nodes = slices.verify_slice_nodes(slice, requested_slivers, peer)
-
-
-
- # handle MyPLC peer association.
- # only used by plc and ple.
- #slices.handle_peer(site, slice, persons, peer)
-
- return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
-
-
+
+ #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]
+ #l = [ node for node in rspec.version.get_nodes_with_slivers() ]
+ #logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
+ #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)
+
+
+ requested_job_dict = self._process_requested_jobs(rspec)
+
+
+ logger.debug("SLABDRIVER.PY \tcreate_sliver requested_job_dict %s "\
+ %(requested_job_dict))
+ #verify_slice_leases returns the leases , but the return value is unused
+ #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):
-
- slices = self.GetSlices({'slice_hrn': slice_hrn})
- if not slices:
+ """
+ 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
+ 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
- slice = slices[0]
-
- # 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
- # is the only/last call to this last method in plc.peers
- peer = peers.get_peer(self, slice_hrn)
- try:
- if peer:
- self.UnBindObjectFromPeer('slice', slice['slice_id'], peer)
- self.DeleteSliceFromNodes(slice_hrn, slice['node_ids'])
- finally:
- if peer:
- self.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id'])
- return 1
-
-
-
-
- # first 2 args are None in case of resource discovery
+
+ #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)
+
+ 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):
- #cached_requested = options.get('cached', True)
-
+ """
+ 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.
+ :param options: options used when listing resources (list_leases, info,
+ geni_available)
+ :return: rspec string in xml
+ :rtype: string
+ """
+
+ #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'))
+ 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')
-
+ 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
-
+ #logger.debug("SlabDriver.ListResources: \
+ #returning cached advertisement")
+ #return rspec
+
#panos: passing user-defined options
- #print "manager options = ",options
aggregate = SlabAggregate(self)
- rspec = aggregate.get_rspec(slice_xrn=slice_urn, version=rspec_version,
- options=options)
-
+
+ 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.
+ No caching used. Options unused but are defined in the SFA method
+ api prototype.
+
+ :return: slice urns list
+ :rtype: list
+
+ """
# look in cache first
#if self.cache:
#slices = self.cache.get('slices')
#if slices:
#logger.debug("PlDriver.list_slices returns from cache")
#return slices
-
- # get data from db
- slices = self.GetSlices()
- slice_hrns = [slicename_to_hrn(self.hrn, slice['slice_hrn']) for slice in slices]
- slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
-
+
+ # 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') \
+ for slice_hrn in slice_hrns]
+
# 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
-
- #No site or node register supported
+
+
def register (self, sfa_record, hrn, pub_key):
- type = sfa_record['type']
- pl_record = self.sfa_fields_to_pl_fields(type, hrn, sfa_record)
-
- #if type == 'authority':
- #sites = self.shell.GetSites([pl_record['login_base']])
- #if not sites:
- #pointer = self.shell.AddSite(pl_record)
- #else:
- #pointer = sites[0]['site_id']
-
- if type == 'slice':
- acceptable_fields=['url', 'instantiation', 'name', 'description']
- for key in pl_record.keys():
- if key not in acceptable_fields:
- pl_record.pop(key)
- slices = self.GetSlices([pl_record['hrn']])
- if not slices:
- pointer = self.AddSlice(pl_record)
- else:
- pointer = slices[0]['slice_id']
-
- elif type == 'user':
- persons = self.GetPersons([sfa_record['hrn']])
- if not persons:
- pointer = self.AddPerson(dict(sfa_record))
- #add in LDAP
- else:
- pointer = persons[0]['person_id']
-
- #Does this make sense to senslab ?
- #if 'enabled' in sfa_record and sfa_record['enabled']:
- #self.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
-
- # add this person to the site only if she is being added for the first
- # time by sfa and doesont already exist in plc
- if not persons or not persons[0]['site_ids']:
- login_base = get_leaf(sfa_record['authority'])
- self.AddPersonToSite(pointer, login_base)
-
- # What roles should this user have?
- self.AddRoleToPerson('user', pointer)
- # Add the user's key
- if pub_key:
- self.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
-
- #No node adding outside OAR
- #elif type == 'node':
- #login_base = hrn_to_pl_login_base(sfa_record['authority'])
- #nodes = self.GetNodes([pl_record['hostname']])
- #if not nodes:
- #pointer = self.AddNode(login_base, pl_record)
- #else:
- #pointer = nodes[0]['node_id']
-
- return pointer
-
- #No site or node record update allowed
+ """
+ Adding new user, slice, node or site should not be handled
+ by SFA.
+
+ ..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.
+ :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
+ 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.
+
+ :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.
+ """
+
pointer = old_sfa_record['pointer']
- type = old_sfa_record['type']
+ old_sfa_record_type = old_sfa_record['type']
# new_key implemented for users only
- if new_key and type not in [ 'user' ]:
- raise UnknownSfaType(type)
-
- #if (type == "authority"):
- #self.shell.UpdateSite(pointer, new_sfa_record)
-
- if type == "slice":
- pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
- if 'name' in pl_record:
- pl_record.pop('name')
- self.UpdateSlice(pointer, pl_record)
-
- elif type == "user":
+ 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 ['first_name', 'last_name', 'title', 'email',
- 'password', 'phone', 'url', 'bio', 'accepted_aup',
- 'enabled']:
+ if key in ['key', 'password']:
update_fields[key] = all_fields[key]
- self.UpdatePerson(pointer, update_fields)
-
+
+
if new_key:
# must check this key against the previous one if it exists
- persons = self.GetPersons([pointer], ['key_ids'])
+ persons = self.slab_api.GetPersons([old_sfa_record])
person = persons[0]
- keys = person['key_ids']
- keys = self.GetKeys(person['key_ids'])
-
- # Delete all stale keys
+ 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
+ #keys? SA 30/05/13
key_exists = False
- for key in keys:
- if new_key != key['key']:
- self.DeleteKey(key['key_id'])
- else:
- key_exists = True
- if not key_exists:
- self.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
-
- #elif type == "node":
- #self.UpdateNode(pointer, new_sfa_record)
-
+ if key in keys_dict:
+ key_exists = True
+ else:
+ #remove all the other keys
+ for key in keys_dict:
+ self.slab_api.DeleteKey(person, key)
+ self.slab_api.AddPersonKey(person, \
+ {'sshPublicKey': person['pkey']},{'sshPublicKey': new_key} )
+ #self.slab_api.AddPersonKey(person, {'key_type': 'ssh', \
+ #'key': new_key})
return True
-
+
def remove (self, sfa_record):
- type=sfa_record['type']
- hrn=sfa_record['hrn']
- record_id= sfa_record['record_id']
- if type == 'user':
- username = hrn.split(".")[len(hrn.split(".")) -1]
- #get user in ldap
- persons = self.GetPersons(username)
- # only delete this person if he has site ids. if he doesnt, it probably means
- # he was just removed from a site, not actually deleted
- if persons and persons[0]['site_ids']:
- self.DeletePerson(username)
- elif type == 'slice':
- if self.GetSlices(hrn):
- self.DeleteSlice(hrn)
-
- #elif type == 'authority':
- #if self.GetSites(pointer):
- #self.DeleteSite(pointer)
+ """
+ Removes users only. Mark the user as disabled in
+ 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
+ :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
+ """
+ sfa_record_type = sfa_record['type']
+ hrn = sfa_record['hrn']
+ if sfa_record_type == 'user':
+
+ #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
+ #accesible.
+ if person :
+ #Mark account as disabled in ldap
+ return self.slab_api.DeletePerson(sfa_record)
+
+ elif sfa_record_type == 'slice':
+ if self.slab_api.GetSlices(slice_filter = hrn, \
+ slice_filter_type = 'slice_hrn'):
+ ret = self.slab_api.DeleteSlice(sfa_record)
+
+
+
+ return True
+
- return True
-
- def GetPeers (self,auth = None, peer_filter=None, return_fields=None):
- table = SfaTable()
- return_records = []
- records_list = table.findObjects({'type':'authority+sa'})
- if not peer_filter and not return_fields:
- return records_list
- return_records = parse_filter(records_list,peer_filter, 'peers', return_fields)
-
- return return_records
-
-
-
- def GetPersons(self, person_filter=None, return_fields=None):
-
- person_list = self.ldap.ldapFind({'authority': self.root_auth })
-
- #check = False
- #if person_filter and isinstance(person_filter, dict):
- #for k in person_filter.keys():
- #if k in person_list[0].keys():
- #check = True
-
- return_person_list = parse_filter(person_list,person_filter ,'persons', return_fields)
- if return_person_list:
- print>>sys.stderr, " \r\n GetPersons person_filter %s return_fields %s return_person_list %s " %(person_filter,return_fields,return_person_list)
- return return_person_list
-
-
- def GetJobs(self,job_id= None, resources=True,return_fields=None, details = None):
- if job_id and resources is False:
- self.oar.parser.SendRequest("GET_jobs_id", job_id)
- if job_id and resources:
- self.oar.parser.SendRequest("GET_jobs_id_resources", job_id)
-
- #node_dict = self.oar.parser.GetNodesFromOARParse()
- #return_node_list = []
-
- #if not (node_filter or return_fields):
- #return_node_list = node_dict.values()
- #return return_node_list
-
- #return_node_list= parse_filter(node_dict.values(),node_filter ,'node', return_fields)
- #return return_node_list
-
- def GetNodes(self,node_filter= None, return_fields=None):
-
- self.oar.parser.SendRequest("GET_resources_full")
- node_dict = self.oar.parser.GetNodesFromOARParse()
- return_node_list = []
-
- if not (node_filter or return_fields):
- return_node_list = node_dict.values()
- return return_node_list
-
- return_node_list= parse_filter(node_dict.values(),node_filter ,'node', return_fields)
- return return_node_list
-
- #def GetSites(self, auth, site_filter = None, return_fields=None):
- #self.oar.parser.SendRequest("GET_resources_full")
- #site_dict = self.oar.parser.GetSitesFromOARParse()
- #return_site_list = []
- #site = site_dict.values()[0]
- #if not (site_filter or return_fields):
- #return_site_list = site_dict.values()
- #return return_site_list
-
- #return_site_list = parse_filter(site_dict.values(),site_filter ,'site', return_fields)
- #return return_site_list
-
- def GetSlices(self,slice_filter = None, return_fields=None):
-
- return_slice_list =[]
- sliceslist = self.db.find('slice',columns = ['oar_job_id', 'slice_hrn', 'record_id_slice','record_id_user'])
- print >>sys.stderr, " \r\n \r\n SLABDRIVER.PY GetSlices slices %s slice_filter %s " %(sliceslist,slice_filter)
- #slicesdict = sliceslist[0]
-
-
- if not (slice_filter or return_fields) and sliceslist:
- for sl in sliceslist:
- if sl['oar_job_id'] is not -1:
- print >>sys.stderr, " \r\n \r\n SLABDRIVER.PY GetSlices sl %s" %(sl)
- self.GetJobs( sl['oar_job_id'],resources=False)
- return_slice_list = sliceslist
- return return_slice_list
-
- return_slice_list = parse_filter(sliceslist, slice_filter,'slice', return_fields)
- for sl in return_slice_list:
- if sl['oar_job_id'] is not -1:
- self.GetJobs( sl['oar_job_id'],resources=False)
- #print >>sys.stderr, " \r\n \r\n SLABDRIVER.PY GetSlices return_slice_list %s" %(return_slice_list)
- return return_slice_list
-
- def testbed_name (self): return "senslab2"
-
- # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
- def aggregate_version (self):
- version_manager = VersionManager()
- ad_rspec_versions = []
- request_rspec_versions = []
- for rspec_version in version_manager.versions:
- 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())
- return {
- 'testbed':self.testbed_name(),
- 'geni_request_rspec_versions': request_rspec_versions,
- 'geni_ad_rspec_versions': ad_rspec_versions,
- }
-
-
-
-
-
-
- ##
- # Convert SFA fields to PLC fields for use when registering up updating
- # registry record in the PLC database
- #
- # @param type type of record (user, slice, ...)
- # @param hrn human readable name
- # @param sfa_fields dictionary of SFA fields
- # @param pl_fields dictionary of PLC fields (output)
-
- def sfa_fields_to_pl_fields(self, type, hrn, record):
-
- def convert_ints(tmpdict, int_fields):
- for field in int_fields:
- if field in tmpdict:
- tmpdict[field] = int(tmpdict[field])
-
- pl_record = {}
- #for field in record:
- # pl_record[field] = record[field]
-
- if type == "slice":
- #instantion used in get_slivers ?
- if not "instantiation" in pl_record:
- pl_record["instantiation"] = "senslab-instantiated"
- pl_record["hrn"] = hrn_to_pl_slicename(hrn)
- if "url" in record:
- pl_record["url"] = record["url"]
- if "description" in record:
- pl_record["description"] = record["description"]
- if "expires" in record:
- pl_record["expires"] = int(record["expires"])
-
- #nodes added by OAR only and then imported to SFA
- #elif type == "node":
- #if not "hostname" in pl_record:
- #if not "hostname" in record:
- #raise MissingSfaInfo("hostname")
- #pl_record["hostname"] = record["hostname"]
- #if not "model" in pl_record:
- #pl_record["model"] = "geni"
-
- #One authority only
- #elif type == "authority":
- #pl_record["login_base"] = hrn_to_pl_login_base(hrn)
-
- #if not "name" in pl_record:
- #pl_record["name"] = hrn
-
- #if not "abbreviated_name" in pl_record:
- #pl_record["abbreviated_name"] = hrn
-
- #if not "enabled" in pl_record:
- #pl_record["enabled"] = True
-
- #if not "is_public" in pl_record:
- #pl_record["is_public"] = True
-
- return pl_record
-
-
-
-
- def AddSliceToNodes(self, slice_name, added_nodes, slice_user=None):
- print>>sys.stderr, "\r\n \r\n AddSliceToNodes slice_name %s added_nodes %s username %s" %(slice_name,added_nodes,slice_user )
- site_list = []
- nodeid_list =[]
- resource = ""
- reqdict = {}
- reqdict['property'] ="network_address in ("
- for node in added_nodes:
- #Get the ID of the node : remove the root auth and put the site in a separate list
- tmp = node.strip(self.root_auth+".")
- l = tmp.split("_")
-
- nodeid= (l[len(l)-1])
- reqdict['property'] += "'"+ nodeid +"', "
- nodeid_list.append(nodeid)
- site_list.append( l[0] )
-
- reqdict['property'] = reqdict['property'][0: len( reqdict['property'])-2] +")"
- reqdict['resource'] ="network_address="+ str(len(nodeid_list))
- reqdict['resource']+= ",walltime=" + str(00) + ":" + str(05) + ":" + str(00)
- reqdict['script_path'] = "/bin/sleep 320"
- reqdict['type'] = "deploy"
- print>>sys.stderr, "\r\n \r\n AddSliceToNodes reqdict %s \r\n site_list %s" %(reqdict,site_list)
- OAR = OARrestapi()
- answer = OAR.POSTRequestToOARRestAPI('POST_job',reqdict,slice_user)
- print>>sys.stderr, "\r\n \r\n AddSliceToNodes jobid %s " %(answer)
- self.db.update('slice',['oar_job_id'], [answer['id']], 'slice_hrn', slice_name)
- return
-
-
-
-
- def DeleteSliceFromNodes(self, slice_name, deleted_nodes):
- return
-
-
-
- def fill_record_sfa_info(self, records):
-
- def startswith(prefix, values):
- return [value for value in values if value.startswith(prefix)]
-
- # get person ids
- person_ids = []
- site_ids = []
- for record in records:
- person_ids.extend(record.get("person_ids", []))
- site_ids.extend(record.get("site_ids", []))
- if 'site_id' in record:
- site_ids.append(record['site_id'])
-
- #print>>sys.stderr, "\r\n \r\n _fill_record_sfa_info ___person_ids %s \r\n \t\t site_ids %s " %(person_ids, site_ids)
-
- # get all pis from the sites we've encountered
- # and store them in a dictionary keyed on site_id
- site_pis = {}
- if site_ids:
- pi_filter = {'|roles': ['pi'], '|site_ids': site_ids}
- pi_list = self.GetPersons( pi_filter, ['person_id', 'site_ids'])
- #print>>sys.stderr, "\r\n \r\n _fill_record_sfa_info ___ GetPersons ['person_id', 'site_ids'] pi_ilist %s" %(pi_list)
-
- for pi in pi_list:
- # we will need the pi's hrns also
- person_ids.append(pi['person_id'])
-
- # we also need to keep track of the sites these pis
- # belong to
- for site_id in pi['site_ids']:
- if site_id in site_pis:
- site_pis[site_id].append(pi)
- else:
- site_pis[site_id] = [pi]
-
- # get sfa records for all records associated with these records.
- # we'll replace pl ids (person_ids) with hrns from the sfa records
- # we obtain
-
- # get the sfa records
- table = SfaTable()
- person_list, persons = [], {}
- person_list = table.find({'type': 'user', 'pointer': person_ids})
- # create a hrns keyed on the sfa record's pointer.
- # Its possible for multiple records to have the same pointer so
- # the dict's value will be a list of hrns.
- persons = defaultdict(list)
- for person in person_list:
- persons[person['pointer']].append(person)
-
- # get the pl records
- pl_person_list, pl_persons = [], {}
- pl_person_list = self.GetPersons(person_ids, ['person_id', 'roles'])
- pl_persons = list_to_dict(pl_person_list, 'person_id')
- #print>>sys.stderr, "\r\n \r\n _fill_record_sfa_info ___ _list %s \r\n \t\t SenslabUsers.GetPersons ['person_id', 'roles'] pl_persons %s \r\n records %s" %(pl_person_list, pl_persons,records)
- # fill sfa info
-
- for record in records:
- # skip records with no pl info (top level authorities)
- #Sandrine 24 oct 11 2 lines
- #if record['pointer'] == -1:
- #continue
- sfa_info = {}
- type = record['type']
- if (type == "slice"):
- # all slice users are researchers
- #record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice') ? besoin ou pas ?
- record['PI'] = []
- record['researcher'] = []
- for person_id in record.get('person_ids', []):
- #Sandrine 24 oct 11 line
- #for person_id in record['person_ids']:
- hrns = [person['hrn'] for person in persons[person_id]]
- record['researcher'].extend(hrns)
-
- # pis at the slice's site
- pl_pis = site_pis[record['site_id']]
- pi_ids = [pi['person_id'] for pi in pl_pis]
- for person_id in pi_ids:
- hrns = [person['hrn'] for person in persons[person_id]]
- record['PI'].extend(hrns)
- record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
- record['geni_creator'] = record['PI']
-
- elif (type == "authority"):
- record['PI'] = []
- record['operator'] = []
- record['owner'] = []
- for pointer in record['person_ids']:
- if pointer not in persons or pointer not in pl_persons:
- # this means there is not sfa or pl record for this user
- continue
- hrns = [person['hrn'] for person in persons[pointer]]
- roles = pl_persons[pointer]['roles']
- if 'pi' in roles:
- record['PI'].extend(hrns)
- if 'tech' in roles:
- record['operator'].extend(hrns)
- if 'admin' in roles:
- record['owner'].extend(hrns)
- # xxx TODO: OrganizationName
- elif (type == "node"):
- sfa_info['dns'] = record.get("hostname", "")
- # xxx TODO: URI, LatLong, IP, DNS
-
- elif (type == "user"):
- sfa_info['email'] = record.get("email", "")
- sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
- sfa_info['geni_certificate'] = record['gid']
- # xxx TODO: PostalAddress, Phone
-
- #print>>sys.stderr, "\r\n \r\rn \t\t \t <<<<<<<<<<<<<<<<<<<<<<<< fill_record_sfa_info sfa_info %s \r\n record %s : "%(sfa_info,record)
- record.update(sfa_info)
-
- def augment_records_with_testbed_info (self, sfa_records):
- return self.fill_record_info (sfa_records)
-
- def fill_record_info(self, records):
- """
- Given a SFA record, fill in the senslab specific and SFA specific
- fields in the record.
- """
- print >>sys.stderr, "\r\n \t\t BEFORE fill_record_info %s" %(records)
- if isinstance(records, list):
- records = [records]
- #print >>sys.stderr, "\r\n \t\t BEFORE fill_record_pl_info %s" %(records)
-
- try:
- if records['type'] == 'slice':
-
- sfatable = SfaTable()
- recslice = self.db.find('slice',str(records['hrn']))
- if isinstance(recslice,list) and len(recslice) == 1:
- recslice = recslice[0]
- recuser = sfatable.find( recslice['record_id_user'], ['hrn'])
-
- print >>sys.stderr, "\r\n \t\t SLABDRIVER.PY fill_record_info %s" %(recuser)
- records['type']
- if isinstance(recuser,list) and len(recuser) == 1:
- recuser = recuser[0]
- records.update({'PI':[recuser['hrn']],
- 'researcher': [recuser['hrn']],
- 'name':records['hrn'], 'oar_job_id':recslice['oar_job_id'],
-
- 'node_ids': [],
- 'person_ids':[recslice['record_id_user']]})
- except TypeError:
- print >>sys.stderr, "\r\n \t\t SLABDRIVER fill_record_info EXCEPTION RECORDS : %s" %(records)
- return
-
- #self.fill_record_pl_info(records)
- ##print >>sys.stderr, "\r\n \t\t after fill_record_pl_info %s" %(records)
- #self.fill_record_sfa_info(records)
- #print >>sys.stderr, "\r\n \t\t after fill_record_sfa_info"
-
- #def update_membership_list(self, oldRecord, record, listName, addFunc, delFunc):
- ## get a list of the HRNs tht are members of the old and new records
- #if oldRecord:
- #oldList = oldRecord.get(listName, [])
- #else:
- #oldList = []
- #newList = record.get(listName, [])
-
- ## if the lists are the same, then we don't have to update anything
- #if (oldList == newList):
- #return
-
- ## build a list of the new person ids, by looking up each person to get
- ## their pointer
- #newIdList = []
- #table = SfaTable()
- #records = table.find({'type': 'user', 'hrn': newList})
- #for rec in records:
- #newIdList.append(rec['pointer'])
-
- ## build a list of the old person ids from the person_ids field
- #if oldRecord:
- #oldIdList = oldRecord.get("person_ids", [])
- #containerId = oldRecord.get_pointer()
- #else:
- ## if oldRecord==None, then we are doing a Register, instead of an
- ## update.
- #oldIdList = []
- #containerId = record.get_pointer()
-
- ## add people who are in the new list, but not the oldList
- #for personId in newIdList:
- #if not (personId in oldIdList):
- #addFunc(self.plauth, personId, containerId)
-
- ## remove people who are in the old list, but not the new list
- #for personId in oldIdList:
- #if not (personId in newIdList):
- #delFunc(self.plauth, personId, containerId)
-
- #def update_membership(self, oldRecord, record):
- #print >>sys.stderr, " \r\n \r\n ***SLABDRIVER.PY update_membership record ", record
- #if record.type == "slice":
- #self.update_membership_list(oldRecord, record, 'researcher',
- #self.users.AddPersonToSlice,
- #self.users.DeletePersonFromSlice)
- #elif record.type == "authority":
- ## xxx TODO
- #pass
-
-### thierry
-# I don't think you plan on running a component manager at this point
-# let me clean up the mess of ComponentAPI that is deprecated anyways