passing the hrn of the initial caller instead of its credentail
[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, origin_hrn=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.origin_hrn=origin_hrn
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                 request_hash=None
218                 slices = aggregates[aggregate].get_slices(credential, request_hash)
219                 slice_hrns.extend(slices)
220                 success = True
221             except:
222                 print >> log, "%s" % (traceback.format_exc())
223                 print >> log, "Error calling slices at aggregate %(aggregate)s" % locals()
224
225             # try sending the request hash if the previous call failed 
226             if not success:
227                 arg_list = [credential]
228                 request_hash = self.api.key.compute_hash(arg_list)
229                 try:
230                     slices = aggregates[aggregate].get_slices(credential, request_hash)
231                     slice_hrns.extend(slices)
232                     success = True
233                 except:
234                     print >> log, "%s" % (traceback.format_exc())
235                     print >> log, "Error calling slices at aggregate %(aggregate)s" % locals()
236
237         # update timestamp and threshold
238         timestamp = datetime.datetime.now()
239         hr_timestamp = timestamp.strftime(self.api.time_format)
240         delta = datetime.timedelta(hours=self.ttl)
241         threshold = timestamp + delta
242         hr_threshold = threshold.strftime(self.api.time_format)
243
244         slice_details = {'hrn': slice_hrns,
245                          'timestamp': hr_timestamp,
246                          'threshold': hr_threshold
247                         }
248         self.update(slice_details)
249         self.write()
250
251
252     def delete_slice(self, hrn):
253         if self.api.interface in ['aggregate']:
254             self.delete_slice_aggregate(hrn)
255         elif self.api.interface in ['slicemgr']:
256             self.delete_slice_smgr(hrn)
257         
258     def delete_slice_aggregate(self, hrn):
259
260         slicename = hrn_to_pl_slicename(hrn)
261         slices = self.api.plshell.GetSlices(self.api.plauth, {'name': slicename})
262         if not slices:
263             return 1        
264         slice = slices[0]
265
266         # determine if this is a peer slice
267         peer = self.get_peer(hrn)
268         if peer:
269             self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'slice', slice['slice_id'], peer)
270         self.api.plshell.DeleteSliceFromNodes(self.api.plauth, slicename, slice['node_ids'])
271         if peer:
272             self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
273         return 1
274
275     def delete_slice_smgr(self, hrn):
276         credential = self.api.getCredential()
277         origin_hrn = self.origin_hrn
278         aggregates = Aggregates(self.api)
279         for aggregate in aggregates:
280             success = False
281             # request hash is optional so lets try the call without it
282             try:
283                 request_hash=None       
284                 aggregates[aggregate].delete_slice(credential, hrn, request_hash, origin_hrn)
285                 success = True
286             except:
287                 print >> log, "%s" % (traceback.format_exc())
288                 print >> log, "Error calling list nodes at aggregate %s" % aggregate
289             
290             # try sending the request hash if the previous call failed 
291             if not success:
292                 try:
293                     arg_list = [credential, hrn]
294                     request_hash = self.api.key.compute_hash(arg_list)
295                     aggregates[aggregate].delete_slice(credential, hrn, request_hash, origin_hrn)
296                     success = True
297                 except:
298                     print >> log, "%s" % (traceback.format_exc())
299                     print >> log, "Error calling list nodes at aggregate %s" % aggregate
300                         
301     def create_slice(self, hrn, rspec):
302         
303         # check our slice policy before we procede
304         whitelist = self.policy['slice_whitelist']     
305         blacklist = self.policy['slice_blacklist']
306        
307         if whitelist and hrn not in whitelist or \
308            blacklist and hrn in blacklist:
309             policy_file = self.policy.policy_file
310             print >> log, "Slice %(hrn)s not allowed by policy %(policy_file)s" % locals()
311             return 1
312
313         if self.api.interface in ['aggregate']:     
314             self.create_slice_aggregate(hrn, rspec)
315         elif self.api.interface in ['slicemgr']:
316             self.create_slice_smgr(hrn, rspec)
317
318     def verify_site(self, registry, credential, slice_hrn, peer, sfa_peer):
319         authority = get_authority(slice_hrn)
320         try:
321             site_records = registry.resolve(credential, authority)
322         except:
323             arg_list = [credential, authority]
324             request_hash = self.api.key.compute_hash(arg_list)
325             site_records = registry.resolve(credential, authority, request_hash)
326             
327         site = {}
328         for site_record in site_records:
329             if site_record['type'] == 'authority':
330                 site = site_record
331         if not site:
332             raise RecordNotFound(authority)
333         remote_site_id = site.pop('site_id')    
334                 
335         login_base = get_leaf(authority)
336         sites = self.api.plshell.GetSites(self.api.plauth, login_base)
337         if not sites:
338             site_id = self.api.plshell.AddSite(self.api.plauth, site)
339             if peer:
340                 self.api.plshell.BindObjectToPeer(self.api.plauth, 'site', site_id, peer, remote_site_id)   
341             # mark this site as an sfa peer record
342             if sfa_peer:
343                 peer_dict = {'type': 'authority', 'hrn': authority, 'peer_authority': sfa_peer, 'pointer': site_id}
344                 try:
345                     registry.register_peer_object(credential, peer_dict)
346                 except:
347                     arg_list = [credential]
348                     request_hash = self.api.key.compute_hash(arg_list) 
349                     registry.register_peer_object(credential, peer_dict, request_hash)
350         else:
351             site_id = sites[0]['site_id']
352             remote_site_id = sites[0]['peer_site_id']
353
354
355         return (site_id, remote_site_id) 
356
357     def verify_slice(self, registry, credential, slice_hrn, site_id, remote_site_id, peer, sfa_peer):
358         slice = {}
359         slice_record = None
360         authority = get_authority(slice_hrn)
361         try:
362             slice_records = registry.resolve(credential, slice_hrn)
363         except:    
364             arg_list = [credential, slice_hrn]
365             request_hash = self.api.key.compute_hash(arg_list)
366             slice_records = registry.resolve(credential, slice_hrn, request_hash)
367
368         for record in slice_records:
369             if record['type'] in ['slice']:
370                 slice_record = record
371         if not slice_record:
372             raise RecordNotFound(hrn)
373         slicename = hrn_to_pl_slicename(slice_hrn)
374         parts = slicename.split("_")
375         login_base = parts[0]
376         slices = self.api.plshell.GetSlices(self.api.plauth, [slicename], ['slice_id', 'node_ids', 'site_id']) 
377         if not slices:
378             slice_fields = {}
379             slice_keys = ['name', 'url', 'description']
380             for key in slice_keys:
381                 if key in slice_record and slice_record[key]:
382                     slice_fields[key] = slice_record[key]
383
384             # add the slice  
385             slice_id = self.api.plshell.AddSlice(self.api.plauth, slice_fields)
386             slice = slice_fields
387             slice['slice_id'] = slice_id
388
389             # mark this slice as an sfa peer record
390             if sfa_peer:
391                 peer_dict = {'type': 'slice', 'hrn': slice_hrn, 'peer_authority': sfa_peer, 'pointer': slice_id}
392                 try:
393                     registry.register_peer_object(credential, peer_dict)
394                 except:
395                     arg_list = [credential]
396                     request_hash = self.api.key.compute_hash(arg_list) 
397                     registry.register_peer_object(credential, peer_dict, request_hash)
398
399             #this belongs to a peer
400             if peer:
401                 self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice_id, peer, slice_record['pointer'])
402             slice['node_ids'] = []
403         else:
404             slice = slices[0]
405             slice_id = slice['slice_id']
406             site_id = slice['site_id']
407
408         slice['peer_slice_id'] = slice_record['pointer']
409         self.verify_persons(registry, credential, slice_record, site_id, remote_site_id, peer, sfa_peer)
410     
411         return slice        
412
413     def verify_persons(self, registry, credential, slice_record, site_id, remote_site_id, peer, sfa_peer):
414         # get the list of valid slice users from the registry and make 
415         # sure they are added to the slice 
416         slicename = hrn_to_pl_slicename(slice_record['hrn'])
417         researchers = slice_record.get('researcher', [])
418         for researcher in researchers:
419             person_record = {}
420             try:
421                 person_records = registry.resolve(credential, researcher)
422             except:
423                 arg_list = [credential, researcher]
424                 request_hash = self.api.key.compute_hash(arg_list) 
425                 person_records = registry.resolve(credential, researcher, request_hash)
426             for record in person_records:
427                 if record['type'] in ['user']:
428                     person_record = record
429             if not person_record:
430                 pass
431             person_dict = person_record
432             local_person=False
433             if peer:
434                 peer_id = self.api.plshell.GetPeers(self.api.plauth, {'shortname': peer}, ['peer_id'])[0]['peer_id']
435                 persons = self.api.plshell.GetPersons(self.api.plauth, {'email': [person_dict['email']], 'peer_id': peer_id}, ['person_id', 'key_ids'])
436                 if not persons:
437                     persons = self.api.plshell.GetPersons(self.api.plauth, [person_dict['email']], ['person_id', 'key_ids'])
438                     if persons:
439                        local_person=True
440
441             else:
442                 persons = self.api.plshell.GetPersons(self.api.plauth, [person_dict['email']], ['person_id', 'key_ids'])   
443         
444             if not persons:
445                 person_id=self.api.plshell.AddPerson(self.api.plauth, person_dict)
446                 self.api.plshell.UpdatePerson(self.api.plauth, person_id, {'enabled' : True})
447                 
448                 # mark this person as an sfa peer record
449                 if sfa_peer:
450                     peer_dict = {'type': 'user', 'hrn': researcher, 'peer_authority': sfa_peer, 'pointer': person_id}
451                     try:
452                         registry.register_peer_object(credential, peer_dict)
453                     except:
454                         arg_list = [credential]
455                         request_hash = self.api.key.compute_hash(arg_list) 
456                         registry.register_peer_object(credential, peer_dict, request_hash)
457
458                 if peer:
459                     self.api.plshell.BindObjectToPeer(self.api.plauth, 'person', person_id, peer, person_dict['pointer'])
460                 key_ids = []
461             else:
462                 person_id = persons[0]['person_id']
463                 key_ids = persons[0]['key_ids']
464
465
466             # if this is a peer person, we must unbind them from the peer or PLCAPI will throw
467             # an error
468             if peer:
469                 self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'person', person_id, peer)
470                 self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'site', site_id,  peer)
471
472             self.api.plshell.AddPersonToSlice(self.api.plauth, person_dict['email'], slicename)
473             self.api.plshell.AddPersonToSite(self.api.plauth, person_dict['email'], site_id)
474             if peer and not local_person:
475                 self.api.plshell.BindObjectToPeer(self.api.plauth, 'person', person_id, peer, person_dict['pointer'])
476             if peer:
477                 self.api.plshell.BindObjectToPeer(self.api.plauth, 'site', site_id, peer, remote_site_id)
478             
479             self.verify_keys(registry, credential, person_dict, key_ids, person_id, peer, local_person)
480
481     def verify_keys(self, registry, credential, person_dict, key_ids, person_id,  peer, local_person):
482         keylist = self.api.plshell.GetKeys(self.api.plauth, key_ids, ['key'])
483         keys = [key['key'] for key in keylist]
484         
485         #add keys that arent already there
486         key_ids = person_dict['key_ids']
487         for personkey in person_dict['keys']:
488             if personkey not in keys:
489                 key = {'key_type': 'ssh', 'key': personkey}
490                 if peer:
491                     self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'person', person_id, peer)
492                 key_id = self.api.plshell.AddPersonKey(self.api.plauth, person_dict['email'], key)
493                 if peer and not local_person:
494                     self.api.plshell.BindObjectToPeer(self.api.plauth, 'person', person_id, peer, person_dict['pointer'])
495                 if peer:
496                     try: self.api.plshell.BindObjectToPeer(self.api.plauth, 'key', key_id, peer, key_ids.pop(0))
497
498                     except: pass   
499
500     def create_slice_aggregate(self, hrn, rspec):
501
502         # Determine if this is a peer slice
503         peer = self.get_peer(hrn)
504         sfa_peer = self.get_sfa_peer(hrn)
505
506         spec = RSpec(rspec)
507         # Get the slice record from sfa
508         slicename = hrn_to_pl_slicename(hrn) 
509         slice = {}
510         slice_record = None
511         registries = Registries(self.api)
512         registry = registries[self.api.hrn]
513         credential = self.api.getCredential()
514
515         site_id, remote_site_id = self.verify_site(registry, credential, hrn, peer, sfa_peer)
516         slice = self.verify_slice(registry, credential, hrn, site_id, remote_site_id, peer, sfa_peer)
517
518         # find out where this slice is currently running
519         nodelist = self.api.plshell.GetNodes(self.api.plauth, slice['node_ids'], ['hostname'])
520         hostnames = [node['hostname'] for node in nodelist]
521
522         # get netspec details
523         nodespecs = spec.getDictsByTagName('NodeSpec')
524
525         # dict in which to store slice attributes to set for the nodes
526         nodes = {}
527         for nodespec in nodespecs:
528             if isinstance(nodespec['name'], list):
529                 for nodename in nodespec['name']:
530                     nodes[nodename] = {}
531                     for k in nodespec.keys():
532                         rspec_attribute_value = nodespec[k]
533                         if (self.rspec_to_slice_tag.has_key(k)):
534                             slice_tag_name = self.rspec_to_slice_tag[k]
535                             nodes[nodename][slice_tag_name] = rspec_attribute_value
536             elif isinstance(nodespec['name'], StringTypes):
537                 nodename = nodespec['name']
538                 nodes[nodename] = {}
539                 for k in nodespec.keys():
540                     rspec_attribute_value = nodespec[k]
541                     if (self.rspec_to_slice_tag.has_key(k)):
542                         slice_tag_name = self.rspec_to_slice_tag[k]
543                         nodes[nodename][slice_tag_name] = rspec_attribute_value
544
545                 for k in nodespec.keys():
546                     rspec_attribute_value = nodespec[k]
547                     if (self.rspec_to_slice_tag.has_key(k)):
548                         slice_tag_name = self.rspec_to_slice_tag[k]
549                         nodes[nodename][slice_tag_name] = rspec_attribute_value
550
551         node_names = nodes.keys()
552         # remove nodes not in rspec
553         deleted_nodes = list(set(hostnames).difference(node_names))
554         # add nodes from rspec
555         added_nodes = list(set(node_names).difference(hostnames))
556
557         if peer:
558             self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'slice', slice['slice_id'], peer)
559
560         self.api.plshell.AddSliceToNodes(self.api.plauth, slicename, added_nodes) 
561
562         # Add recognized slice tags
563         for node_name in node_names:
564             node = nodes[node_name]
565             for slice_tag in node.keys():
566                 value = node[slice_tag]
567                 if (isinstance(value, list)):
568                     value = value[0]
569
570                 self.api.plshell.AddSliceTag(self.api.plauth, slicename, slice_tag, value, node_name)
571
572         self.api.plshell.DeleteSliceFromNodes(self.api.plauth, slicename, deleted_nodes)
573         if peer:
574             self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
575
576         return 1
577
578     def create_slice_smgr(self, hrn, rspec):
579         spec = RSpec()
580         tempspec = RSpec()
581         spec.parseString(rspec)
582         slicename = hrn_to_pl_slicename(hrn)
583         specDict = spec.toDict()
584         if specDict.has_key('RSpec'): specDict = specDict['RSpec']
585         if specDict.has_key('start_time'): start_time = specDict['start_time']
586         else: start_time = 0
587         if specDict.has_key('end_time'): end_time = specDict['end_time']
588         else: end_time = 0
589
590         rspecs = {}
591         aggregates = Aggregates(self.api)
592         credential = self.api.getCredential()
593
594         # split the netspecs into individual rspecs
595         netspecs = spec.getDictsByTagName('NetSpec')
596         for netspec in netspecs:
597             net_hrn = netspec['name']
598             resources = {'start_time': start_time, 'end_time': end_time, 'networks': netspec}
599             resourceDict = {'RSpec': resources}
600             tempspec.parseDict(resourceDict)
601             rspecs[net_hrn] = tempspec.toxml()
602
603         # send each rspec to the appropriate aggregate/sm
604         origin_hrn = self.origin_hrn
605         for net_hrn in rspecs:
606             try:
607                 # if we are directly connected to the aggregate then we can just send them the rspec
608                 # if not, then we may be connected to an sm thats connected to the aggregate
609                 if net_hrn in aggregates:
610                     # send the whloe rspec to the local aggregate
611                     if net_hrn in [self.api.hrn]:
612                         try:
613                             request_hash = None
614                             aggregates[net_hrn].create_slice(credential, hrn, rspec, request_hash, origin_hrn)
615                         except:
616                             arg_list = [credential,hrn,rspec]
617                             request_hash = self.api.key.compute_hash(arg_list)
618                             aggregates[net_hrn].create_slice(credential, hrn, rspec, request_hash, origin_hrn)
619                     else:
620                         try:
621                             request_hash = None
622                             aggregates[net_hrn].create_slice(credential, hrn, rspecs[net_hrn], request_hash, origin_hrn)
623                         except:
624                             arg_list = [credential,hrn,rspecs[net_hrn]]
625                             request_hash = self.api.key.compute_hash(arg_list)
626                             aggregates[net_hrn].create_slice(credential, hrn, rspecs[net_hrn], request_hash, origin_hrn)
627                 else:
628                     # lets forward this rspec to a sm that knows about the network
629                     arg_list = [credential, net_hrn]
630                     request_hash = self.api.compute_hash(arg_list)    
631                     for aggregate in aggregates:
632                         try:
633                             network_found = aggregates[aggregate].get_aggregates(credential, net_hrn)
634                         except:
635                             network_found = aggregates[aggregate].get_aggregates(credential, net_hrn, request_hash)
636                         if network_networks:
637                             try:
638                                 request_hash = None
639                                 aggregates[aggregate].create_slice(credential, hrn, rspecs[net_hrn], request_hash, origin_hrn)
640                             except:
641                                 arg_list = [credential, hrn, rspecs[net_hrn]]
642                                 request_hash = self.api.key.compute_hash(arg_list) 
643                                 aggregates[aggregate].create_slice(credential, hrn, rspecs[net_hrn], request_hash, origin_hrn)
644                      
645             except:
646                 print >> log, "Error creating slice %(hrn)s at aggregate %(net_hrn)s" % locals()
647                 traceback.print_exc()
648         return 1
649
650
651     def start_slice(self, hrn):
652         if self.api.interface in ['aggregate']:
653             self.start_slice_aggregate(hrn)
654         elif self.api.interface in ['slicemgr']:
655             self.start_slice_smgr(hrn)
656
657     def start_slice_aggregate(self, hrn):
658         slicename = hrn_to_pl_slicename(hrn)
659         slices = self.api.plshell.GetSlices(self.api.plauth, {'name': slicename}, ['slice_id'])
660         if not slices:
661             raise RecordNotFound(hrn)
662         slice_id = slices[0]
663         attributes = self.api.plshell.GetSliceAttributes(self.api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
664         attribute_id = attreibutes[0]['slice_attribute_id']
665         self.api.plshell.UpdateSliceAttribute(self.api.plauth, attribute_id, "1" )
666         return 1
667
668     def start_slice_smgr(self, hrn):
669         credential = self.api.getCredential()
670         aggregates = Aggregates(self.api)
671         for aggregate in aggregates:
672             aggregates[aggregate].start_slice(credential, hrn)
673         return 1
674
675
676     def stop_slice(self, hrn):
677         if self.api.interface in ['aggregate']:
678             self.stop_slice_aggregate(hrn)
679         elif self.api.interface in ['slicemgr']:
680             self.stop_slice_smgr(hrn)
681
682     def stop_slice_aggregate(self, hrn):
683         slicename = hrn_to_pl_slicename(hrn)
684         slices = self.api.plshell.GetSlices(self.api.plauth, {'name': slicename}, ['slice_id'])
685         if not slices:
686             raise RecordNotFound(hrn)
687         slice_id = slices[0]['slice_id']
688         attributes = self.api.plshell.GetSliceAttributes(self.api.plauth, {'slice_id': slice_id, 'name': 'enabled'}, ['slice_attribute_id'])
689         attribute_id = attributes[0]['slice_attribute_id']
690         self.api.plshell.UpdateSliceAttribute(self.api.plauth, attribute_id, "0")
691         return 1
692
693     def stop_slice_smgr(self, hrn):
694         credential = self.api.getCredential()
695         aggregates = Aggregates(self.api)
696         arg_list = [credential, hrn]
697         request_hash = self.api.key.compute_hash(arg_list)
698         for aggregate in aggregates:
699             try:
700                 aggregates[aggregate].stop_slice(credential, hrn)
701             except:  
702                 aggregates[aggregate].stop_slice(credential, hrn, request_hash)
703