- user_keys = user.get('keys', [])
- updated_persons.append(user)
- for key_string in user_keys:
- requested_keys.append(key_string)
- if key_string not in existing_keys:
- key = {'key': key_string, 'key_type': 'ssh'}
- try:
- if peer:
- person = persondict[user['email']]
- self.driver.shell.UnBindObjectFromPeer('person', person['person_id'], peer['shortname'])
- key['key_id'] = self.driver.shell.AddPersonKey(user['email'], key)
- if peer:
- key_index = user_keys.index(key['key'])
- remote_key_id = user['key_ids'][key_index]
- self.driver.shell.BindObjectToPeer('key', key['key_id'], peer['shortname'], remote_key_id)
-
- finally:
- if peer:
- self.driver.shell.BindObjectToPeer('person', person['person_id'], peer['shortname'], user['person_id'])
-
- # remove old keys (only if we are not appending)
- append = options.get('append', True)
- if append == False:
- removed_keys = set(existing_keys).difference(requested_keys)
- for existing_key_id in keydict:
- if keydict[existing_key_id] in removed_keys:
- try:
- if peer:
- self.driver.shell.UnBindObjectFromPeer('key', existing_key_id, peer['shortname'])
- self.driver.shell.DeleteKey(existing_key_id)
- except:
- pass
-
- def verify_slice_attributes(self, slice, requested_slice_attributes, options={}, admin=False):
- append = options.get('append', True)
- # get list of attributes users ar able to manage
+ logger.debug("incoming user {}".format(user))
+
+ # compute the hrn's for the authority and site
+ top_auth_hrn = top_auth(slice_hrn)
+ site_hrn = '.'.join(slice_hrn.split('.')[:-1])
+ slice_part = slice_hrn.split('.')[-1]
+ # deduce login_base and slice_name
+ if top_auth_hrn == self.driver.hrn:
+ login_base = slice_hrn.split('.')[-2][:12]
+ else:
+ login_base = hash_loginbase(site_hrn)
+ slice_name = '_'.join([login_base, slice_part])
+
+ # locate the site object
+ # due to a limitation in PLCAPI, we have to specify 'hrn' as part of
+ # the return fields
+ site = self.driver.shell.GetSites(
+ {'peer_id': None, 'hrn': site_hrn}, ['site_id', 'hrn'])[0]
+ site_id = site['site_id']
+
+ # locate the slice object
+ slice = self.driver.shell.GetSlices(
+ {'peer_id': None, 'hrn': slice_hrn},
+ ['slice_id', 'hrn', 'person_ids'])[0]
+ slice_id = slice['slice_id']
+ slice_person_ids = slice['person_ids']
+
+ # the common set of attributes for our calls to GetPersons
+ person_fields = ['person_id', 'email', 'hrn']
+
+ # for the intended set of hrns, locate existing persons
+ target_hrns = [user['hrn'] for user in users]
+ target_existing_persons = self.driver.shell.GetPersons(
+ {'peer_id': None, 'hrn': target_hrns}, person_fields)
+ target_existing_person_ids = [person['person_id']
+ for person in target_existing_persons]
+ # find out the hrns that *do not* have a corresponding person
+ existing_hrns = [person['hrn'] for person in target_existing_persons]
+ tocreate_hrns = set(target_hrns) - set(existing_hrns)
+ # create these
+ target_created_person_ids = [self.create_person_from_user(
+ users_by_hrn[hrn], site_id) for hrn in tocreate_hrns]
+
+ # we can partition the persons of interest into one of these 3 classes
+ add_person_ids = set(target_created_person_ids) | set(
+ target_existing_person_ids) - set(slice_person_ids)
+ keep_person_ids = set(
+ target_existing_person_ids) & set(slice_person_ids)
+ del_person_ids = set(slice_person_ids) - \
+ set(target_existing_person_ids)
+
+ # delete
+ for person_id in del_person_ids:
+ self.driver.shell.DeletePersonFromSlice(person_id, slice_id)
+
+ # about the last 2 sets, for managing keys, we need to trace back person_id -> user
+ # and for this we need all the Person objects; we already have the target_existing ones
+ # also we avoid issuing a call if possible
+ target_created_persons = [] if not target_created_person_ids \
+ else self.driver.shell.GetPersons(
+ {'peer_id': None, 'person_id': target_created_person_ids},
+ person_fields)
+ persons_by_person_id = {
+ person['person_id']: person
+ for person in target_existing_persons + target_created_persons}
+
+ def user_by_person_id(person_id):
+ person = persons_by_person_id[person_id]
+ hrn = person['hrn']
+ return users_by_hrn[hrn]
+
+ persons_to_verify_keys = {}
+ # add
+ for person_id in add_person_ids:
+ self.driver.shell.AddPersonToSlice(person_id, slice_id)
+ persons_to_verify_keys[person_id] = user_by_person_id(person_id)
+ # Update kept persons
+ for person_id in keep_person_ids:
+ persons_to_verify_keys[person_id] = user_by_person_id(person_id)
+ self.verify_keys(persons_to_verify_keys, options)
+
+ # return hrns of the newly added persons
+
+ return [persons_by_person_id[person_id]['hrn']
+ for person_id in add_person_ids]
+
+ def verify_keys(self, persons_to_verify_keys, options=None):
+ if options is None:
+ options = {}
+ # we only add keys that comes from sfa to persons in PL
+ for person_id in persons_to_verify_keys:
+ person_sfa_keys = persons_to_verify_keys[person_id].get('keys', [])
+ person_pl_keys = self.driver.shell.GetKeys(
+ {'person_id': int(person_id)})
+ person_pl_keys_list = [key['key'] for key in person_pl_keys]
+
+ keys_to_add = set(person_sfa_keys).difference(person_pl_keys_list)
+
+ for key_string in keys_to_add:
+ key = {'key': key_string, 'key_type': 'ssh'}
+ self.driver.shell.AddPersonKey(int(person_id), key)
+
+ def verify_slice_tags(self, slice, requested_slice_attributes,
+ options=None, admin=False):
+ """
+ This function deals with slice tags, and supports 3 modes described
+ in the 'pltags' option that can be either
+ (*) 'ignore' (default) - do nothing
+ (*) 'append' - only add incoming tags, that do not match an existing tag
+ (*) 'sync' - tries to do the plain wholesale thing,
+ i.e. to leave the db in sync with incoming tags
+ """
+ if options is None:
+ options = {}
+
+ # lookup 'pltags' in options to find out which mode is requested here
+ pltags = options.get('pltags', 'ignore')
+ # make sure the default is 'ignore'
+ if pltags not in ('ignore', 'append', 'sync'):
+ pltags = 'ignore'
+
+ if pltags == 'ignore':
+ logger.info(
+ 'verify_slice_tags in ignore mode - leaving slice tags as-is')
+ return
+
+ # incoming data (attributes) have a (name, value) pair
+ # while PLC data (tags) have a (tagname, value) pair
+ # we must be careful not to mix these up
+
+ # get list of tags users are able to manage - based on category