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