Merge branch 'master' into senslab2
[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             self.driver.AddSliceToNodes(slice, added_nodes, username)
266             #self.driver.AddSliceToNodes(slice['name'], added_nodes, username)
267             
268             if deleted_nodes:
269                 self.driver.DeleteSliceFromNodes(slice['name'], deleted_nodes)
270
271         except: 
272             logger.log_exc('Failed to add/remove slice from nodes')
273
274     def free_egre_key(self):
275         used = set()
276         for tag in self.driver.GetSliceTags({'tagname': 'egre_key'}):
277                 used.add(int(tag['value']))
278
279         for i in range(1, 256):
280             if i not in used:
281                 key = i
282                 break
283         else:
284             raise KeyError("No more EGRE keys available")
285
286         return str(key)
287
288   
289        
290                         
291         
292
293     def handle_peer(self, site, slice, persons, peer):
294         if peer:
295             # bind site
296             try:
297                 if site:
298                     self.driver.BindObjectToPeer('site', site['site_id'], peer['shortname'], slice['site_id'])
299             except Exception,e:
300                 self.driver.DeleteSite(site['site_id'])
301                 raise e
302             
303             # bind slice
304             try:
305                 if slice:
306                     self.driver.BindObjectToPeer('slice', slice['slice_id'], peer['shortname'], slice['slice_id'])
307             except Exception,e:
308                 self.driver.DeleteSlice(slice['slice_id'])
309                 raise e 
310
311             # bind persons
312             for person in persons:
313                 try:
314                     self.driver.BindObjectToPeer('person', 
315                                                      person['person_id'], peer['shortname'], person['peer_person_id'])
316
317                     for (key, remote_key_id) in zip(person['keys'], person['key_ids']):
318                         try:
319                             self.driver.BindObjectToPeer( 'key', key['key_id'], peer['shortname'], remote_key_id)
320                         except:
321                             self.driver.DeleteKey(key['key_id'])
322                             logger("failed to bind key: %s to peer: %s " % (key['key_id'], peer['shortname']))
323                 except Exception,e:
324                     self.driver.DeletePerson(person['person_id'])
325                     raise e       
326
327         return slice
328
329     #def verify_site(self, slice_xrn, slice_record={}, peer=None, sfa_peer=None, options={}):
330         #(slice_hrn, type) = urn_to_hrn(slice_xrn)
331         #site_hrn = get_authority(slice_hrn)
332         ## login base can't be longer than 20 characters
333         ##slicename = hrn_to_pl_slicename(slice_hrn)
334         #authority_name = slice_hrn.split('.')[0]
335         #login_base = authority_name[:20]
336         #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)
337         
338         #sites = self.driver.GetSites(login_base)
339         #if not sites:
340             ## create new site record
341             #site = {'name': 'geni.%s' % authority_name,
342                     #'abbreviated_name': authority_name,
343                     #'login_base': login_base,
344                     #'max_slices': 100,
345                     #'max_slivers': 1000,
346                     #'enabled': True,
347                     #'peer_site_id': None}
348             #if peer:
349                 #site['peer_site_id'] = slice_record.get('site_id', None)
350             #site['site_id'] = self.driver.AddSite(site)
351             ## exempt federated sites from monitor policies
352             #self.driver.AddSiteTag(site['site_id'], 'exempt_site_until', "20200101")
353             
354             ### is this still necessary?
355             ### add record to the local registry 
356             ##if sfa_peer and slice_record:
357                 ##peer_dict = {'type': 'authority', 'hrn': site_hrn, \
358                              ##'peer_authority': sfa_peer, 'pointer': site['site_id']}
359                 ##self.registry.register_peer_object(self.credential, peer_dict)
360         #else:
361             #site =  sites[0]
362             #if peer:
363                 ## unbind from peer so we can modify if necessary. Will bind back later
364                 #self.driver.UnBindObjectFromPeer('site', site['site_id'], peer['shortname']) 
365         
366         #return site        
367
368     def verify_slice(self, slice_hrn, slice_record, peer, sfa_peer, options={} ):
369
370         login_base = slice_hrn.split(".")[0]
371         slicename = slice_hrn
372         sl = self.driver.GetSlices(slice_filter=slicename, filter_type = 'slice_hrn') 
373         if sl:
374
375             print>>sys.stderr, " \r\n \r\rn Slices.py verify_slice slicename %s sl %s slice_record %s"%(slicename ,sl, slice_record)
376         else:
377             print>>sys.stderr, " \r\n \r\rn Slices.py verify_slice UH-Oh..."
378         if not sl:
379             slice = {'name': slicename,
380                      'url': slice_record.get('url', slice_hrn), 
381                      #'description': slice_record.get('description', slice_hrn)
382                      }
383             # add the slice                          
384             slice['slice_id'] = self.driver.AddSlice(slice)
385             slice['node_ids'] = []
386             slice['person_ids'] = []
387             #if peer:
388                 #slice['peer_slice_id'] = slice_record.get('slice_id', None) 
389             # mark this slice as an sfa peer record
390             #if sfa_peer:
391                 #peer_dict = {'type': 'slice', 'hrn': slice_hrn, 
392                              #'peer_authority': sfa_peer, 'pointer': slice['slice_id']}
393                 #self.registry.register_peer_object(self.credential, peer_dict)
394         else:
395             slice = sl
396             slice.update(slice_record)
397             #del slice['last_updated']
398             #del slice['date_created']
399             #if peer:
400                 #slice['peer_slice_id'] = slice_record.get('slice_id', None)
401                 ## unbind from peer so we can modify if necessary. Will bind back later
402                 #self.driver.UnBindObjectFromPeer('slice', slice['slice_id'], peer['shortname'])
403                 #Update existing record (e.g. expires field) it with the latest info.
404             ##if slice_record and slice['expires'] != slice_record['expires']:
405                 ##self.driver.UpdateSlice( slice['slice_id'], {'expires' : slice_record['expires']})
406        
407         return slice
408
409     #def get_existing_persons(self, users):
410     def verify_persons(self, slice_hrn, slice_record, users,  peer, sfa_peer, options={}):
411         users_by_id = {}
412         users_by_hrn = {}
413         users_dict = {}
414       
415         for user in users:
416             
417             if 'urn' in user and (not 'hrn' in user ) :
418                 user['hrn'],user['type'] = urn_to_hrn(user['urn'])
419                
420             if 'person_id' in user and 'hrn' in user:
421                 users_by_id[user['person_id']] = user
422                 users_dict[user['person_id']] = {'person_id':user['person_id'], 'hrn':user['hrn']}
423
424                 users_by_hrn[user['hrn']] = user
425                 users_dict[user['hrn']] = {'person_id':user['person_id'], 'hrn':user['hrn']}
426                 
427         #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) 
428         
429         existing_user_ids = []
430         existing_user_hrns = []
431         existing_users= []
432         #Check if user is in LDAP using its hrn.
433         #Assuming Senslab is centralised :  one LDAP for all sites, user_id unknown from LDAP
434         # LDAP does not provide users id, therfore we rely on hrns
435         if users_by_hrn:
436             existing_users = self.driver.GetPersons({'hrn': users_by_hrn.keys()}, 
437                                                         ['hrn','pkey'])
438             if existing_users:
439                 for user in existing_users :
440                     #for  k in users_dict[user['hrn']] :
441                     existing_user_hrns.append (users_dict[user['hrn']]['hrn'])
442                     existing_user_ids.append (users_dict[user['hrn']]['person_id'])
443                     #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) 
444          
445
446         # requested slice users        
447         requested_user_ids = users_by_id.keys() 
448         requested_user_hrns = users_by_hrn.keys()
449         #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) 
450         # existing slice users
451         existing_slice_users_filter = {'hrn': slice_record.get('PI', [])}
452         #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)
453         
454         existing_slice_users = self.driver.GetPersons(existing_slice_users_filter,['hrn','pkey'])
455         #print>>sys.stderr, " \r\n \r\n slices.py verify_person   existing_slice_users %s " %(existing_slice_users)
456
457         existing_slice_user_hrns = [user['hrn'] for user in existing_slice_users]
458
459         #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)
460         # users to be added, removed or updated
461
462         added_user_hrns = set(requested_user_hrns).difference(set(existing_user_hrns))
463
464         added_slice_user_hrns = set(requested_user_hrns).difference(existing_slice_user_hrns)
465         
466         removed_user_hrns = set(existing_slice_user_hrns).difference(requested_user_hrns)
467         
468
469         updated_user_hrns = set(existing_slice_user_hrns).intersection(requested_user_hrns)
470         #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)
471         #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)
472         # Remove stale users (only if we are not appending) 
473         append = options.get('append', True)
474         if append == False:
475             for removed_user_hrn in removed_user_hrns:
476                 self.driver.DeletePersonFromSlice(removed_user_hrn, slice_record['name'])
477         # update_existing users
478         updated_users_list = [user for user in existing_slice_users if user['hrn'] in \
479           updated_user_hrns]
480         #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) 
481         #self.verify_keys(existing_slice_users, updated_users_list, peer, append)
482
483         added_persons = []
484         # add new users
485         for added_user_hrn in added_user_hrns:
486             added_user = users_dict[added_user_hrn]
487             #hrn, type = urn_to_hrn(added_user['urn'])  
488             person = {
489                 #'first_name': added_user.get('first_name', hrn),
490                 #'last_name': added_user.get('last_name', hrn),
491                 'person_id': added_user['person_id'],
492                 #'peer_person_id': None,
493                 #'keys': [],
494                 #'key_ids': added_user.get('key_ids', []),
495                 
496             } 
497             #print>>sys.stderr, " \r\n \r\n slices.py verify_persons   added_user_ids %s " %(added_user_ids)
498             person['person_id'] = self.driver.AddPerson(person)
499             if peer:
500                 person['peer_person_id'] = added_user['person_id']
501             added_persons.append(person)
502            
503             # enable the account 
504             self.driver.UpdatePerson(person['person_id'], {'enabled': True})
505             
506             # add person to site
507             #self.driver.AddPersonToSite(added_user_id, login_base)
508
509             #for key_string in added_user.get('keys', []):
510                 #key = {'key':key_string, 'key_type':'ssh'}
511                 #key['key_id'] = self.driver.AddPersonKey(person['person_id'], key)
512                 #person['keys'].append(key)
513
514             # add the registry record
515             #if sfa_peer:
516                 #peer_dict = {'type': 'user', 'hrn': hrn, 'peer_authority': sfa_peer, \
517                     #'pointer': person['person_id']}
518                 #self.registry.register_peer_object(self.credential, peer_dict)
519         for added_slice_user_hrn in added_slice_user_hrns.union(added_user_hrns):           
520             self.driver.AddPersonToSlice(added_slice_user_hrn, slice_record['name'])
521         #for added_slice_user_id in added_slice_user_ids.union(added_user_ids):
522             # add person to the slice 
523             #self.driver.AddPersonToSlice(added_slice_user_id, slice_record['name'])
524             # if this is a peer record then it should already be bound to a peer.
525             # no need to return worry about it getting bound later 
526
527         return added_persons
528             
529
530     def verify_keys(self, persons, users, peer, options={}):
531         # existing keys 
532         key_ids = []
533         for person in persons:
534             key_ids.extend(person['key_ids'])
535         keylist = self.driver.GetKeys(key_ids, ['key_id', 'key'])
536         keydict = {}
537         for key in keylist:
538             keydict[key['key']] = key['key_id']     
539         existing_keys = keydict.keys()
540         persondict = {}
541         for person in persons:
542             persondict[person['email']] = person    
543     
544         # add new keys
545         requested_keys = []
546         updated_persons = []
547         for user in users:
548             user_keys = user.get('keys', [])
549             updated_persons.append(user)
550             for key_string in user_keys:
551                 requested_keys.append(key_string)
552                 if key_string not in existing_keys:
553                     key = {'key': key_string, 'key_type': 'ssh'}
554                     try:
555                         if peer:
556                             person = persondict[user['email']]
557                             self.driver.UnBindObjectFromPeer('person', person['person_id'], peer['shortname'])
558                         key['key_id'] = self.driver.AddPersonKey(user['email'], key)
559                         if peer:
560                             key_index = user_keys.index(key['key'])
561                             remote_key_id = user['key_ids'][key_index]
562                             self.driver.BindObjectToPeer('key', key['key_id'], peer['shortname'], remote_key_id)
563                             
564                     finally:
565                         if peer:
566                             self.driver.BindObjectToPeer('person', person['person_id'], peer['shortname'], user['person_id'])
567         
568         # remove old keys (only if we are not appending)
569         if append == False: 
570             removed_keys = set(existing_keys).difference(requested_keys)
571             for existing_key_id in keydict:
572                 if keydict[existing_key_id] in removed_keys:
573                     try:
574                         if peer:
575                             self.driver.UnBindObjectFromPeer('key', existing_key_id, peer['shortname'])
576                         self.driver.DeleteKey(existing_key_id)
577                     except:
578                         pass   
579
580     #def verify_slice_attributes(self, slice, requested_slice_attributes, append=False, admin=False):
581         ## get list of attributes users ar able to manage
582         #filter = {'category': '*slice*'}
583         #if not admin:
584             #filter['|roles'] = ['user']
585         #slice_attributes = self.driver.GetTagTypes(filter)
586         #valid_slice_attribute_names = [attribute['tagname'] for attribute in slice_attributes]
587
588         ## get sliver attributes
589         #added_slice_attributes = []
590         #removed_slice_attributes = []
591         #ignored_slice_attribute_names = []
592         #existing_slice_attributes = self.driver.GetSliceTags({'slice_id': slice['slice_id']})
593
594         ## get attributes that should be removed
595         #for slice_tag in existing_slice_attributes:
596             #if slice_tag['tagname'] in ignored_slice_attribute_names:
597                 ## If a slice already has a admin only role it was probably given to them by an
598                 ## admin, so we should ignore it.
599                 #ignored_slice_attribute_names.append(slice_tag['tagname'])
600             #else:
601                 ## If an existing slice attribute was not found in the request it should
602                 ## be removed
603                 #attribute_found=False
604                 #for requested_attribute in requested_slice_attributes:
605                     #if requested_attribute['name'] == slice_tag['tagname'] and \
606                        #requested_attribute['value'] == slice_tag['value']:
607                         #attribute_found=True
608                         #break
609
610             #if not attribute_found and not append:
611                 #removed_slice_attributes.append(slice_tag)
612         
613         ## get attributes that should be added:
614         #for requested_attribute in requested_slice_attributes:
615             ## if the requested attribute wasn't found  we should add it
616             #if requested_attribute['name'] in valid_slice_attribute_names:
617                 #attribute_found = False
618                 #for existing_attribute in existing_slice_attributes:
619                     #if requested_attribute['name'] == existing_attribute['tagname'] and \
620                        #requested_attribute['value'] == existing_attribute['value']:
621                         #attribute_found=True
622                         #break
623                 #if not attribute_found:
624                     #added_slice_attributes.append(requested_attribute)
625
626
627         ## remove stale attributes
628         #for attribute in removed_slice_attributes:
629             #try:
630                 #self.driver.DeleteSliceTag(attribute['slice_tag_id'])
631             #except Exception, e:
632                 #self.logger.warn('Failed to remove sliver attribute. name: %s, value: %s, node_id: %s\nCause:%s'\
633                                 #% (name, value,  node_id, str(e)))
634
635         ## add requested_attributes
636         #for attribute in added_slice_attributes:
637             #try:
638                 #self.driver.AddSliceTag(slice['name'], attribute['name'], attribute['value'], attribute.get('node_id', None))
639             #except Exception, e:
640                 #self.logger.warn('Failed to add sliver attribute. name: %s, value: %s, node_id: %s\nCause:%s'\
641                                 #% (name, value,  node_id, str(e)))
642
643     #def create_slice_aggregate(self, xrn, rspec):
644         #hrn, type = urn_to_hrn(xrn)
645         ## Determine if this is a peer slice
646         #peer = self.get_peer(hrn)
647         #sfa_peer = self.get_sfa_peer(hrn)
648
649         #spec = RSpec(rspec)
650         ## Get the slice record from sfa
651         #slicename = hrn_to_pl_slicename(hrn) 
652         #slice = {}
653         #slice_record = None
654         #registry = self.api.registries[self.api.hrn]
655         #credential = self.api.getCredential()
656
657         #site_id, remote_site_id = self.verify_site(registry, credential, hrn, peer, sfa_peer)
658         #slice = self.verify_slice(registry, credential, hrn, site_id, remote_site_id, peer, sfa_peer)
659
660         ## find out where this slice is currently running
661         #nodelist = self.driver.GetNodes(slice['node_ids'], ['hostname'])
662         #hostnames = [node['hostname'] for node in nodelist]
663
664         ## get netspec details
665         #nodespecs = spec.getDictsByTagName('NodeSpec')
666
667         ## dict in which to store slice attributes to set for the nodes
668         #nodes = {}
669         #for nodespec in nodespecs:
670             #if isinstance(nodespec['name'], list):
671                 #for nodename in nodespec['name']:
672                     #nodes[nodename] = {}
673                     #for k in nodespec.keys():
674                         #rspec_attribute_value = nodespec[k]
675                         #if (self.rspec_to_slice_tag.has_key(k)):
676                             #slice_tag_name = self.rspec_to_slice_tag[k]
677                             #nodes[nodename][slice_tag_name] = rspec_attribute_value
678             #elif isinstance(nodespec['name'], StringTypes):
679                 #nodename = nodespec['name']
680                 #nodes[nodename] = {}
681                 #for k in nodespec.keys():
682                     #rspec_attribute_value = nodespec[k]
683                     #if (self.rspec_to_slice_tag.has_key(k)):
684                         #slice_tag_name = self.rspec_to_slice_tag[k]
685                         #nodes[nodename][slice_tag_name] = rspec_attribute_value
686
687                 #for k in nodespec.keys():
688                     #rspec_attribute_value = nodespec[k]
689                     #if (self.rspec_to_slice_tag.has_key(k)):
690                         #slice_tag_name = self.rspec_to_slice_tag[k]
691                         #nodes[nodename][slice_tag_name] = rspec_attribute_value
692
693         #node_names = nodes.keys()
694         ## remove nodes not in rspec
695         #deleted_nodes = list(set(hostnames).difference(node_names))
696         ## add nodes from rspec
697         #added_nodes = list(set(node_names).difference(hostnames))
698
699         #try:
700             #if peer:
701                 #self.driver.UnBindObjectFromPeer('slice', slice['slice_id'], peer)
702
703             #self.driver.AddSliceToNodes(slicename, added_nodes) 
704
705             ## Add recognized slice tags
706             #for node_name in node_names:
707                 #node = nodes[node_name]
708                 #for slice_tag in node.keys():
709                     #value = node[slice_tag]
710                     #if (isinstance(value, list)):
711                         #value = value[0]
712
713                     #self.driver.AddSliceTag(slicename, slice_tag, value, node_name)
714
715             #self.driver.DeleteSliceFromNodes(slicename, deleted_nodes)
716         #finally:
717             #if peer:
718                 #self.driver.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id'])
719
720         #return 1
721