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