Fixed bug in GetPeers.
[sfa.git] / sfa / senslab / slabslices.py
1 from types import StringTypes
2 from collections import defaultdict
3 import sys
4 from sfa.util.xrn import get_leaf, get_authority, urn_to_hrn
5 from sfa.util.plxrn import hrn_to_pl_slicename
6 from sfa.util.policy import Policy
7 from sfa.rspecs.rspec import RSpec
8 from sfa.plc.vlink import VLink
9 from sfa.util.xrn import Xrn
10 from sfa.util.sfalogging import logger
11
12 from sqlalchemy import Column, Integer, String, DateTime
13 from sqlalchemy import Table, Column, MetaData, join, ForeignKey
14 from sfa.storage.model import RegRecord
15 from sfa.storage.alchemy import dbsession,engine
16
17 MAXINT =  2L**31-1
18
19 class SlabSlices:
20
21     rspec_to_slice_tag = {'max_rate':'net_max_rate'}
22
23     #def __init__(self, api, ttl = .5, origin_hrn=None):
24         #self.api = api
25         ##filepath = path + os.sep + filename
26         #self.policy = Policy(self.api)    
27         #self.origin_hrn = origin_hrn
28         #self.registry = api.registries[api.hrn]
29         #self.credential = api.getCredential()
30         #self.nodes = []
31         #self.persons = []
32
33
34     def __init__(self, driver):
35         self.driver = driver
36         
37         
38     def get_slivers(self, xrn, node=None):
39         hrn, type = urn_to_hrn(xrn)
40          
41         slice_name = hrn_to_pl_slicename(hrn)
42         # XX Should we just call PLCAPI.GetSliceTicket(slice_name) instead
43         # of doing all of this?
44         #return self.api.driver.GetSliceTicket(self.auth, slice_name) 
45         
46
47        
48         slice = self.driver.GetSlices(slice_filter = slice_name, filter_type = 'slice_hrn')
49  
50
51         # Get user information
52         alchemy_person = dbsession.query(RegRecord).filter_by(record_id = slice['record_id_user']).first()
53
54         slivers = []
55         sliver_attributes = []
56             
57         if slice['oar_job_id'] is not -1:
58             nodes_all = self.GetNodes({'hostname':slice['node_ids']},
59                             ['node_id', 'hostname','site','boot_state'])
60             nodeall_byhostname = dict([(n['hostname'], n) for n in nodes_all])
61             nodes = slice['node_ids']
62             
63             for node in nodes:
64                 #for sliver_attribute in filter(lambda a: a['node_id'] == node['node_id'], slice_tags):
65                 sliver_attribute['tagname'] = 'slab-tag'
66                 sliver_attribute['value'] = 'slab-value'
67                 sliver_attributes.append(sliver_attribute['tagname'])
68                 attributes.append({'tagname': sliver_attribute['tagname'],
69                                     'value': sliver_attribute['value']})
70
71             # set nodegroup slice attributes
72             for slice_tag in filter(lambda a: a['nodegroup_id'] in node['nodegroup_ids'], slice_tags):
73                 # Do not set any nodegroup slice attributes for
74                 # which there is at least one sliver attribute
75                 # already set.
76                 if slice_tag not in slice_tags:
77                     attributes.append({'tagname': slice_tag['tagname'],
78                         'value': slice_tag['value']})
79
80             for slice_tag in filter(lambda a: a['node_id'] is None, slice_tags):
81                 # Do not set any global slice attributes for
82                 # which there is at least one sliver attribute
83                 # already set.
84                 if slice_tag['tagname'] not in sliver_attributes:
85                     attributes.append({'tagname': slice_tag['tagname'],
86                                    'value': slice_tag['value']})
87
88             # XXX Sanity check; though technically this should be a system invariant
89             # checked with an assertion
90             if slice['expires'] > MAXINT:  slice['expires']= MAXINT
91             
92             slivers.append({
93                 'hrn': hrn,
94                 'name': slice['name'],
95                 'slice_id': slice['slice_id'],
96                 'instantiation': slice['instantiation'],
97                 'expires': slice['expires'],
98                 'keys': keys,
99                 'attributes': attributes
100             })
101
102         return slivers
103         
104         
105         
106  #def get_slivers(self, xrn, node=None):
107         #hrn, type = urn_to_hrn(xrn)
108          
109         #slice_name = hrn_to_pl_slicename(hrn)
110         ## XX Should we just call PLCAPI.GetSliceTicket(slice_name) instead
111         ## of doing all of this?
112         ##return self.api.driver.GetSliceTicket(self.auth, slice_name) 
113         
114         ## from PLCAPI.GetSlivers.get_slivers()
115         #slice_fields = ['slice_id', 'name', 'instantiation', 'expires', 'person_ids', 'slice_tag_ids']
116         #slices = self.api.driver.GetSlices(slice_name, slice_fields)
117         ## Build up list of users and slice attributes
118         #person_ids = set()
119         #all_slice_tag_ids = set()
120         #for slice in slices:
121             #person_ids.update(slice['person_ids'])
122             #all_slice_tag_ids.update(slice['slice_tag_ids'])
123         #person_ids = list(person_ids)
124         #all_slice_tag_ids = list(all_slice_tag_ids)
125         ## Get user information
126         #all_persons_list = self.api.driver.GetPersons({'person_id':person_ids,'enabled':True}, ['person_id', 'enabled', 'key_ids'])
127         #all_persons = {}
128         #for person in all_persons_list:
129             #all_persons[person['person_id']] = person        
130
131         ## Build up list of keys
132         #key_ids = set()
133         #for person in all_persons.values():
134             #key_ids.update(person['key_ids'])
135         #key_ids = list(key_ids)
136         ## Get user account keys
137         #all_keys_list = self.api.driver.GetKeys(key_ids, ['key_id', 'key', 'key_type'])
138         #all_keys = {}
139         #for key in all_keys_list:
140             #all_keys[key['key_id']] = key
141         ## Get slice attributes
142         #all_slice_tags_list = self.api.driver.GetSliceTags(all_slice_tag_ids)
143         #all_slice_tags = {}
144         #for slice_tag in all_slice_tags_list:
145             #all_slice_tags[slice_tag['slice_tag_id']] = slice_tag
146            
147         #slivers = []
148         #for slice in slices:
149             #keys = []
150             #for person_id in slice['person_ids']:
151                 #if person_id in all_persons:
152                     #person = all_persons[person_id]
153                     #if not person['enabled']:
154                         #continue
155                     #for key_id in person['key_ids']:
156                         #if key_id in all_keys:
157                             #key = all_keys[key_id]
158                             #keys += [{'key_type': key['key_type'],
159                                     #'key': key['key']}]
160             #attributes = []
161             ## All (per-node and global) attributes for this slice
162             #slice_tags = []
163             #for slice_tag_id in slice['slice_tag_ids']:
164                 #if slice_tag_id in all_slice_tags:
165                     #slice_tags.append(all_slice_tags[slice_tag_id]) 
166             ## Per-node sliver attributes take precedence over global
167             ## slice attributes, so set them first.
168             ## Then comes nodegroup slice attributes
169             ## Followed by global slice attributes
170             #sliver_attributes = []
171
172             #if node is not None:
173                 #for sliver_attribute in filter(lambda a: a['node_id'] == node['node_id'], slice_tags):
174                     #sliver_attributes.append(sliver_attribute['tagname'])
175                     #attributes.append({'tagname': sliver_attribute['tagname'],
176                                     #'value': sliver_attribute['value']})
177
178             ## set nodegroup slice attributes
179             #for slice_tag in filter(lambda a: a['nodegroup_id'] in node['nodegroup_ids'], slice_tags):
180                 ## Do not set any nodegroup slice attributes for
181                 ## which there is at least one sliver attribute
182                 ## already set.
183                 #if slice_tag not in slice_tags:
184                     #attributes.append({'tagname': slice_tag['tagname'],
185                         #'value': slice_tag['value']})
186
187             #for slice_tag in filter(lambda a: a['node_id'] is None, slice_tags):
188                 ## Do not set any global slice attributes for
189                 ## which there is at least one sliver attribute
190                 ## already set.
191                 #if slice_tag['tagname'] not in sliver_attributes:
192                     #attributes.append({'tagname': slice_tag['tagname'],
193                                    #'value': slice_tag['value']})
194
195             ## XXX Sanity check; though technically this should be a system invariant
196             ## checked with an assertion
197             #if slice['expires'] > MAXINT:  slice['expires']= MAXINT
198             
199             #slivers.append({
200                 #'hrn': hrn,
201                 #'name': slice['name'],
202                 #'slice_id': slice['slice_id'],
203                 #'instantiation': slice['instantiation'],
204                 #'expires': slice['expires'],
205                 #'keys': keys,
206                 #'attributes': attributes
207             #})
208
209         #return slivers
210     def get_peer(self, xrn):
211         hrn, type = urn_to_hrn(xrn)
212         #Does this slice belong to a local site or a peer senslab site?
213         peer = None
214         
215         # get this slice's authority (site)
216         slice_authority = get_authority(hrn)
217         
218         # get this site's authority (sfa root authority or sub authority)
219         site_authority = get_authority(slice_authority).lower()
220         print>>sys.stderr, " \r\n \r\n \t slices.py get_peer slice_authority  %s site_authority %s " %(slice_authority, site_authority)
221         # check if we are already peered with this site_authority, if so
222         peers = self.driver.GetPeers({})
223         #print>>sys.stderr, " \r\n \r\n \t slices.py get_peer peers %s " %(peers)
224         for peer_record in peers:
225           
226             if site_authority == peer_record.hrn:
227                 peer = peer_record
228         #print>>sys.stderr, " \r\n \r\n \t slices.py get_peer peer  %s " %(peer) 
229         return peer
230
231     def get_sfa_peer(self, xrn):
232         hrn, type = urn_to_hrn(xrn)
233
234         # return the authority for this hrn or None if we are the authority
235         sfa_peer = None
236         slice_authority = get_authority(hrn)
237         site_authority = get_authority(slice_authority)
238
239         if site_authority != self.driver.hrn:
240             sfa_peer = site_authority
241
242         return sfa_peer
243
244     def verify_slice_nodes(self, slice, requested_slivers, peer):
245         current_slivers = []
246         deleted_nodes = []
247         
248         if slice['node_ids']:
249             nodes = self.driver.GetNodes(slice['node_ids'], ['hostname'])
250             current_slivers = [node['hostname'] for node in nodes]
251     
252             # remove nodes not in rspec
253             deleted_nodes = list(set(current_slivers).difference(requested_slivers))
254     
255         # add nodes from rspec
256         added_nodes = list(set(requested_slivers).difference(current_slivers))        
257         #print>>sys.stderr , "\r\n \r\n \t slices.py  verify_slice_nodes added_nodes %s slice %s" %( added_nodes,slice)
258         try:
259             #if peer:
260                 #self.driver.UnBindObjectFromPeer('slice', slice['slice_id'], peer['shortname'])
261             #PI is a list, get the only username in this list
262             #so that the OAR/LDAP knows the user: remove the authority from the name
263             tmp=  slice['PI'][0].split(".")
264             username = tmp[(len(tmp)-1)]
265             #Update the table with the nodes that populate the slice
266             self.driver.db.update_job(slice['name'],nodes = added_nodes)
267             print>>sys.stderr, "\r\n \\r\n \r\n \t\t\t VERIFY_SLICE_NODES slice %s \r\n \r\n \r\n " %(slice)
268             #If there is a timeslot specified, then a job can be launched
269             try:
270                 slot = slice['timeslot']
271                 self.driver.LaunchExperimentOnOAR(slice, added_nodes, username)
272             except KeyError:
273                 pass
274
275             
276             if deleted_nodes:
277                 self.driver.DeleteSliceFromNodes(slice['name'], deleted_nodes)
278
279         except: 
280             logger.log_exc('Failed to add/remove slice from nodes')
281             
282
283     def free_egre_key(self):
284         used = set()
285         for tag in self.driver.GetSliceTags({'tagname': 'egre_key'}):
286                 used.add(int(tag['value']))
287
288         for i in range(1, 256):
289             if i not in used:
290                 key = i
291                 break
292         else:
293             raise KeyError("No more EGRE keys available")
294
295         return str(key)
296
297   
298        
299                         
300         
301
302     def handle_peer(self, site, slice, persons, peer):
303         if peer:
304             # bind site
305             try:
306                 if site:
307                     self.driver.BindObjectToPeer('site', site['site_id'], peer['shortname'], slice['site_id'])
308             except Exception,e:
309                 self.driver.DeleteSite(site['site_id'])
310                 raise e
311             
312             # bind slice
313             try:
314                 if slice:
315                     self.driver.BindObjectToPeer('slice', slice['slice_id'], peer['shortname'], slice['slice_id'])
316             except Exception,e:
317                 self.driver.DeleteSlice(slice['slice_id'])
318                 raise e 
319
320             # bind persons
321             for person in persons:
322                 try:
323                     self.driver.BindObjectToPeer('person', 
324                                                      person['person_id'], peer['shortname'], person['peer_person_id'])
325
326                     for (key, remote_key_id) in zip(person['keys'], person['key_ids']):
327                         try:
328                             self.driver.BindObjectToPeer( 'key', key['key_id'], peer['shortname'], remote_key_id)
329                         except:
330                             self.driver.DeleteKey(key['key_id'])
331                             logger("failed to bind key: %s to peer: %s " % (key['key_id'], peer['shortname']))
332                 except Exception,e:
333                     self.driver.DeletePerson(person['person_id'])
334                     raise e       
335
336         return slice
337
338     #def verify_site(self, slice_xrn, slice_record={}, peer=None, sfa_peer=None, options={}):
339         #(slice_hrn, type) = urn_to_hrn(slice_xrn)
340         #site_hrn = get_authority(slice_hrn)
341         ## login base can't be longer than 20 characters
342         ##slicename = hrn_to_pl_slicename(slice_hrn)
343         #authority_name = slice_hrn.split('.')[0]
344         #login_base = authority_name[:20]
345         #print >>sys.stderr, " \r\n \r\n \t\t SLABSLICES.PY verify_site authority_name %s  login_base %s slice_hrn %s" %(authority_name,login_base,slice_hrn)
346         
347         #sites = self.driver.GetSites(login_base)
348         #if not sites:
349             ## create new site record
350             #site = {'name': 'geni.%s' % authority_name,
351                     #'abbreviated_name': authority_name,
352                     #'login_base': login_base,
353                     #'max_slices': 100,
354                     #'max_slivers': 1000,
355                     #'enabled': True,
356                     #'peer_site_id': None}
357             #if peer:
358                 #site['peer_site_id'] = slice_record.get('site_id', None)
359             #site['site_id'] = self.driver.AddSite(site)
360             ## exempt federated sites from monitor policies
361             #self.driver.AddSiteTag(site['site_id'], 'exempt_site_until', "20200101")
362             
363             ### is this still necessary?
364             ### add record to the local registry 
365             ##if sfa_peer and slice_record:
366                 ##peer_dict = {'type': 'authority', 'hrn': site_hrn, \
367                              ##'peer_authority': sfa_peer, 'pointer': site['site_id']}
368                 ##self.registry.register_peer_object(self.credential, peer_dict)
369         #else:
370             #site =  sites[0]
371             #if peer:
372                 ## unbind from peer so we can modify if necessary. Will bind back later
373                 #self.driver.UnBindObjectFromPeer('site', site['site_id'], peer['shortname']) 
374         
375         #return site        
376
377     def verify_slice(self, slice_hrn, slice_record, peer, sfa_peer, options={} ):
378
379         login_base = slice_hrn.split(".")[0]
380         slicename = slice_hrn
381         sl = self.driver.GetSlices(slice_filter=slicename, filter_type = 'slice_hrn') 
382         if sl:
383
384             print>>sys.stderr, " \r\n \r\rn Slices.py verify_slice slicename %s sl %s slice_record %s"%(slicename ,sl, slice_record)
385         else:
386             print>>sys.stderr, " \r\n \r\rn Slices.py verify_slice UH-Oh..."
387         if not sl:
388             slice = {'name': slicename,
389                      'url': slice_record.get('url', slice_hrn), 
390                      #'description': slice_record.get('description', slice_hrn)
391                      }
392             # add the slice                          
393             slice['slice_id'] = self.driver.AddSlice(slice)
394             slice['node_ids'] = []
395             slice['person_ids'] = []
396             #if peer:
397                 #slice['peer_slice_id'] = slice_record.get('slice_id', None) 
398             # mark this slice as an sfa peer record
399             #if sfa_peer:
400                 #peer_dict = {'type': 'slice', 'hrn': slice_hrn, 
401                              #'peer_authority': sfa_peer, 'pointer': slice['slice_id']}
402                 #self.registry.register_peer_object(self.credential, peer_dict)
403         else:
404             slice = sl
405             slice.update(slice_record)
406             #del slice['last_updated']
407             #del slice['date_created']
408             #if peer:
409                 #slice['peer_slice_id'] = slice_record.get('slice_id', None)
410                 ## unbind from peer so we can modify if necessary. Will bind back later
411                 #self.driver.UnBindObjectFromPeer('slice', slice['slice_id'], peer['shortname'])
412                 #Update existing record (e.g. expires field) it with the latest info.
413             ##if slice_record and slice['expires'] != slice_record['expires']:
414                 ##self.driver.UpdateSlice( slice['slice_id'], {'expires' : slice_record['expires']})
415        
416         return slice
417
418
419     def verify_persons(self, slice_hrn, slice_record, users,  peer, sfa_peer, options={}):
420         users_by_id = {}
421         users_by_hrn = {}
422         users_dict = {}
423       
424         for user in users:
425             
426             if 'urn' in user and (not 'hrn' in user ) :
427                 user['hrn'],user['type'] = urn_to_hrn(user['urn'])
428                
429             if 'person_id' in user and 'hrn' in user:
430                 users_by_id[user['person_id']] = user
431                 users_dict[user['person_id']] = {'person_id':user['person_id'], 'hrn':user['hrn']}
432
433                 users_by_hrn[user['hrn']] = user
434                 users_dict[user['hrn']] = {'person_id':user['person_id'], 'hrn':user['hrn']}
435                 
436         #print>>sys.stderr, " \r\n \r\n \t slabslices.py verify_person  users_dict %s \r\n user_by_hrn %s \r\n \tusers_by_id %s " %( users_dict,users_by_hrn, users_by_id) 
437         
438         existing_user_ids = []
439         existing_user_hrns = []
440         existing_users= []
441         #Check if user is in LDAP using its hrn.
442         #Assuming Senslab is centralised :  one LDAP for all sites, user_id unknown from LDAP
443         # LDAP does not provide users id, therfore we rely on hrns
444         if users_by_hrn:
445             existing_users = self.driver.GetPersons({'hrn': users_by_hrn.keys()}, 
446                                                         ['hrn','pkey'])
447             if existing_users:
448                 for user in existing_users :
449                     #for  k in users_dict[user['hrn']] :
450                     existing_user_hrns.append (users_dict[user['hrn']]['hrn'])
451                     existing_user_ids.append (users_dict[user['hrn']]['person_id'])
452                     #print>>sys.stderr, " \r\n \r\n \t slabslices.py verify_person  existing_user_ids.append (users_dict[user['hrn']][k]) %s \r\n existing_users %s " %(  existing_user_ids,existing_users) 
453          
454             #User from another federated site , does not have a senslab account yet
455             else:
456                 pass
457                 
458         # requested slice users        
459         requested_user_ids = users_by_id.keys() 
460         requested_user_hrns = users_by_hrn.keys()
461         #print>>sys.stderr, " \r\n \r\n \t slabslices.py verify_person  requested_user_ids  %s user_by_hrn %s " %( requested_user_ids,users_by_hrn) 
462         # existing slice users
463         existing_slice_users_filter = {'hrn': slice_record.get('PI', [])}
464         #print>>sys.stderr, " \r\n \r\n slices.py verify_person requested_user_ids %s existing_slice_users_filter %s slice_record %s" %(requested_user_ids,existing_slice_users_filter,slice_record)
465         
466         existing_slice_users = self.driver.GetPersons(existing_slice_users_filter,['hrn','pkey'])
467         #print>>sys.stderr, " \r\n \r\n slices.py verify_person   existing_slice_users %s " %(existing_slice_users)
468
469         existing_slice_user_hrns = [user['hrn'] for user in existing_slice_users]
470
471         #print>>sys.stderr, " \r\n \r\n slices.py verify_person requested_user_ids %s  existing_slice_user_hrns %s " %(requested_user_ids,existing_slice_user_hrns)
472         # users to be added, removed or updated
473
474         added_user_hrns = set(requested_user_hrns).difference(set(existing_user_hrns))
475
476         added_slice_user_hrns = set(requested_user_hrns).difference(existing_slice_user_hrns)
477         
478         removed_user_hrns = set(existing_slice_user_hrns).difference(requested_user_hrns)
479         
480
481         updated_user_hrns = set(existing_slice_user_hrns).intersection(requested_user_hrns)
482         #print>>sys.stderr, " \r\n \r\n slices.py verify_persons  added_user_ids %s added_slice_user_ids %s " %(added_user_ids,added_slice_user_ids)
483         #print>>sys.stderr, " \r\n \r\n slices.py verify_persons  removed_user_hrns %s updated_user_hrns %s " %(removed_user_hrns,updated_user_hrns)
484         # Remove stale users (only if we are not appending) 
485         append = options.get('append', True)
486         if append == False:
487             for removed_user_hrn in removed_user_hrns:
488                 self.driver.DeletePersonFromSlice(removed_user_hrn, slice_record['name'])
489         # update_existing users
490         updated_users_list = [user for user in existing_slice_users if user['hrn'] in \
491           updated_user_hrns]
492         #print>>sys.stderr, " \r\n \r\n slices.py verify_persons  removed_user_hrns %s updated_users_list %s " %(removed_user_hrns,updated_users_list) 
493         #self.verify_keys(existing_slice_users, updated_users_list, peer, append)
494
495         added_persons = []
496         # add new users
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'])  
500             person = {
501                 #'first_name': added_user.get('first_name', hrn),
502                 #'last_name': added_user.get('last_name', hrn),
503                 'person_id': added_user['person_id'],
504                 #'peer_person_id': None,
505                 #'keys': [],
506                 #'key_ids': added_user.get('key_ids', []),
507                 
508             } 
509             #print>>sys.stderr, " \r\n \r\n slices.py verify_persons   added_user_ids %s " %(added_user_ids)
510             person['person_id'] = self.driver.AddPerson(person)
511             if peer:
512                 person['peer_person_id'] = added_user['person_id']
513             added_persons.append(person)
514            
515             # enable the account 
516             self.driver.UpdatePerson(person['person_id'], {'enabled': True})
517             
518             # add person to site
519             #self.driver.AddPersonToSite(added_user_id, login_base)
520
521             #for key_string in added_user.get('keys', []):
522                 #key = {'key':key_string, 'key_type':'ssh'}
523                 #key['key_id'] = self.driver.AddPersonKey(person['person_id'], key)
524                 #person['keys'].append(key)
525
526             # add the registry record
527             #if sfa_peer:
528                 #peer_dict = {'type': 'user', 'hrn': hrn, 'peer_authority': sfa_peer, \
529                     #'pointer': person['person_id']}
530                 #self.registry.register_peer_object(self.credential, peer_dict)
531         for added_slice_user_hrn in added_slice_user_hrns.union(added_user_hrns):           
532             self.driver.AddPersonToSlice(added_slice_user_hrn, slice_record['name'])
533         #for added_slice_user_id in added_slice_user_ids.union(added_user_ids):
534             # add person to the slice 
535             #self.driver.AddPersonToSlice(added_slice_user_id, slice_record['name'])
536             # if this is a peer record then it should already be bound to a peer.
537             # no need to return worry about it getting bound later 
538
539         return added_persons
540             
541
542     def verify_keys(self, persons, users, peer, options={}):
543         # existing keys 
544         key_ids = []
545         for person in persons:
546             key_ids.extend(person['key_ids'])
547         keylist = self.driver.GetKeys(key_ids, ['key_id', 'key'])
548         keydict = {}
549         for key in keylist:
550             keydict[key['key']] = key['key_id']     
551         existing_keys = keydict.keys()
552         persondict = {}
553         for person in persons:
554             persondict[person['email']] = person    
555     
556         # add new keys
557         requested_keys = []
558         updated_persons = []
559         for user in users:
560             user_keys = user.get('keys', [])
561             updated_persons.append(user)
562             for key_string in user_keys:
563                 requested_keys.append(key_string)
564                 if key_string not in existing_keys:
565                     key = {'key': key_string, 'key_type': 'ssh'}
566                     try:
567                         if peer:
568                             person = persondict[user['email']]
569                             self.driver.UnBindObjectFromPeer('person', person['person_id'], peer['shortname'])
570                         key['key_id'] = self.driver.AddPersonKey(user['email'], key)
571                         if peer:
572                             key_index = user_keys.index(key['key'])
573                             remote_key_id = user['key_ids'][key_index]
574                             self.driver.BindObjectToPeer('key', key['key_id'], peer['shortname'], remote_key_id)
575                             
576                     finally:
577                         if peer:
578                             self.driver.BindObjectToPeer('person', person['person_id'], peer['shortname'], user['person_id'])
579         
580         # remove old keys (only if we are not appending)
581         if append == False: 
582             removed_keys = set(existing_keys).difference(requested_keys)
583             for existing_key_id in keydict:
584                 if keydict[existing_key_id] in removed_keys:
585                     try:
586                         if peer:
587                             self.driver.UnBindObjectFromPeer('key', existing_key_id, peer['shortname'])
588                         self.driver.DeleteKey(existing_key_id)
589                     except:
590                         pass   
591
592     #def verify_slice_attributes(self, slice, requested_slice_attributes, append=False, admin=False):
593         ## get list of attributes users ar able to manage
594         #filter = {'category': '*slice*'}
595         #if not admin:
596             #filter['|roles'] = ['user']
597         #slice_attributes = self.driver.GetTagTypes(filter)
598         #valid_slice_attribute_names = [attribute['tagname'] for attribute in slice_attributes]
599
600         ## get sliver attributes
601         #added_slice_attributes = []
602         #removed_slice_attributes = []
603         #ignored_slice_attribute_names = []
604         #existing_slice_attributes = self.driver.GetSliceTags({'slice_id': slice['slice_id']})
605
606         ## get attributes that should be removed
607         #for slice_tag in existing_slice_attributes:
608             #if slice_tag['tagname'] in ignored_slice_attribute_names:
609                 ## If a slice already has a admin only role it was probably given to them by an
610                 ## admin, so we should ignore it.
611                 #ignored_slice_attribute_names.append(slice_tag['tagname'])
612             #else:
613                 ## If an existing slice attribute was not found in the request it should
614                 ## be removed
615                 #attribute_found=False
616                 #for requested_attribute in requested_slice_attributes:
617                     #if requested_attribute['name'] == slice_tag['tagname'] and \
618                        #requested_attribute['value'] == slice_tag['value']:
619                         #attribute_found=True
620                         #break
621
622             #if not attribute_found and not append:
623                 #removed_slice_attributes.append(slice_tag)
624         
625         ## get attributes that should be added:
626         #for requested_attribute in requested_slice_attributes:
627             ## if the requested attribute wasn't found  we should add it
628             #if requested_attribute['name'] in valid_slice_attribute_names:
629                 #attribute_found = False
630                 #for existing_attribute in existing_slice_attributes:
631                     #if requested_attribute['name'] == existing_attribute['tagname'] and \
632                        #requested_attribute['value'] == existing_attribute['value']:
633                         #attribute_found=True
634                         #break
635                 #if not attribute_found:
636                     #added_slice_attributes.append(requested_attribute)
637
638
639         ## remove stale attributes
640         #for attribute in removed_slice_attributes:
641             #try:
642                 #self.driver.DeleteSliceTag(attribute['slice_tag_id'])
643             #except Exception, e:
644                 #self.logger.warn('Failed to remove sliver attribute. name: %s, value: %s, node_id: %s\nCause:%s'\
645                                 #% (name, value,  node_id, str(e)))
646
647         ## add requested_attributes
648         #for attribute in added_slice_attributes:
649             #try:
650                 #self.driver.AddSliceTag(slice['name'], attribute['name'], attribute['value'], attribute.get('node_id', None))
651             #except Exception, e:
652                 #self.logger.warn('Failed to add sliver attribute. name: %s, value: %s, node_id: %s\nCause:%s'\
653                                 #% (name, value,  node_id, str(e)))
654
655     #def create_slice_aggregate(self, xrn, rspec):
656         #hrn, type = urn_to_hrn(xrn)
657         ## Determine if this is a peer slice
658         #peer = self.get_peer(hrn)
659         #sfa_peer = self.get_sfa_peer(hrn)
660
661         #spec = RSpec(rspec)
662         ## Get the slice record from sfa
663         #slicename = hrn_to_pl_slicename(hrn) 
664         #slice = {}
665         #slice_record = None
666         #registry = self.api.registries[self.api.hrn]
667         #credential = self.api.getCredential()
668
669         #site_id, remote_site_id = self.verify_site(registry, credential, hrn, peer, sfa_peer)
670         #slice = self.verify_slice(registry, credential, hrn, site_id, remote_site_id, peer, sfa_peer)
671
672         ## find out where this slice is currently running
673         #nodelist = self.driver.GetNodes(slice['node_ids'], ['hostname'])
674         #hostnames = [node['hostname'] for node in nodelist]
675
676         ## get netspec details
677         #nodespecs = spec.getDictsByTagName('NodeSpec')
678
679         ## dict in which to store slice attributes to set for the nodes
680         #nodes = {}
681         #for nodespec in nodespecs:
682             #if isinstance(nodespec['name'], list):
683                 #for nodename in nodespec['name']:
684                     #nodes[nodename] = {}
685                     #for k in nodespec.keys():
686                         #rspec_attribute_value = nodespec[k]
687                         #if (self.rspec_to_slice_tag.has_key(k)):
688                             #slice_tag_name = self.rspec_to_slice_tag[k]
689                             #nodes[nodename][slice_tag_name] = rspec_attribute_value
690             #elif isinstance(nodespec['name'], StringTypes):
691                 #nodename = nodespec['name']
692                 #nodes[nodename] = {}
693                 #for k in nodespec.keys():
694                     #rspec_attribute_value = nodespec[k]
695                     #if (self.rspec_to_slice_tag.has_key(k)):
696                         #slice_tag_name = self.rspec_to_slice_tag[k]
697                         #nodes[nodename][slice_tag_name] = rspec_attribute_value
698
699                 #for k in nodespec.keys():
700                     #rspec_attribute_value = nodespec[k]
701                     #if (self.rspec_to_slice_tag.has_key(k)):
702                         #slice_tag_name = self.rspec_to_slice_tag[k]
703                         #nodes[nodename][slice_tag_name] = rspec_attribute_value
704
705         #node_names = nodes.keys()
706         ## remove nodes not in rspec
707         #deleted_nodes = list(set(hostnames).difference(node_names))
708         ## add nodes from rspec
709         #added_nodes = list(set(node_names).difference(hostnames))
710
711         #try:
712             #if peer:
713                 #self.driver.UnBindObjectFromPeer('slice', slice['slice_id'], peer)
714
715             #self.driver.LaunchExperimentOnOAR(slicename, added_nodes) 
716
717             ## Add recognized slice tags
718             #for node_name in node_names:
719                 #node = nodes[node_name]
720                 #for slice_tag in node.keys():
721                     #value = node[slice_tag]
722                     #if (isinstance(value, list)):
723                         #value = value[0]
724
725                     #self.driver.AddSliceTag(slicename, slice_tag, value, node_name)
726
727             #self.driver.DeleteSliceFromNodes(slicename, deleted_nodes)
728         #finally:
729             #if peer:
730                 #self.driver.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id'])
731
732         #return 1
733