Merge Master in geni-v3 conflict resolution
[sfa.git] / sfa / senslab / slabslices.py
1 from sfa.util.xrn import get_authority, urn_to_hrn
2 from sfa.util.sfalogging import logger
3
4
5 MAXINT =  2L**31-1
6
7 class SlabSlices:
8
9     rspec_to_slice_tag = {'max_rate':'net_max_rate'}
10     
11     
12     def __init__(self, driver):
13         self.driver = driver
14         
15     
16     def get_peer(self, xrn):
17         hrn, hrn_type = urn_to_hrn(xrn)
18         #Does this slice belong to a local site or a peer senslab site?
19         peer = None
20         
21         # get this slice's authority (site)
22         slice_authority = get_authority(hrn)
23         #Senslab stuff
24         #This slice belongs to the current site
25         if slice_authority ==  self.driver.slab_api.root_auth:
26             site_authority = slice_authority
27             return None
28        
29         site_authority = get_authority(slice_authority).lower()
30         # get this site's authority (sfa root authority or sub authority)
31
32         logger.debug("SLABSLICES \ get_peer slice_authority  %s \
33                     site_authority %s hrn %s" %(slice_authority, \
34                                         site_authority, hrn))
35         
36             
37         # check if we are already peered with this site_authority, if so
38         #peers = self.driver.slab_api.GetPeers({})  
39         peers = self.driver.slab_api.GetPeers(peer_filter = site_authority)
40         for peer_record in peers:
41           
42             if site_authority == peer_record.hrn:
43                 peer = peer_record
44         logger.debug(" SLABSLICES \tget_peer peer  %s " %(peer))
45         return peer
46
47     def get_sfa_peer(self, xrn):
48         hrn, hrn_type = urn_to_hrn(xrn)
49
50         # return the authority for this hrn or None if we are the authority
51         sfa_peer = None
52         slice_authority = get_authority(hrn)
53         site_authority = get_authority(slice_authority)
54
55         if site_authority != self.driver.hrn:
56             sfa_peer = site_authority
57
58         return sfa_peer
59
60         
61     def verify_slice_leases(self, sfa_slice, requested_jobs_dict, peer):
62
63         logger.debug("SLABSLICES verify_slice_leases sfa_slice %s \
64                         "%( sfa_slice))
65         #First get the list of current leases from OAR          
66         leases = self.driver.slab_api.GetLeases({'name':sfa_slice['hrn']})
67         logger.debug("SLABSLICES verify_slice_leases requested_jobs_dict %s \
68                         leases %s "%(requested_jobs_dict, leases ))
69         
70         current_nodes_reserved_by_start_time = {}
71         requested_nodes_by_start_time = {}
72         leases_by_start_time = {}
73         reschedule_jobs_dict = {}
74
75         
76         #Create reduced dictionary with key start_time and value 
77         # the list of nodes
78         #-for the leases already registered by OAR first
79         # then for the new leases requested by the user
80         
81         #Leases already scheduled/running in OAR
82         for lease in leases :
83             current_nodes_reserved_by_start_time[lease['t_from']] = \
84                     lease['reserved_nodes']
85             leases_by_start_time[lease['t_from']] = lease
86             
87         
88         #Requested jobs     
89         for start_time in requested_jobs_dict:
90             requested_nodes_by_start_time[int(start_time)]  = \
91                     requested_jobs_dict[start_time]['hostname']            
92         #Check if there is any difference between the leases already
93         #registered in OAR and the requested jobs.   
94         #Difference could be:
95         #-Lease deleted in the requested jobs
96         #-Added/removed nodes
97         #-Newly added lease 
98
99         logger.debug("SLABSLICES verify_slice_leases \
100                         requested_nodes_by_start_time %s \
101                         "%(requested_nodes_by_start_time ))
102         #Find all deleted leases
103         start_time_list = \
104             list(set(leases_by_start_time.keys()).\
105             difference(requested_nodes_by_start_time.keys()))
106         deleted_leases = [leases_by_start_time[start_time]['lease_id'] \
107                             for start_time in start_time_list]
108
109
110             
111         #Find added or removed nodes in exisiting leases
112         for start_time in requested_nodes_by_start_time: 
113             logger.debug("SLABSLICES verify_slice_leases  start_time %s \
114                          "%( start_time))
115             if start_time in current_nodes_reserved_by_start_time:
116                 
117                 if requested_nodes_by_start_time[start_time] == \
118                     current_nodes_reserved_by_start_time[start_time]:
119                     continue
120                 
121                 else:
122                     update_node_set = \
123                             set(requested_nodes_by_start_time[start_time])
124                     added_nodes = \
125                         update_node_set.difference(\
126                         current_nodes_reserved_by_start_time[start_time])
127                     shared_nodes = \
128                         update_node_set.intersection(\
129                         current_nodes_reserved_by_start_time[start_time])
130                     old_nodes_set = \
131                         set(\
132                         current_nodes_reserved_by_start_time[start_time])
133                     removed_nodes = \
134                         old_nodes_set.difference(\
135                         requested_nodes_by_start_time[start_time])
136                     logger.debug("SLABSLICES verify_slice_leases \
137                         shared_nodes %s  added_nodes %s removed_nodes %s"\
138                         %(shared_nodes, added_nodes,removed_nodes ))
139                     #If the lease is modified, delete it before 
140                     #creating it again.
141                     #Add the deleted lease job id in the list
142                     #WARNING :rescheduling does not work if there is already  
143                     # 2 running/scheduled jobs because deleting a job 
144                     #takes time SA 18/10/2012
145                     if added_nodes or removed_nodes:
146                         deleted_leases.append(\
147                             leases_by_start_time[start_time]['lease_id'])
148                         #Reschedule the job 
149                         if added_nodes or shared_nodes:
150                             reschedule_jobs_dict[str(start_time)] = \
151                                         requested_jobs_dict[str(start_time)]
152
153             else: 
154                     #New lease
155                     
156                 job = requested_jobs_dict[str(start_time)]
157                 logger.debug("SLABSLICES \
158                 NEWLEASE slice %s  job %s"\
159                 %(sfa_slice, job)) 
160                 self.driver.slab_api.AddLeases(job['hostname'], \
161                         sfa_slice, int(job['start_time']), \
162                         int(job['duration']))
163
164         #Deleted leases are the ones with lease id not declared in the Rspec
165         if deleted_leases:
166             self.driver.slab_api.DeleteLeases(deleted_leases, sfa_slice['hrn'])
167             logger.debug("SLABSLICES \
168                     verify_slice_leases slice %s deleted_leases %s"\
169                     %(sfa_slice, deleted_leases))
170                     
171                     
172         if reschedule_jobs_dict : 
173             for start_time in  reschedule_jobs_dict:
174                 job = reschedule_jobs_dict[start_time]
175                 self.driver.slab_api.AddLeases(job['hostname'], \
176                     sfa_slice, int(job['start_time']), \
177                     int(job['duration']))
178         return leases
179
180     def verify_slice_nodes(self, sfa_slice, requested_slivers, peer):
181         current_slivers = []
182         deleted_nodes = []
183
184         if 'node_ids' in sfa_slice:
185             nodes = self.driver.slab_api.GetNodes(sfa_slice['list_node_ids'], \
186                 ['hostname'])
187             current_slivers = [node['hostname'] for node in nodes]
188     
189             # remove nodes not in rspec
190             deleted_nodes = list(set(current_slivers).\
191                                                 difference(requested_slivers))
192             # add nodes from rspec
193             #added_nodes = list(set(requested_slivers).\
194                                         #difference(current_slivers))
195
196
197             logger.debug("SLABSLICES \tverify_slice_nodes slice %s\
198                                          \r\n \r\n deleted_nodes %s"\
199                                         %(sfa_slice, deleted_nodes))
200
201             if deleted_nodes:
202                 #Delete the entire experience
203                 self.driver.slab_api.DeleteSliceFromNodes(sfa_slice)
204                 #self.driver.DeleteSliceFromNodes(sfa_slice['slice_hrn'], \
205                                                                 #deleted_nodes)
206             return nodes
207
208             
209
210     def free_egre_key(self):
211         used = set()
212         for tag in self.driver.slab_api.GetSliceTags({'tagname': 'egre_key'}):
213             used.add(int(tag['value']))
214
215         for i in range(1, 256):
216             if i not in used:
217                 key = i
218                 break
219         else:
220             raise KeyError("No more EGRE keys available")
221
222         return str(key)
223
224   
225        
226                         
227         
228
229     def handle_peer(self, site, sfa_slice, persons, peer):
230         if peer:
231             # bind site
232             try:
233                 if site:
234                     self.driver.slab_api.BindObjectToPeer('site', site['site_id'], \
235                                         peer['shortname'], sfa_slice['site_id'])
236             except Exception, error:
237                 self.driver.slab_api.DeleteSite(site['site_id'])
238                 raise error
239             
240             # bind slice
241             try:
242                 if sfa_slice:
243                     self.driver.slab_api.BindObjectToPeer('slice', slice['slice_id'], \
244                                     peer['shortname'], sfa_slice['slice_id'])
245             except Exception, error:
246                 self.driver.slab_api.DeleteSlice(sfa_slice['slice_id'])
247                 raise error 
248
249             # bind persons
250             for person in persons:
251                 try:
252                     self.driver.slab_api.BindObjectToPeer('person', \
253                                     person['person_id'], peer['shortname'], \
254                                     person['peer_person_id'])
255
256                     for (key, remote_key_id) in zip(person['keys'], \
257                                                         person['key_ids']):
258                         try:
259                             self.driver.slab_api.BindObjectToPeer( 'key', \
260                                             key['key_id'], peer['shortname'], \
261                                             remote_key_id)
262                         except:
263                             self.driver.slab_api.DeleteKey(key['key_id'])
264                             logger.log_exc("failed to bind key: %s \
265                                             to peer: %s " % (key['key_id'], \
266                                             peer['shortname']))
267                 except Exception, error:
268                     self.driver.slab_api.DeletePerson(person['person_id'])
269                     raise error       
270
271         return sfa_slice
272
273     #def verify_site(self, slice_xrn, slice_record={}, peer=None, \
274                                         #sfa_peer=None, options={}):
275         #(slice_hrn, type) = urn_to_hrn(slice_xrn)
276         #site_hrn = get_authority(slice_hrn)
277         ## login base can't be longer than 20 characters
278         ##slicename = hrn_to_pl_slicename(slice_hrn)
279         #authority_name = slice_hrn.split('.')[0]
280         #login_base = authority_name[:20]
281         #logger.debug(" SLABSLICES.PY \tverify_site authority_name %s  \
282                                         #login_base %s slice_hrn %s" \
283                                         #%(authority_name,login_base,slice_hrn)
284         
285         #sites = self.driver.slab_api.GetSites(login_base)
286         #if not sites:
287             ## create new site record
288             #site = {'name': 'geni.%s' % authority_name,
289                     #'abbreviated_name': authority_name,
290                     #'login_base': login_base,
291                     #'max_slices': 100,
292                     #'max_slivers': 1000,
293                     #'enabled': True,
294                     #'peer_site_id': None}
295             #if peer:
296                 #site['peer_site_id'] = slice_record.get('site_id', None)
297             #site['site_id'] = self.driver.slab_api.AddSite(site)
298             ## exempt federated sites from monitor policies
299             #self.driver.slab_api.AddSiteTag(site['site_id'], 'exempt_site_until', \
300                                                                 #"20200101")
301             
302             ### is this still necessary?
303             ### add record to the local registry 
304             ##if sfa_peer and slice_record:
305                 ##peer_dict = {'type': 'authority', 'hrn': site_hrn, \
306                              ##'peer_authority': sfa_peer, 'pointer': \
307                                                         #site['site_id']}
308                 ##self.registry.register_peer_object(self.credential, peer_dict)
309         #else:
310             #site =  sites[0]
311             #if peer:
312                 ## unbind from peer so we can modify if necessary.
313                 ## Will bind back later
314                 #self.driver.slab_api.UnBindObjectFromPeer('site', site['site_id'], \
315                                                             #peer['shortname']) 
316         
317         #return site        
318
319     def verify_slice(self, slice_hrn, slice_record, peer, sfa_peer):
320
321         #login_base = slice_hrn.split(".")[0]
322         slicename = slice_hrn
323         slices_list = self.driver.slab_api.GetSlices(slice_filter = slicename, \
324                                             slice_filter_type = 'slice_hrn') 
325         sfa_slice = None                                 
326         if slices_list:
327             for sl in slices_list:
328             
329                 logger.debug("SLABSLICE \tverify_slice slicename %s slices_list %s sl %s \
330                                     slice_record %s"%(slicename, slices_list,sl, \
331                                                             slice_record))
332                 sfa_slice = sl
333                 sfa_slice.update(slice_record)
334                 #del slice['last_updated']
335                 #del slice['date_created']
336                 #if peer:
337                     #slice['peer_slice_id'] = slice_record.get('slice_id', None)
338                     ## unbind from peer so we can modify if necessary. 
339                     ## Will bind back later
340                     #self.driver.slab_api.UnBindObjectFromPeer('slice', \
341                                                         #slice['slice_id'], \
342                                                             #peer['shortname'])
343                 #Update existing record (e.g. expires field) 
344                     #it with the latest info.
345                 ##if slice_record and slice['expires'] != slice_record['expires']:
346                     ##self.driver.slab_api.UpdateSlice( slice['slice_id'], {'expires' : \
347                                                         #slice_record['expires']})
348         else:
349             #Search for user in ldap based on email SA 14/11/12
350             ldap_user = self.driver.slab_api.ldap.LdapFindUser(slice_record['user'])
351             logger.debug(" SLABSLICES \tverify_slice Oups \
352                         slice_record %s peer %s sfa_peer %s ldap_user %s"\
353                         %(slice_record, peer,sfa_peer ,ldap_user ))
354             #User already registered in ldap, meaning user should be in SFA db
355             #and hrn = sfa_auth+ uid   
356             sfa_slice = {'hrn': slicename,
357                      #'url': slice_record.get('url', slice_hrn), 
358                      #'description': slice_record.get('description', slice_hrn)
359                      'node_list' : [],
360                      'authority' : slice_record['authority'],
361                      'gid':slice_record['gid'],
362                      #'record_id_user' : user.record_id,
363                      'slice_id' : slice_record['record_id'],
364                      'reg-researchers':slice_record['reg-researchers'],
365                      #'record_id_slice': slice_record['record_id'],
366                      'peer_authority':str(sfa_peer)
367                     
368                      }        
369             if ldap_user : 
370                 hrn = self.driver.slab_api.root_auth +'.'+ ldap_user['uid']
371                 
372                 user = self.driver.get_user_record(hrn)
373                 
374                 logger.debug(" SLABSLICES \tverify_slice hrn %s USER %s" %(hrn, user))
375                 #sfa_slice = {'slice_hrn': slicename,
376                      ##'url': slice_record.get('url', slice_hrn), 
377                      ##'description': slice_record.get('description', slice_hrn)
378                      #'node_list' : [],
379                      #'authority' : slice_record['authority'],
380                      #'gid':slice_record['gid'],
381                      ##'record_id_user' : user.record_id,
382                      #'slice_id' : slice_record['record_id'],
383                      #'reg-researchers':slice_record['reg-researchers'],
384                      ##'record_id_slice': slice_record['record_id'],
385                      #'peer_authority':str(peer.hrn)
386                     
387                      #}
388                      # add the slice  
389                 if sfa_slice :
390                     self.driver.slab_api.AddSlice(sfa_slice, user)  
391                      
392                 if peer:
393                     sfa_slice['slice_id'] = slice_record['record_id']
394                                    
395             #slice['slice_id'] = self.driver.slab_api.AddSlice(slice)
396             logger.debug("SLABSLICES \tverify_slice ADDSLICE OK") 
397             #slice['node_ids']=[]
398             #slice['person_ids'] = []
399             #if peer:
400                 #sfa_slice['peer_slice_id'] = slice_record.get('slice_id', None) 
401             # mark this slice as an sfa peer record
402             #if sfa_peer:
403                 #peer_dict = {'type': 'slice', 'hrn': slice_hrn, 
404                              #'peer_authority': sfa_peer, 'pointer': \
405                                                     #slice['slice_id']}
406                 #self.registry.register_peer_object(self.credential, peer_dict)
407             
408
409        
410         return sfa_slice
411
412
413     def verify_persons(self, slice_hrn, slice_record, users,  peer, sfa_peer, \
414                                                                 options={}):
415         """ 
416         users is a record list. Records can either be local records 
417         or users records from known and trusted federated sites. 
418         If the user is from another site that senslab doesn't trust yet,
419         then Resolve will raise an error before getting to create_sliver. 
420         """
421         #TODO SA 21/08/12 verify_persons Needs review 
422         
423         logger.debug("SLABSLICES \tverify_persons \tslice_hrn  %s  \t slice_record %s\r\n users %s \t peer %s "%( slice_hrn, slice_record, users,  peer)) 
424         users_by_id = {}  
425         #users_by_hrn = {} 
426         users_by_email = {}
427         #users_dict : dict whose keys can either be the user's hrn or its id.
428         #Values contains only id and hrn 
429         users_dict = {}
430         
431         #First create dicts by hrn and id for each user in the user record list:      
432         for info in users:
433             
434             if 'slice_record' in info :
435                 slice_rec = info['slice_record'] 
436                 user = slice_rec['user']
437
438             if 'email' in user:  
439                 users_by_email[user['email']] = user
440                 users_dict[user['email']] = user
441                 
442             #if 'hrn' in user:
443                 #users_by_hrn[user['hrn']] = user
444                 #users_dict[user['hrn']] = user
445         
446         logger.debug( "SLABSLICE.PY \t verify_person  \
447                         users_dict %s \r\n user_by_email %s \r\n \
448                         \tusers_by_id %s " \
449                         %(users_dict,users_by_email, users_by_id))
450         
451         existing_user_ids = []
452         #existing_user_hrns = []
453         existing_user_emails = []
454         existing_users = []
455         # Check if user is in Senslab LDAP using its hrn.
456         # Assuming Senslab is centralised :  one LDAP for all sites, 
457         # user_id unknown from LDAP
458         # LDAP does not provide users id, therefore we rely on hrns containing
459         # the login of the user.
460         # If the hrn is not a senslab hrn, the user may not be in LDAP.
461         #if users_by_hrn:
462         if users_by_email :
463             #Construct the list of filters (list of dicts) for GetPersons
464             filter_user = []
465             #for hrn in users_by_hrn:
466             for email in users_by_email :
467                 #filter_user.append (users_by_hrn[hrn])
468                 filter_user.append (users_by_email[email])
469             #Check user's in LDAP with GetPersons
470             #Needed because what if the user has been deleted in LDAP but 
471             #is still in SFA?
472             existing_users = self.driver.slab_api.GetPersons(filter_user) 
473             logger.debug(" \r\n SLABSLICE.PY \tverify_person  filter_user %s existing_users %s " \
474                                                     %(filter_user, existing_users))               
475             #User's in senslab LDAP               
476             if existing_users:
477                 for user in existing_users :
478                     users_dict[user['email']].update(user)
479                     existing_user_emails.append(users_dict[user['email']]['email'])
480                     
481                     #existing_user_hrns.append(users_dict[user['hrn']]['hrn'])
482                     #existing_user_ids.\
483                                     #append(users_dict[user['hrn']]['person_id'])
484          
485             # User from another known trusted federated site. Check 
486             # if a senslab account matching the email has already been created.
487             else: 
488                 req = 'mail='
489                 if isinstance(users, list):
490                     
491                     req += users[0]['email']  
492                 else:
493                     req += users['email']
494                     
495                 ldap_reslt = self.driver.slab_api.ldap.LdapSearch(req)
496                 if ldap_reslt:
497                     logger.debug(" SLABSLICE.PY \tverify_person users \
498                                 USER already in Senslab \t ldap_reslt %s \
499                                 "%( ldap_reslt)) 
500                     existing_users.append(ldap_reslt[1])
501                  
502                 else:
503                     #User not existing in LDAP
504                     #TODO SA 21/08/12 raise smthg to add user or add it auto ?
505                     #new_record = {}
506                     #new_record['pkey'] = users[0]['keys'][0]
507                     #new_record['mail'] = users[0]['email']
508                   
509                     logger.debug(" SLABSLICE.PY \tverify_person users \
510                                 not in ldap ...NEW ACCOUNT NEEDED %s \r\n \t \
511                                 ldap_reslt %s "  %(users, ldap_reslt))
512    
513         #requested_user_ids = users_by_id.keys() 
514         #requested_user_hrns = users_by_hrn.keys()
515         requested_user_emails = users_by_email.keys()
516         logger.debug("SLABSLICE.PY \tverify_person  \
517                        users_by_email  %s " %( users_by_email)) 
518         #logger.debug("SLABSLICE.PY \tverify_person  \
519                         #user_by_hrn %s " %( users_by_hrn)) 
520       
521    
522         #Check that the user of the slice in the slice record
523         #matches the existing users 
524         try:
525             if slice_record['PI'][0] in requested_user_hrns:
526             #if slice_record['record_id_user'] in requested_user_ids and \
527                                 #slice_record['PI'][0] in requested_user_hrns:
528                 logger.debug(" SLABSLICE  \tverify_person ['PI'] slice_record %s" \
529                         %(slice_record))
530            
531         except KeyError:
532             pass
533             
534       
535         # users to be added, removed or updated
536         #One user in one senslab slice : there should be no need
537         #to remove/ add any user from/to a slice.
538         #However a user from SFA which is not registered in Senslab yet
539         #should be added to the LDAP.
540         added_user_emails = set(requested_user_emails).\
541                                             difference(set(existing_user_emails))
542         #added_user_hrns = set(requested_user_hrns).\
543                                             #difference(set(existing_user_hrns))
544
545         #self.verify_keys(existing_slice_users, updated_users_list, \
546                                                             #peer, append)
547
548         added_persons = []
549         # add new users
550         
551         #requested_user_email is in existing_user_emails
552         if len(added_user_emails) == 0:
553            
554             slice_record['login'] = users_dict[requested_user_emails[0]]['uid']
555             logger.debug(" SLABSLICE  \tverify_person QUICK DIRTY %s" \
556                         %(slice_record))
557             
558         #for added_user_hrn in added_user_hrns:
559             #added_user = users_dict[added_user_hrn]
560             
561             
562         for added_user_email in added_user_emails:
563             #hrn, type = urn_to_hrn(added_user['urn'])  
564             added_user = users_dict[added_user_email]
565             logger.debug(" SLABSLICE \r\n \r\n  \t THE SECOND verify_person  added_user %s" %(added_user))
566             person = {}
567             person['peer_person_id'] =  None
568             k_list  = ['first_name','last_name','person_id']
569             for k in k_list:
570                 if k in added_user:
571                     person[k] = added_user[k]
572
573             person['pkey'] = added_user['keys'][0]
574             person['mail'] = added_user['email']
575             person['email'] = added_user['email']
576             person['key_ids'] =  added_user.get('key_ids', [])
577             #person['urn'] =   added_user['urn']
578               
579             #person['person_id'] = self.driver.slab_api.AddPerson(person)
580             person['uid'] = self.driver.slab_api.AddPerson(person)
581             
582             logger.debug(" SLABSLICE \r\n \r\n  \t THE SECOND verify_person ppeersonne  %s" %(person))
583             #Update slice_Record with the id now known to LDAP
584             slice_record['login'] = person['uid']
585             #slice_record['reg_researchers'] = [self.driver.slab_api.root_auth + '.' + person['uid']]
586             #slice_record['reg-researchers'] =  slice_record['reg_researchers']
587             
588             #if peer:
589                 #person['peer_person_id'] = added_user['person_id']
590             added_persons.append(person)
591            
592             # enable the account 
593             #self.driver.slab_api.UpdatePerson(slice_record['reg_researchers'][0], added_user_email)
594             
595             # add person to site
596             #self.driver.slab_api.AddPersonToSite(added_user_id, login_base)
597
598             #for key_string in added_user.get('keys', []):
599                 #key = {'key':key_string, 'key_type':'ssh'}
600                 #key['key_id'] = self.driver.slab_api.AddPersonKey(person['person_id'], \
601                                                 #                       key)
602                 #person['keys'].append(key)
603
604             # add the registry record
605             #if sfa_peer:
606                 #peer_dict = {'type': 'user', 'hrn': hrn, 'peer_authority': \
607                                                 #sfa_peer, \
608                                                 #'pointer': person['person_id']}
609                 #self.registry.register_peer_object(self.credential, peer_dict)
610         #for added_slice_user_hrn in \
611                                 #added_slice_user_hrns.union(added_user_hrns):
612             #self.driver.slab_api.AddPersonToSlice(added_slice_user_hrn, \
613                                                     #slice_record['name'])
614         #for added_slice_user_id in \
615                                     #added_slice_user_ids.union(added_user_ids):
616             # add person to the slice 
617             #self.driver.slab_api.AddPersonToSlice(added_slice_user_id, \
618                                                 #slice_record['name'])
619             # if this is a peer record then it 
620             # should already be bound to a peer.
621             # no need to return worry about it getting bound later 
622
623         return added_persons
624             
625     #Unused
626     def verify_keys(self, persons, users, peer, options={}):
627         # existing keys 
628         key_ids = []
629         for person in persons:
630             key_ids.extend(person['key_ids'])
631         keylist = self.driver.slab_api.GetKeys(key_ids, ['key_id', 'key'])
632         keydict = {}
633         for key in keylist:
634             keydict[key['key']] = key['key_id']     
635         existing_keys = keydict.keys()
636         persondict = {}
637         for person in persons:
638             persondict[person['email']] = person    
639     
640         # add new keys
641         requested_keys = []
642         updated_persons = []
643         for user in users:
644             user_keys = user.get('keys', [])
645             updated_persons.append(user)
646             for key_string in user_keys:
647                 requested_keys.append(key_string)
648                 if key_string not in existing_keys:
649                     key = {'key': key_string, 'key_type': 'ssh'}
650                     try:
651                         if peer:
652                             person = persondict[user['email']]
653                             self.driver.slab_api.UnBindObjectFromPeer('person', \
654                                         person['person_id'], peer['shortname'])
655                         key['key_id'] = \
656                                 self.driver.slab_api.AddPersonKey(user['email'], key)
657                         if peer:
658                             key_index = user_keys.index(key['key'])
659                             remote_key_id = user['key_ids'][key_index]
660                             self.driver.slab_api.BindObjectToPeer('key', \
661                                             key['key_id'], peer['shortname'], \
662                                             remote_key_id)
663                             
664                     finally:
665                         if peer:
666                             self.driver.slab_api.BindObjectToPeer('person', \
667                                     person['person_id'], peer['shortname'], \
668                                     user['person_id'])
669         
670         # remove old keys (only if we are not appending)
671         append = options.get('append', True)
672         if append == False: 
673             removed_keys = set(existing_keys).difference(requested_keys)
674             for existing_key_id in keydict:
675                 if keydict[existing_key_id] in removed_keys:
676
677                     if peer:
678                         self.driver.slab_api.UnBindObjectFromPeer('key', \
679                                         existing_key_id, peer['shortname'])
680                     self.driver.slab_api.DeleteKey(existing_key_id)
681  
682
683     #def verify_slice_attributes(self, slice, requested_slice_attributes, \
684                                             #append=False, admin=False):
685         ## get list of attributes users ar able to manage
686         #filter = {'category': '*slice*'}
687         #if not admin:
688             #filter['|roles'] = ['user']
689         #slice_attributes = self.driver.slab_api.GetTagTypes(filter)
690         #valid_slice_attribute_names = [attribute['tagname'] \
691                                             #for attribute in slice_attributes]
692
693         ## get sliver attributes
694         #added_slice_attributes = []
695         #removed_slice_attributes = []
696         #ignored_slice_attribute_names = []
697         #existing_slice_attributes = self.driver.slab_api.GetSliceTags({'slice_id': \
698                                                             #slice['slice_id']})
699
700         ## get attributes that should be removed
701         #for slice_tag in existing_slice_attributes:
702             #if slice_tag['tagname'] in ignored_slice_attribute_names:
703                 ## If a slice already has a admin only role 
704                 ## it was probably given to them by an
705                 ## admin, so we should ignore it.
706                 #ignored_slice_attribute_names.append(slice_tag['tagname'])
707             #else:
708                 ## If an existing slice attribute was not 
709                 ## found in the request it should
710                 ## be removed
711                 #attribute_found=False
712                 #for requested_attribute in requested_slice_attributes:
713                     #if requested_attribute['name'] == slice_tag['tagname'] \
714                         #and requested_attribute['value'] == slice_tag['value']:
715                         #attribute_found=True
716                         #break
717
718             #if not attribute_found and not append:
719                 #removed_slice_attributes.append(slice_tag)
720         
721         ## get attributes that should be added:
722         #for requested_attribute in requested_slice_attributes:
723             ## if the requested attribute wasn't found  we should add it
724             #if requested_attribute['name'] in valid_slice_attribute_names:
725                 #attribute_found = False
726                 #for existing_attribute in existing_slice_attributes:
727                     #if requested_attribute['name'] == \
728                         #existing_attribute['tagname'] and \
729                        #requested_attribute['value'] == \
730                        #existing_attribute['value']:
731                         #attribute_found=True
732                         #break
733                 #if not attribute_found:
734                     #added_slice_attributes.append(requested_attribute)
735
736
737         ## remove stale attributes
738         #for attribute in removed_slice_attributes:
739             #try:
740                 #self.driver.slab_api.DeleteSliceTag(attribute['slice_tag_id'])
741             #except Exception, error:
742                 #self.logger.warn('Failed to remove sliver attribute. name: \
743                                 #%s, value: %s, node_id: %s\nCause:%s'\
744                                 #% (name, value,  node_id, str(error)))
745
746         ## add requested_attributes
747         #for attribute in added_slice_attributes:
748             #try:
749                 #self.driver.slab_api.AddSliceTag(slice['name'], attribute['name'], \
750                             #attribute['value'], attribute.get('node_id', None))
751             #except Exception, error:
752                 #self.logger.warn('Failed to add sliver attribute. name: %s, \
753                                 #value: %s, node_id: %s\nCause:%s'\
754                                 #% (name, value,  node_id, str(error)))
755
756