1 from sfa.util.xrn import get_authority, urn_to_hrn
2 from sfa.util.sfalogging import logger
9 rspec_to_slice_tag = {'max_rate':'net_max_rate'}
11 #def __init__(self, api, ttl = .5, origin_hrn=None):
13 ##filepath = path + os.sep + filename
14 #self.policy = Policy(self.api)
15 #self.origin_hrn = origin_hrn
16 #self.registry = api.registries[api.hrn]
17 #self.credential = api.getCredential()
22 def __init__(self, driver):
26 #def get_slivers(self, xrn, node=None):
27 #hrn, hrn_type = urn_to_hrn(xrn)
29 #slice_name = hrn_to_pl_slicename(hrn)
30 ## XX Should we just call PLCAPI.GetSliceTicket(slice_name) instead
31 ## of doing all of this?
32 ##return self.api.driver.GetSliceTicket(self.auth, slice_name)
36 #sfa_slice = self.driver.GetSlices(slice_filter = slice_name, \
37 # slice_filter_type = 'slice_hrn')
40 ## Get user information
42 #alchemy_person = dbsession.query(RegRecord).filter_by(record_id = \
43 #sfa_slice['record_id_user']).first()
46 #sliver_attributes = []
48 #if sfa_slice['oar_job_id'] is not -1:
49 #nodes_all = self.driver.GetNodes({'hostname': \
50 #sfa_slice['node_ids']},
51 #['node_id', 'hostname','site','boot_state'])
52 #nodeall_byhostname = dict([(n['hostname'], n) for n in nodes_all])
53 #nodes = sfa_slice['node_ids']
56 ##for sliver_attribute in filter(lambda a: a['node_id'] == \
57 #node['node_id'], slice_tags):
58 #sliver_attribute['tagname'] = 'slab-tag'
59 #sliver_attribute['value'] = 'slab-value'
60 #sliver_attributes.append(sliver_attribute['tagname'])
61 #attributes.append({'tagname': sliver_attribute['tagname'],
62 #'value': sliver_attribute['value']})
64 ## set nodegroup slice attributes
65 #for slice_tag in filter(lambda a: a['nodegroup_id'] \
66 #in node['nodegroup_ids'], slice_tags):
67 ## Do not set any nodegroup slice attributes for
68 ## which there is at least one sliver attribute
70 #if slice_tag not in slice_tags:
71 #attributes.append({'tagname': slice_tag['tagname'],
72 #'value': slice_tag['value']})
74 #for slice_tag in filter(lambda a: a['node_id'] is None, \
76 ## Do not set any global slice attributes for
77 ## which there is at least one sliver attribute
79 #if slice_tag['tagname'] not in sliver_attributes:
80 #attributes.append({'tagname': slice_tag['tagname'],
81 #'value': slice_tag['value']})
83 ## XXX Sanity check; though technically this should
84 ## be a system invariant
85 ## checked with an assertion
86 #if sfa_slice['expires'] > MAXINT: sfa_slice['expires']= MAXINT
90 #'name': sfa_slice['name'],
91 #'slice_id': sfa_slice['slice_id'],
92 #'instantiation': sfa_slice['instantiation'],
93 #'expires': sfa_slice['expires'],
95 #'attributes': attributes
105 def get_peer(self, xrn):
106 hrn, hrn_type = urn_to_hrn(xrn)
107 #Does this slice belong to a local site or a peer senslab site?
110 # get this slice's authority (site)
111 slice_authority = get_authority(hrn)
112 site_authority = slice_authority
113 # get this site's authority (sfa root authority or sub authority)
114 #site_authority = get_authority(slice_authority).lower()
115 logger.debug("SLABSLICES \ get_peer slice_authority %s \
116 site_authority %s hrn %s" %(slice_authority, \
117 site_authority, hrn))
118 #This slice belongs to the current site
119 if site_authority == self.driver.root_auth :
121 # check if we are already peered with this site_authority, if so
122 #peers = self.driver.GetPeers({})
123 peers = self.driver.GetPeers(peer_filter = slice_authority)
124 for peer_record in peers:
126 if site_authority == peer_record.hrn:
128 logger.debug(" SLABSLICES \tget_peer peer %s " %(peer))
131 def get_sfa_peer(self, xrn):
132 hrn, hrn_type = urn_to_hrn(xrn)
134 # return the authority for this hrn or None if we are the authority
136 slice_authority = get_authority(hrn)
137 site_authority = get_authority(slice_authority)
139 if site_authority != self.driver.hrn:
140 sfa_peer = site_authority
145 def verify_slice_leases(self, sfa_slice, requested_jobs_dict, kept_leases, \
149 #First get the list of current leases from OAR
150 leases = self.driver.GetLeases({'name':sfa_slice['name']})
151 #leases = self.driver.GetLeases({'name':sfa_slice['name']}, ['lease_id'])
153 current_leases = [lease['lease_id'] for lease in leases]
154 #Deleted leases are the ones with lease id not declared in the Rspec
155 deleted_leases = list(set(current_leases).difference(kept_leases))
159 #peer = RegAuyhority object is unsubscriptable
160 #TODO :UnBindObjectFromPeer Quick and dirty auth='senslab2 SA 27/07/12
161 self.driver.UnBindObjectFromPeer('senslab2', 'slice', \
162 sfa_slice['record_id_slice'], peer.hrn)
164 self.driver.DeleteLeases(deleted_leases, \
167 #TODO : catch other exception?
169 logger.log_exc('Failed to add/remove slice leases')
172 for start_time in requested_jobs_dict:
173 job = requested_jobs_dict[start_time]
174 self.driver.AddLeases(job['hostname'], \
175 sfa_slice, int(job['start_time']), \
176 int(job['duration']))
180 def verify_slice_nodes(self, sfa_slice, requested_slivers, peer):
184 if sfa_slice['node_ids']:
185 nodes = self.driver.GetNodes(sfa_slice['node_ids'], ['hostname'])
186 current_slivers = [node['hostname'] for node in nodes]
188 # remove nodes not in rspec
189 deleted_nodes = list(set(current_slivers).\
190 difference(requested_slivers))
191 # add nodes from rspec
192 #added_nodes = list(set(requested_slivers).difference(current_slivers))
194 #Update the table with the nodes that populate the slice
195 logger.debug("SLABSLICES \tverify_slice_nodes slice %s\
196 \r\n \r\n deleted_nodes %s"\
197 %(sfa_slice,deleted_nodes))
200 self.driver.DeleteSliceFromNodes(sfa_slice['name'], \
206 def free_egre_key(self):
208 for tag in self.driver.GetSliceTags({'tagname': 'egre_key'}):
209 used.add(int(tag['value']))
211 for i in range(1, 256):
216 raise KeyError("No more EGRE keys available")
225 def handle_peer(self, site, sfa_slice, persons, peer):
230 self.driver.BindObjectToPeer('site', site['site_id'], \
231 peer['shortname'], sfa_slice['site_id'])
232 except Exception, error:
233 self.driver.DeleteSite(site['site_id'])
239 self.driver.BindObjectToPeer('slice', slice['slice_id'], \
240 peer['shortname'], sfa_slice['slice_id'])
241 except Exception, error:
242 self.driver.DeleteSlice(sfa_slice['slice_id'])
246 for person in persons:
248 self.driver.BindObjectToPeer('person', \
249 person['person_id'], peer['shortname'], \
250 person['peer_person_id'])
252 for (key, remote_key_id) in zip(person['keys'], \
255 self.driver.BindObjectToPeer( 'key', \
256 key['key_id'], peer['shortname'], \
259 self.driver.DeleteKey(key['key_id'])
260 logger.log_exc("failed to bind key: %s \
261 to peer: %s " % (key['key_id'], \
263 except Exception, error:
264 self.driver.DeletePerson(person['person_id'])
269 #def verify_site(self, slice_xrn, slice_record={}, peer=None, \
270 #sfa_peer=None, options={}):
271 #(slice_hrn, type) = urn_to_hrn(slice_xrn)
272 #site_hrn = get_authority(slice_hrn)
273 ## login base can't be longer than 20 characters
274 ##slicename = hrn_to_pl_slicename(slice_hrn)
275 #authority_name = slice_hrn.split('.')[0]
276 #login_base = authority_name[:20]
277 #logger.debug(" SLABSLICES.PY \tverify_site authority_name %s \
278 #login_base %s slice_hrn %s" \
279 #%(authority_name,login_base,slice_hrn)
281 #sites = self.driver.GetSites(login_base)
283 ## create new site record
284 #site = {'name': 'geni.%s' % authority_name,
285 #'abbreviated_name': authority_name,
286 #'login_base': login_base,
288 #'max_slivers': 1000,
290 #'peer_site_id': None}
292 #site['peer_site_id'] = slice_record.get('site_id', None)
293 #site['site_id'] = self.driver.AddSite(site)
294 ## exempt federated sites from monitor policies
295 #self.driver.AddSiteTag(site['site_id'], 'exempt_site_until', \
298 ### is this still necessary?
299 ### add record to the local registry
300 ##if sfa_peer and slice_record:
301 ##peer_dict = {'type': 'authority', 'hrn': site_hrn, \
302 ##'peer_authority': sfa_peer, 'pointer': \
304 ##self.registry.register_peer_object(self.credential, peer_dict)
308 ## unbind from peer so we can modify if necessary.
309 ## Will bind back later
310 #self.driver.UnBindObjectFromPeer('site', site['site_id'], \
315 def verify_slice(self, slice_hrn, slice_record, peer, sfa_peer):
317 #login_base = slice_hrn.split(".")[0]
318 slicename = slice_hrn
319 slices_list = self.driver.GetSlices(slice_filter = slicename, \
320 slice_filter_type = 'slice_hrn')
322 for sl in slices_list:
324 logger.debug("SLABSLICE \tverify_slice slicename %s sl %s \
325 slice_record %s"%(slicename, sl, slice_record))
327 sfa_slice.update(slice_record)
328 #del slice['last_updated']
329 #del slice['date_created']
331 #slice['peer_slice_id'] = slice_record.get('slice_id', None)
332 ## unbind from peer so we can modify if necessary.
333 ## Will bind back later
334 #self.driver.UnBindObjectFromPeer('slice', slice['slice_id'], \
336 #Update existing record (e.g. expires field)
337 #it with the latest info.
338 ##if slice_record and slice['expires'] != slice_record['expires']:
339 ##self.driver.UpdateSlice( slice['slice_id'], {'expires' : \
340 #slice_record['expires']})
342 logger.debug(" SLABSLICES \tverify_slice Oups \
343 slice_record %s peer %s sfa_peer %s "\
344 %(slice_record, peer,sfa_peer))
345 sfa_slice = {'slice_hrn': slicename,
346 #'url': slice_record.get('url', slice_hrn),
347 #'description': slice_record.get('description', slice_hrn)
349 'record_id_user' : slice_record['person_ids'][0],
350 'record_id_slice': slice_record['record_id'],
351 'peer_authority':str(peer.hrn)
355 self.driver.AddSlice(sfa_slice)
356 #slice['slice_id'] = self.driver.AddSlice(slice)
357 logger.debug("SLABSLICES \tverify_slice ADDSLICE OK")
358 #slice['node_ids']=[]
359 #slice['person_ids'] = []
361 #slice['peer_slice_id'] = slice_record.get('slice_id', None)
362 # mark this slice as an sfa peer record
364 #peer_dict = {'type': 'slice', 'hrn': slice_hrn,
365 #'peer_authority': sfa_peer, 'pointer': \
367 #self.registry.register_peer_object(self.credential, peer_dict)
374 def verify_persons(self, slice_hrn, slice_record, users, peer, sfa_peer, \
377 users is a record list. Records can either be local records
378 or users records from known and trusted federated sites.
379 If the user is from another site that senslab doesn't trust yet,
380 then Resolve will raise an error before getting to create_sliver.
382 #TODO SA 21/08/12 verify_persons Needs review
387 #users_dict : dict whose keys can either be the user's hrn or its id.
388 #Values contains only id and hrn
391 #First create dicts by hrn and id for each user in the user record list:
394 if 'urn' in user and (not 'hrn' in user ) :
395 user['hrn'], user['type'] = urn_to_hrn(user['urn'])
397 if 'person_id' in user and 'hrn' in user:
398 users_by_id[user['person_id']] = user
399 users_dict[user['person_id']] = {'person_id':\
400 user['person_id'], 'hrn':user['hrn']}
402 users_by_hrn[user['hrn']] = user
403 users_dict[user['hrn']] = {'person_id':user['person_id'], \
407 logger.debug( "SLABSLICE.PY \t verify_person \
408 users_dict %s \r\n user_by_hrn %s \r\n \
410 %(users_dict,users_by_hrn, users_by_id))
412 existing_user_ids = []
413 existing_user_hrns = []
415 # Check if user is in Senslab LDAP using its hrn.
416 # Assuming Senslab is centralised : one LDAP for all sites,
417 # user_id unknown from LDAP
418 # LDAP does not provide users id, therefore we rely on hrns containing
419 # the login of the user.
420 # If the hrn is not a senslab hrn, the user may not be in LDAP.
422 #Construct the list of filters (list of dicts) for GetPersons
424 for hrn in users_by_hrn:
425 filter_user.append (users_by_hrn[hrn])
426 logger.debug(" SLABSLICE.PY \tverify_person filter_user %s " \
428 #Check user's in LDAP with GetPersons
429 #Needed because what if the user has been deleted in LDAP but
431 existing_users = self.driver.GetPersons(filter_user)
433 #User's in senslab LDAP
435 for user in existing_users :
436 existing_user_hrns.append(users_dict[user['hrn']]['hrn'])
438 append(users_dict[user['hrn']]['person_id'])
440 # User from another known trusted federated site. Check
441 # if a senslab account matching the email has already been created.
444 if isinstance(users, list):
446 req += users[0]['email']
448 req += users['email']
450 ldap_reslt = self.driver.ldap.LdapSearch(req)
452 logger.debug(" SLABSLICE.PY \tverify_person users \
453 USER already in Senslab \t ldap_reslt %s "%( ldap_reslt))
454 existing_users.append(ldap_reslt[1])
457 #User not existing in LDAP
458 #TODO SA 21/08/12 raise something to add user or add it auto ?
459 logger.debug(" SLABSLICE.PY \tverify_person users \
460 not in ldap ...NEW ACCOUNT NEEDED %s \r\n \t ldap_reslt %s " \
461 %(users, ldap_reslt))
463 requested_user_ids = users_by_id.keys()
464 requested_user_hrns = users_by_hrn.keys()
465 logger.debug("SLABSLICE.PY \tverify_person requested_user_ids %s \
466 user_by_hrn %s " %(requested_user_ids, users_by_hrn))
469 #Check that the user of the slice in the slice record
470 #matches the existing users
472 if slice_record['record_id_user'] in requested_user_ids and \
473 slice_record['PI'][0] in requested_user_hrns:
474 logger.debug(" SLABSLICE \tverify_person \
475 requested_user_ids %s = \
476 slice_record['record_id_user'] %s" \
477 %(requested_user_ids,slice_record['record_id_user']))
483 # users to be added, removed or updated
484 #One user in one senslab slice : there should be no need
485 #to remove/ add any user from/to a slice.
486 #However a user from SFA which is not registered in Senslab yet
487 #should be added to the LDAP.
489 added_user_hrns = set(requested_user_hrns).\
490 difference(set(existing_user_hrns))
492 #self.verify_keys(existing_slice_users, updated_users_list, \
497 for added_user_hrn in added_user_hrns:
498 added_user = users_dict[added_user_hrn]
499 #hrn, type = urn_to_hrn(added_user['urn'])
501 #'first_name': added_user.get('first_name', hrn),
502 #'last_name': added_user.get('last_name', hrn),
503 'first_name': added_user['first_name'],
504 'last_name': added_user['last_name'],
505 'person_id': added_user['person_id'],
506 'peer_person_id': None,
508 'key_ids': added_user.get('key_ids', []),
511 person['person_id'] = self.driver.AddPerson(person)
513 person['peer_person_id'] = added_user['person_id']
514 added_persons.append(person)
517 self.driver.UpdatePerson(person['person_id'], {'enabled': True})
520 #self.driver.AddPersonToSite(added_user_id, login_base)
522 #for key_string in added_user.get('keys', []):
523 #key = {'key':key_string, 'key_type':'ssh'}
524 #key['key_id'] = self.driver.AddPersonKey(person['person_id'], \
526 #person['keys'].append(key)
528 # add the registry record
530 #peer_dict = {'type': 'user', 'hrn': hrn, 'peer_authority': \
532 #'pointer': person['person_id']}
533 #self.registry.register_peer_object(self.credential, peer_dict)
534 #for added_slice_user_hrn in \
535 #added_slice_user_hrns.union(added_user_hrns):
536 #self.driver.AddPersonToSlice(added_slice_user_hrn, \
537 #slice_record['name'])
538 #for added_slice_user_id in \
539 #added_slice_user_ids.union(added_user_ids):
540 # add person to the slice
541 #self.driver.AddPersonToSlice(added_slice_user_id, \
542 #slice_record['name'])
543 # if this is a peer record then it
544 # should already be bound to a peer.
545 # no need to return worry about it getting bound later
550 def verify_keys(self, persons, users, peer, options={}):
553 for person in persons:
554 key_ids.extend(person['key_ids'])
555 keylist = self.driver.GetKeys(key_ids, ['key_id', 'key'])
558 keydict[key['key']] = key['key_id']
559 existing_keys = keydict.keys()
561 for person in persons:
562 persondict[person['email']] = person
568 user_keys = user.get('keys', [])
569 updated_persons.append(user)
570 for key_string in user_keys:
571 requested_keys.append(key_string)
572 if key_string not in existing_keys:
573 key = {'key': key_string, 'key_type': 'ssh'}
576 person = persondict[user['email']]
577 self.driver.UnBindObjectFromPeer('person', \
578 person['person_id'], peer['shortname'])
580 self.driver.AddPersonKey(user['email'], key)
582 key_index = user_keys.index(key['key'])
583 remote_key_id = user['key_ids'][key_index]
584 self.driver.BindObjectToPeer('key', \
585 key['key_id'], peer['shortname'], \
590 self.driver.BindObjectToPeer('person', \
591 person['person_id'], peer['shortname'], \
594 # remove old keys (only if we are not appending)
595 append = options.get('append', True)
597 removed_keys = set(existing_keys).difference(requested_keys)
598 for existing_key_id in keydict:
599 if keydict[existing_key_id] in removed_keys:
602 self.driver.UnBindObjectFromPeer('key', \
603 existing_key_id, peer['shortname'])
604 self.driver.DeleteKey(existing_key_id)
607 #def verify_slice_attributes(self, slice, requested_slice_attributes, \
608 #append=False, admin=False):
609 ## get list of attributes users ar able to manage
610 #filter = {'category': '*slice*'}
612 #filter['|roles'] = ['user']
613 #slice_attributes = self.driver.GetTagTypes(filter)
614 #valid_slice_attribute_names = [attribute['tagname'] \
615 #for attribute in slice_attributes]
617 ## get sliver attributes
618 #added_slice_attributes = []
619 #removed_slice_attributes = []
620 #ignored_slice_attribute_names = []
621 #existing_slice_attributes = self.driver.GetSliceTags({'slice_id': \
624 ## get attributes that should be removed
625 #for slice_tag in existing_slice_attributes:
626 #if slice_tag['tagname'] in ignored_slice_attribute_names:
627 ## If a slice already has a admin only role
628 ## it was probably given to them by an
629 ## admin, so we should ignore it.
630 #ignored_slice_attribute_names.append(slice_tag['tagname'])
632 ## If an existing slice attribute was not
633 ## found in the request it should
635 #attribute_found=False
636 #for requested_attribute in requested_slice_attributes:
637 #if requested_attribute['name'] == slice_tag['tagname'] \
638 #and requested_attribute['value'] == slice_tag['value']:
639 #attribute_found=True
642 #if not attribute_found and not append:
643 #removed_slice_attributes.append(slice_tag)
645 ## get attributes that should be added:
646 #for requested_attribute in requested_slice_attributes:
647 ## if the requested attribute wasn't found we should add it
648 #if requested_attribute['name'] in valid_slice_attribute_names:
649 #attribute_found = False
650 #for existing_attribute in existing_slice_attributes:
651 #if requested_attribute['name'] == \
652 #existing_attribute['tagname'] and \
653 #requested_attribute['value'] == \
654 #existing_attribute['value']:
655 #attribute_found=True
657 #if not attribute_found:
658 #added_slice_attributes.append(requested_attribute)
661 ## remove stale attributes
662 #for attribute in removed_slice_attributes:
664 #self.driver.DeleteSliceTag(attribute['slice_tag_id'])
665 #except Exception, error:
666 #self.logger.warn('Failed to remove sliver attribute. name: \
667 #%s, value: %s, node_id: %s\nCause:%s'\
668 #% (name, value, node_id, str(error)))
670 ## add requested_attributes
671 #for attribute in added_slice_attributes:
673 #self.driver.AddSliceTag(slice['name'], attribute['name'], \
674 #attribute['value'], attribute.get('node_id', None))
675 #except Exception, error:
676 #self.logger.warn('Failed to add sliver attribute. name: %s, \
677 #value: %s, node_id: %s\nCause:%s'\
678 #% (name, value, node_id, str(error)))