29213a92ef497760490dd94fe19fdb83b3adebcd
[sfa.git] / sfa / plc / slices.py
1 ### $Id$
2 ### $URL$
3
4 import datetime
5 import time
6 import traceback
7 import sys
8
9 from types import StringTypes
10 from sfa.util.misc import *
11 from sfa.util.rspec import *
12 from sfa.util.specdict import *
13 from sfa.util.faults import *
14 from sfa.util.storage import *
15 from sfa.util.record import GeniRecord
16 from sfa.util.policy import Policy
17 from sfa.util.prefixTree import prefixTree
18 from sfa.util.debug import log
19 from sfa.server.aggregate import Aggregates
20 from sfa.server.registry import Registries
21
22 MAXINT =  2L**31-1
23
24 class Slices(SimpleStorage):
25
26     rspec_to_slice_tag = {'max_rate':'net_max_rate'}
27
28     def __init__(self, api, ttl = .5, caller_cred=None):
29         self.api = api
30         self.ttl = ttl
31         self.threshold = None
32         path = self.api.config.SFA_DATA_DIR
33         filename = ".".join([self.api.interface, self.api.hrn, "slices"])
34         filepath = path + os.sep + filename
35         self.slices_file = filepath
36         SimpleStorage.__init__(self, self.slices_file)
37         self.policy = Policy(self.api)    
38         self.load()
39         self.caller_cred=caller_cred
40
41     def get_slivers(self, hrn, node=None):
42          
43         slice_name = hrn_to_pl_slicename(hrn)
44         # XX Should we just call PLCAPI.GetSliceTicket(slice_name) instead
45         # of doing all of this?
46         #return self.api.GetSliceTicket(self.auth, slice_name) 
47         
48         # from PLCAPI.GetSlivers.get_slivers()
49         slice_fields = ['slice_id', 'name', 'instantiation', 'expires', 'person_ids', 'slice_tag_ids']
50         slices = self.api.plshell.GetSlices(self.api.plauth, slice_name, slice_fields)
51         # Build up list of users and slice attributes
52         person_ids = set()
53         all_slice_tag_ids = set()
54         for slice in slices:
55             person_ids.update(slice['person_ids'])
56             all_slice_tag_ids.update(slice['slice_tag_ids'])
57         person_ids = list(person_ids)
58         all_slice_tag_ids = list(all_slice_tag_ids)
59         # Get user information
60         all_persons_list = self.api.plshell.GetPersons(self.api.plauth, {'person_id':person_ids,'enabled':True}, ['person_id', 'enabled', 'key_ids'])
61         all_persons = {}
62         for person in all_persons_list:
63             all_persons[person['person_id']] = person        
64
65         # Build up list of keys
66         key_ids = set()
67         for person in all_persons.values():
68             key_ids.update(person['key_ids'])
69         key_ids = list(key_ids)
70         # Get user account keys
71         all_keys_list = self.api.plshell.GetKeys(self.api.plauth, key_ids, ['key_id', 'key', 'key_type'])
72         all_keys = {}
73         for key in all_keys_list:
74             all_keys[key['key_id']] = key
75         # Get slice attributes
76         all_slice_tags_list = self.api.plshell.GetSliceTags(self.api.plauth, all_slice_tag_ids)
77         all_slice_tags = {}
78         for slice_tag in all_slice_tags_list:
79             all_slice_tags[slice_tag['slice_tag_id']] = slice_tag
80            
81         slivers = []
82         for slice in slices:
83             keys = []
84             for person_id in slice['person_ids']:
85                 if person_id in all_persons:
86                     person = all_persons[person_id]
87                     if not person['enabled']:
88                         continue
89                     for key_id in person['key_ids']:
90                         if key_id in all_keys:
91                             key = all_keys[key_id]
92                             keys += [{'key_type': key['key_type'],
93                                     'key': key['key']}]
94             attributes = []
95             # All (per-node and global) attributes for this slice
96             slice_tags = []
97             for slice_tag_id in slice['slice_tag_ids']:
98                 if slice_tag_id in all_slice_tags:
99                     slice_tags.append(all_slice_tags[slice_tag_id]) 
100             # Per-node sliver attributes take precedence over global
101             # slice attributes, so set them first.
102             # Then comes nodegroup slice attributes
103             # Followed by global slice attributes
104             sliver_attributes = []
105
106             if node is not None:
107                 for sliver_attribute in filter(lambda a: a['node_id'] == node['node_id'], slice_tags):
108                     sliver_attributes.append(sliver_attribute['tagname'])
109                     attributes.append({'tagname': sliver_attribute['tagname'],
110                                     'value': sliver_attribute['value']})
111
112             # set nodegroup slice attributes
113             for slice_tag in filter(lambda a: a['nodegroup_id'] in node['nodegroup_ids'], slice_tags):
114                 # Do not set any nodegroup slice attributes for
115                 # which there is at least one sliver attribute
116                 # already set.
117                 if slice_tag not in slice_tags:
118                     attributes.append({'tagname': slice_tag['tagname'],
119                         'value': slice_tag['value']})
120
121             for slice_tag in filter(lambda a: a['node_id'] is None, slice_tags):
122                 # Do not set any global slice attributes for
123                 # which there is at least one sliver attribute
124                 # already set.
125                 if slice_tag['tagname'] not in sliver_attributes:
126                     attributes.append({'tagname': slice_tag['tagname'],
127                                    'value': slice_tag['value']})
128
129             # XXX Sanity check; though technically this should be a system invariant
130             # checked with an assertion
131             if slice['expires'] > MAXINT:  slice['expires']= MAXINT
132             
133             slivers.append({
134                 'hrn': hrn,
135                 'name': slice['name'],
136                 'slice_id': slice['slice_id'],
137                 'instantiation': slice['instantiation'],
138                 'expires': slice['expires'],
139                 'keys': keys,
140                 'attributes': attributes
141             })
142
143         return slivers
144  
145     def get_peer(self, hrn):
146         # Becaues of myplc federation,  we first need to determine if this
147         # slice belongs to out local plc or a myplc peer. We will assume it 
148         # is a local site, unless we find out otherwise  
149         peer = None
150
151         # get this slice's authority (site)
152         slice_authority = get_authority(hrn)
153
154         # get this site's authority (sfa root authority or sub authority)
155         site_authority = get_authority(slice_authority).lower()
156
157         # check if we are already peered with this site_authority, if so
158         peers = self.api.plshell.GetPeers(self.api.plauth, {}, ['peer_id', 'peername', 'shortname', 'hrn_root'])
159         for peer_record in peers:
160             names = [name.lower() for name in peer_record.values() if isinstance(name, StringTypes)]
161             if site_authority in names:
162                 peer = peer_record['shortname']
163
164         return peer
165
166     def get_sfa_peer(self, hrn):
167         # return the authority for this hrn or None if we are the authority
168         sfa_peer = None
169         slice_authority = get_authority(hrn)
170         site_authority = get_authority(slice_authority)
171
172         if site_authority != self.api.hrn:
173             sfa_peer = site_authority
174
175         return sfa_peer 
176
177     def refresh(self):
178         """
179         Update the cached list of slices
180         """
181         # Reload components list
182         now = datetime.datetime.now()
183         if not self.has_key('threshold') or not self.has_key('timestamp') or \
184            now > datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['threshold'], self.api.time_format))):
185             if self.api.interface in ['aggregate']:
186                 self.refresh_slices_aggregate()
187             elif self.api.interface in ['slicemgr']:
188                 self.refresh_slices_smgr()
189
190     def refresh_slices_aggregate(self):
191         slices = self.api.plshell.GetSlices(self.api.plauth, {'peer_id': None}, ['name'])
192         slice_hrns = [slicename_to_hrn(self.api.hrn, slice['name']) for slice in slices]
193
194          # update timestamp and threshold
195         timestamp = datetime.datetime.now()
196         hr_timestamp = timestamp.strftime(self.api.time_format)
197         delta = datetime.timedelta(hours=self.ttl)
198         threshold = timestamp + delta
199         hr_threshold = threshold.strftime(self.api.time_format)
200         
201         slice_details = {'hrn': slice_hrns,
202                          'timestamp': hr_timestamp,
203                          'threshold': hr_threshold
204                         }
205         self.update(slice_details)
206         self.write()     
207         
208
209     def refresh_slices_smgr(self):
210         slice_hrns = []
211         aggregates = Aggregates(self.api)
212         credential = self.api.getCredential()
213         for aggregate in aggregates:
214             success = False
215             # request hash is optional so lets try the call without it 
216             try:
217                 slices = aggregates[aggregate].get_slices(credential)
218                 slice_hrns.extend(slices)
219                 success = True
220             except:
221                 print >> log, "%s" % (traceback.format_exc())
222                 print >> log, "Error calling slices at aggregate %(aggregate)s" % locals()
223
224             # try sending the request hash if the previous call failed 
225             if not success:
226                 arg_list = [credential]
227                 request_hash = self.api.key.compute_hash(arg_list)
228                 try:
229                     slices = aggregates[aggregate].get_slices(credential, request_hash)
230                     slice_hrns.extend(slices)
231                     success = True
232                 except:
233                     print >> log, "%s" % (traceback.format_exc())
234                     print >> log, "Error calling slices at aggregate %(aggregate)s" % locals()
235
236         # update timestamp and threshold
237         timestamp = datetime.datetime.now()
238         hr_timestamp = timestamp.strftime(self.api.time_format)
239         delta = datetime.timedelta(hours=self.ttl)
240         threshold = timestamp + delta
241         hr_threshold = threshold.strftime(self.api.time_format)
242
243         slice_details = {'hrn': slice_hrns,
244                          'timestamp': hr_timestamp,
245                          'threshold': hr_threshold
246                         }
247         self.update(slice_details)
248         self.write()
249
250
251     def delete_slice(self, hrn):
252         if self.api.interface in ['aggregate']:
253             self.delete_slice_aggregate(hrn)
254         elif self.api.interface in ['slicemgr']:
255             self.delete_slice_smgr(hrn)
256         
257     def delete_slice_aggregate(self, hrn):
258
259         slicename = hrn_to_pl_slicename(hrn)
260         slices = self.api.plshell.GetSlices(self.api.plauth, {'name': slicename})
261         if not slices:
262             return 1        
263         slice = slices[0]
264
265         # determine if this is a peer slice
266         peer = self.get_peer(hrn)
267         if peer:
268             self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'slice', slice['slice_id'], peer)
269         self.api.plshell.DeleteSliceFromNodes(self.api.plauth, slicename, slice['node_ids'])
270         if peer:
271             self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
272         return 1
273
274     def delete_slice_smgr(self, hrn):
275         credential = self.api.getCredential()
276         caller_cred = self.caller_cred
277         aggregates = Aggregates(self.api)
278         for aggregate in aggregates:
279             success = False
280             # request hash is optional so lets try the call without it
281             try:
282                 request_hash=None       
283                 aggregates[aggregate].delete_slice(credential, hrn, request_hash, caller_cred)
284                 success = True
285             except:
286                 print >> log, "%s" % (traceback.format_exc())
287                 print >> log, "Error calling list nodes at aggregate %s" % aggregate
288             
289             # try sending the request hash if the previous call failed 
290             if not success:
291                 try:
292                     arg_list = [credential, hrn]
293                     request_hash = self.api.key.compute_hash(arg_list)
294                     aggregates[aggregate].delete_slice(credential, hrn, request_hash, caller_cred)
295                     success = True
296                 except:
297                     print >> log, "%s" % (traceback.format_exc())
298                     print >> log, "Error calling list nodes at aggregate %s" % aggregate
299                         
300     def create_slice(self, hrn, rspec):
301         
302         # check our slice policy before we procede
303         whitelist = self.policy['slice_whitelist']     
304         blacklist = self.policy['slice_blacklist']
305        
306         if whitelist and hrn not in whitelist or \
307            blacklist and hrn in blacklist:
308             policy_file = self.policy.policy_file
309             print >> log, "Slice %(hrn)s not allowed by policy %(policy_file)s" % locals()
310             return 1
311
312         if self.api.interface in ['aggregate']:     
313             self.create_slice_aggregate(hrn, rspec)
314         elif self.api.interface in ['slicemgr']:
315             self.create_slice_smgr(hrn, rspec)
316
317     def verify_site(self, registry, credential, slice_hrn, peer, sfa_peer):
318         authority = get_authority(slice_hrn)
319         try:
320             site_records = registry.resolve(credential, authority)
321         except:
322             arg_list = [credential, authority]
323             request_hash = self.api.key.compute_hash(arg_list)
324             site_records = registry.resolve(credential, authority, request_hash)
325             
326         site = {}
327         for site_record in site_records:
328             if site_record['type'] == 'authority':
329                 site = site_record
330         if not site:
331             raise RecordNotFound(authority)
332         remote_site_id = site.pop('site_id')    
333                 
334         login_base = get_leaf(authority)
335         sites = self.api.plshell.GetSites(self.api.plauth, login_base)
336         if not sites:
337             site_id = self.api.plshell.AddSite(self.api.plauth, site)
338             if peer:
339                 self.api.plshell.BindObjectToPeer(self.api.plauth, 'site', site_id, peer, remote_site_id)   
340             # mark this site as an sfa peer record
341             if sfa_peer:
342                 peer_dict = {'type': 'authority', 'hrn': authority, 'peer_authority': sfa_peer, 'pointer': site_id}
343                 try:
344                     registry.register_peer_object(credential, peer_dict)
345                 except:
346                     arg_list = [credential]
347                     request_hash = self.api.key.compute_hash(arg_list) 
348                     registry.register_peer_object(credential, peer_dict, request_hash)
349         else:
350             site_id = sites[0]['site_id']
351             remote_site_id = sites[0]['peer_site_id']
352
353
354         return (site_id, remote_site_id) 
355
356     def verify_slice(self, registry, credential, slice_hrn, site_id, remote_site_id, peer, sfa_peer):
357         slice = {}
358         slice_record = None
359         authority = get_authority(slice_hrn)
360         try:
361             slice_records = registry.resolve(credential, slice_hrn)
362         except:    
363             arg_list = [credential, slice_hrn]
364             request_hash = self.api.key.compute_hash(arg_list)
365             slice_records = registry.resolve(credential, slice_hrn, request_hash)
366
367         for record in slice_records:
368             if record['type'] in ['slice']:
369                 slice_record = record
370         if not slice_record:
371             raise RecordNotFound(hrn)
372         slicename = hrn_to_pl_slicename(slice_hrn)
373         parts = slicename.split("_")
374         login_base = parts[0]
375         slices = self.api.plshell.GetSlices(self.api.plauth, [slicename], ['slice_id', 'node_ids', 'site_id']) 
376         if not slices:
377             slice_fields = {}
378             slice_keys = ['name', 'url', 'description']
379             for key in slice_keys:
380                 if key in slice_record and slice_record[key]:
381                     slice_fields[key] = slice_record[key]
382
383             # add the slice  
384             slice_id = self.api.plshell.AddSlice(self.api.plauth, slice_fields)
385             slice = slice_fields
386             slice['slice_id'] = slice_id
387
388             # mark this slice as an sfa peer record
389             if sfa_peer:
390                 peer_dict = {'type': 'slice', 'hrn': slice_hrn, 'peer_authority': sfa_peer, 'pointer': slice_id}
391                 try:
392                     registry.register_peer_object(credential, peer_dict)
393                 except:
394                     arg_list = [credential]
395                     request_hash = self.api.key.compute_hash(arg_list) 
396                     registry.register_peer_object(credential, peer_dict, request_hash)
397
398             #this belongs to a peer
399             if peer:
400                 self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice_id, peer, slice_record['pointer'])
401             slice['node_ids'] = []
402         else:
403             slice = slices[0]
404             slice_id = slice['slice_id']
405             site_id = slice['site_id']
406
407         slice['peer_slice_id'] = slice_record['pointer']
408         self.verify_persons(registry, credential, slice_record, site_id, remote_site_id, peer, sfa_peer)
409     
410         return slice        
411
412     def verify_persons(self, registry, credential, slice_record, site_id, remote_site_id, peer, sfa_peer):
413         # get the list of valid slice users from the registry and make 
414         # sure they are added to the slice 
415         slicename = hrn_to_pl_slicename(slice_record['hrn'])
416         researchers = slice_record.get('researcher', [])
417         for researcher in researchers:
418             person_record = {}
419             try:
420                 person_records = registry.resolve(credential, researcher)
421             except:
422                 arg_list = [credential, researcher]
423                 request_hash = self.api.key.compute_hash(arg_list) 
424                 person_records = registry.resolve(credential, researcher, request_hash)
425             for record in person_records:
426                 if record['type'] in ['user']:
427                     person_record = record
428             if not person_record:
429                 pass
430             person_dict = person_record
431             local_person=False
432             if peer:
433                 peer_id = self.api.plshell.GetPeers(self.api.plauth, {'shortname': peer}, ['peer_id'])[0]['peer_id']
434                 persons = self.api.plshell.GetPersons(self.api.plauth, {'email': [person_dict['email']], 'peer_id': peer_id}, ['person_id', 'key_ids'])
435                 if not persons:
436                     persons = self.api.plshell.GetPersons(self.api.plauth, [person_dict['email']], ['person_id', 'key_ids'])
437                     if persons:
438                        local_person=True
439
440             else:
441                 persons = self.api.plshell.GetPersons(self.api.plauth, [person_dict['email']], ['person_id', 'key_ids'])   
442         
443             if not persons:
444                 person_id=self.api.plshell.AddPerson(self.api.plauth, person_dict)
445                 self.api.plshell.UpdatePerson(self.api.plauth, person_id, {'enabled' : True})
446                 
447                 # mark this person as an sfa peer record
448                 if sfa_peer:
449                     peer_dict = {'type': 'user', 'hrn': researcher, 'peer_authority': sfa_peer, 'pointer': person_id}
450                     try:
451                         registry.register_peer_object(credential, peer_dict)
452                     except:
453                         arg_list = [credential]
454                         request_hash = self.api.key.compute_hash(arg_list) 
455                         registry.register_peer_object(credential, peer_dict, request_hash)
456
457                 if peer:
458                     self.api.plshell.BindObjectToPeer(self.api.plauth, 'person', person_id, peer, person_dict['pointer'])
459                 key_ids = []
460             else:
461                 person_id = persons[0]['person_id']
462                 key_ids = persons[0]['key_ids']
463
464
465             # if this is a peer person, we must unbind them from the peer or PLCAPI will throw
466             # an error
467             if peer:
468                 self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'person', person_id, peer)
469                 self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'site', site_id,  peer)
470
471             self.api.plshell.AddPersonToSlice(self.api.plauth, person_dict['email'], slicename)
472             self.api.plshell.AddPersonToSite(self.api.plauth, person_dict['email'], site_id)
473             if peer and not local_person:
474                 self.api.plshell.BindObjectToPeer(self.api.plauth, 'person', person_id, peer, person_dict['pointer'])
475             if peer:
476                 self.api.plshell.BindObjectToPeer(self.api.plauth, 'site', site_id, peer, remote_site_id)
477             
478             self.verify_keys(registry, credential, person_dict, key_ids, person_id, peer, local_person)
479
480     def verify_keys(self, registry, credential, person_dict, key_ids, person_id,  peer, local_person):
481         keylist = self.api.plshell.GetKeys(self.api.plauth, key_ids, ['key'])
482         keys = [key['key'] for key in keylist]
483         
484         #add keys that arent already there
485         key_ids = person_dict['key_ids']
486         for personkey in person_dict['keys']:
487             if personkey not in keys:
488                 key = {'key_type': 'ssh', 'key': personkey}
489                 if peer:
490                     self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'person', person_id, peer)
491                 key_id = self.api.plshell.AddPersonKey(self.api.plauth, person_dict['email'], key)
492                 if peer and not local_person:
493                     self.api.plshell.BindObjectToPeer(self.api.plauth, 'person', person_id, peer, person_dict['pointer'])
494                 if peer:
495                     try: self.api.plshell.BindObjectToPeer(self.api.plauth, 'key', key_id, peer, key_ids.pop(0))
496
497                     except: pass   
498
499     def create_slice_aggregate(self, hrn, rspec):
500
501         # Determine if this is a peer slice
502         peer = self.get_peer(hrn)
503         sfa_peer = self.get_sfa_peer(hrn)
504
505         spec = RSpec(rspec)
506         # Get the slice record from sfa
507         slicename = hrn_to_pl_slicename(hrn) 
508         slice = {}
509         slice_record = None
510         registries = Registries(self.api)
511         registry = registries[self.api.hrn]
512         credential = self.api.getCredential()
513
514         site_id, remote_site_id = self.verify_site(registry, credential, hrn, peer, sfa_peer)
515         slice = self.verify_slice(registry, credential, hrn, site_id, remote_site_id, peer, sfa_peer)
516
517         # find out where this slice is currently running
518         nodelist = self.api.plshell.GetNodes(self.api.plauth, slice['node_ids'], ['hostname'])
519         hostnames = [node['hostname'] for node in nodelist]
520
521         # get netspec details
522         nodespecs = spec.getDictsByTagName('NodeSpec')
523
524         # dict in which to store slice attributes to set for the nodes
525         nodes = {}
526         for nodespec in nodespecs:
527             if isinstance(nodespec['name'], list):
528                 for nodename in nodespec['name']:
529                     nodes[nodename] = {}
530                     for k in nodespec.keys():
531                         rspec_attribute_value = nodespec[k]
532                         if (self.rspec_to_slice_tag.has_key(k)):
533                             slice_tag_name = self.rspec_to_slice_tag[k]
534                             nodes[nodename][slice_tag_name] = rspec_attribute_value
535             elif isinstance(nodespec['name'], StringTypes):
536                 nodename = nodespec['name']
537                 nodes[nodename] = {}
538                 for k in nodespec.keys():
539                     rspec_attribute_value = nodespec[k]
540                     if (self.rspec_to_slice_tag.has_key(k)):
541                         slice_tag_name = self.rspec_to_slice_tag[k]
542                         nodes[nodename][slice_tag_name] = rspec_attribute_value
543
544                 for k in nodespec.keys():
545                     rspec_attribute_value = nodespec[k]
546                     if (self.rspec_to_slice_tag.has_key(k)):
547                         slice_tag_name = self.rspec_to_slice_tag[k]
548                         nodes[nodename][slice_tag_name] = rspec_attribute_value
549
550         node_names = nodes.keys()
551         # remove nodes not in rspec
552         deleted_nodes = list(set(hostnames).difference(node_names))
553         # add nodes from rspec
554         added_nodes = list(set(node_names).difference(hostnames))
555
556         if peer:
557             self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'slice', slice['slice_id'], peer)
558
559         self.api.plshell.AddSliceToNodes(self.api.plauth, slicename, added_nodes) 
560
561         # Add recognized slice tags
562         for node_name in node_names:
563             node = nodes[node_name]
564             for slice_tag in node.keys():
565                 value = node[slice_tag]
566                 if (isinstance(value, list)):
567                     value = value[0]
568
569                 self.api.plshell.AddSliceTag(self.api.plauth, slicename, slice_tag, value, node_name)
570
571         self.api.plshell.DeleteSliceFromNodes(self.api.plauth, slicename, deleted_nodes)
572         if peer:
573             self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
574
575         return 1
576
577     def create_slice_smgr(self, hrn, rspec):
578         spec = RSpec()
579         tempspec = RSpec()
580         spec.parseString(rspec)
581         slicename = hrn_to_pl_slicename(hrn)
582         specDict = spec.toDict()
583         if specDict.has_key('RSpec'): specDict = specDict['RSpec']
584         if specDict.has_key('start_time'): start_time = specDict['start_time']
585         else: start_time = 0
586         if specDict.has_key('end_time'): end_time = specDict['end_time']
587         else: end_time = 0
588
589         rspecs = {}
590         aggregates = Aggregates(self.api)
591         credential = self.api.getCredential()
592
593         # split the netspecs into individual rspecs
594         netspecs = spec.getDictsByTagName('NetSpec')
595         for netspec in netspecs:
596             net_hrn = netspec['name']
597             resources = {'start_time': start_time, 'end_time': end_time, 'networks': netspec}
598             resourceDict = {'RSpec': resources}
599             tempspec.parseDict(resourceDict)
600             rspecs[net_hrn] = tempspec.toxml()
601
602         # send each rspec to the appropriate aggregate/sm
603         caller_cred = self.caller_cred 
604         for net_hrn in rspecs:
605             try:
606                 # if we are directly connected to the aggregate then we can just send them the rspec
607                 # if not, then we may be connected to an sm thats connected to the aggregate
608                 if net_hrn in aggregates:
609                     # send the whloe rspec to the local aggregate
610                     if net_hrn in [self.api.hrn]:
611                         try:
612                             request_hash = None
613                             aggregates[net_hrn].create_slice(credential, hrn, rspec, request_hash, caller_cred)
614                         except:
615                             arg_list = [credential,hrn,rspec]
616                             request_hash = self.api.key.compute_hash(arg_list)
617                             aggregates[net_hrn].create_slice(credential, hrn, rspec, request_hash, caller_cred)
618                     else:
619                         try:
620                             request_hash = None
621                             aggregates[net_hrn].create_slice(credential, hrn, rspecs[net_hrn], request_hash, caller_cred)
622                         except:
623                             arg_list = [credential,hrn,rspecs[net_hrn]]
624                             request_hash = self.api.key.compute_hash(arg_list)
625                             aggregates[net_hrn].create_slice(credential, hrn, rspecs[net_hrn], request_hash, caller_cred)
626                 else:
627                     # lets forward this rspec to a sm that knows about the network
628                     arg_list = [credential, net_hrn]
629                     request_hash = self.api.compute_hash(arg_list)    
630                     for aggregate in aggregates:
631                         try:
632                             network_found = aggregates[aggregate].get_aggregates(credential, net_hrn)
633                         except:
634                             network_found = aggregates[aggregate].get_aggregates(credential, net_hrn, request_hash)
635                         if network_networks:
636                             try:
637                                 request_hash = None
638                                 aggregates[aggregate].create_slice(credential, hrn, rspecs[net_hrn], request_hash, caller_cred)
639                             except:
640                                 arg_list = [credential, hrn, rspecs[net_hrn]]
641                                 request_hash = self.api.key.compute_hash(arg_list) 
642                                 aggregates[aggregate].create_slice(credential, hrn, rspecs[net_hrn], request_hash, caller_cred)
643                      
644             except:
645                 print >> log, "Error creating slice %(hrn)s at aggregate %(net_hrn)s" % locals()
646                 traceback.print_exc()
647         return 1
648
649
650     def start_slice(self, hrn):
651         if self.api.interface in ['aggregate']:
652             self.start_slice_aggregate(hrn)
653         elif self.api.interface in ['slicemgr']:
654             self.start_slice_smgr(hrn)
655
656     def start_slice_aggregate(self, hrn):
657         slicename = hrn_to_pl_slicename(hrn)
658         slices = self.api.plshell.GetSlices(self.api.plauth, {'name': slicename}, ['slice_id'])
659         if not slices:
660             raise RecordNotFound(hrn)
661         slice_id = slices[0]
662         attributes = self.api.plshell.GetSliceAttributes(self.api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
663         attribute_id = attreibutes[0]['slice_attribute_id']
664         self.api.plshell.UpdateSliceAttribute(self.api.plauth, attribute_id, "1" )
665         return 1
666
667     def start_slice_smgr(self, hrn):
668         credential = self.api.getCredential()
669         aggregates = Aggregates(self.api)
670         for aggregate in aggregates:
671             aggregates[aggregate].start_slice(credential, hrn)
672         return 1
673
674
675     def stop_slice(self, hrn):
676         if self.api.interface in ['aggregate']:
677             self.stop_slice_aggregate(hrn)
678         elif self.api.interface in ['slicemgr']:
679             self.stop_slice_smgr(hrn)
680
681     def stop_slice_aggregate(self, hrn):
682         slicename = hrn_to_pl_slicename(hrn)
683         slices = self.api.plshell.GetSlices(self.api.plauth, {'name': slicename}, ['slice_id'])
684         if not slices:
685             raise RecordNotFound(hrn)
686         slice_id = slices[0]['slice_id']
687         attributes = self.api.plshell.GetSliceAttributes(self.api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
688         attribute_id = attributes[0]['slice_attribute_id']
689         self.api.plshell.UpdateSliceAttribute(self.api.plauth, attribute_id, "0")
690         return 1
691
692     def stop_slice_smgr(self, hrn):
693         credential = self.api.getCredential()
694         aggregates = Aggregates(self.api)
695         arg_list = [credential, hrn]
696         request_hash = self.api.key.compute_hash(arg_list)
697         for aggregate in aggregates:
698             try:
699                 aggregates[aggregate].stop_slice(credential, hrn)
700             except:  
701                 aggregates[aggregate].stop_slice(credential, hrn, request_hash)
702