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
24 class Slices(SimpleStorage):
26 rspec_to_slice_tag = {'max_rate':'net_max_rate'}
28 def __init__(self, api, ttl = .5, caller_cred=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)
39 self.caller_cred=caller_cred
41 def get_slivers(self, hrn, node=None):
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)
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
53 all_slice_tag_ids = set()
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'])
62 for person in all_persons_list:
63 all_persons[person['person_id']] = person
65 # Build up list of keys
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'])
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)
78 for slice_tag in all_slice_tags_list:
79 all_slice_tags[slice_tag['slice_tag_id']] = slice_tag
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']:
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'],
95 # All (per-node and global) attributes for this slice
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 = []
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']})
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
117 if slice_tag not in slice_tags:
118 attributes.append({'tagname': slice_tag['tagname'],
119 'value': slice_tag['value']})
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
125 if slice_tag['tagname'] not in sliver_attributes:
126 attributes.append({'tagname': slice_tag['tagname'],
127 'value': slice_tag['value']})
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
135 'name': slice['name'],
136 'slice_id': slice['slice_id'],
137 'instantiation': slice['instantiation'],
138 'expires': slice['expires'],
140 'attributes': attributes
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
151 # get this slice's authority (site)
152 slice_authority = get_authority(hrn)
154 # get this site's authority (sfa root authority or sub authority)
155 site_authority = get_authority(slice_authority).lower()
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']
166 def get_sfa_peer(self, hrn):
167 # return the authority for this hrn or None if we are the authority
169 slice_authority = get_authority(hrn)
170 site_authority = get_authority(slice_authority)
172 if site_authority != self.api.hrn:
173 sfa_peer = site_authority
179 Update the cached list of slices
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()
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]
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)
201 slice_details = {'hrn': slice_hrns,
202 'timestamp': hr_timestamp,
203 'threshold': hr_threshold
205 self.update(slice_details)
209 def refresh_slices_smgr(self):
211 aggregates = Aggregates(self.api)
212 credential = self.api.getCredential()
213 for aggregate in aggregates:
215 # request hash is optional so lets try the call without it
218 slices = aggregates[aggregate].get_slices(credential, request_hash)
219 slice_hrns.extend(slices)
222 print >> log, "%s" % (traceback.format_exc())
223 print >> log, "Error calling slices at aggregate %(aggregate)s" % locals()
225 # try sending the request hash if the previous call failed
227 arg_list = [credential]
228 request_hash = self.api.key.compute_hash(arg_list)
230 slices = aggregates[aggregate].get_slices(credential, request_hash)
231 slice_hrns.extend(slices)
234 print >> log, "%s" % (traceback.format_exc())
235 print >> log, "Error calling slices at aggregate %(aggregate)s" % locals()
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)
244 slice_details = {'hrn': slice_hrns,
245 'timestamp': hr_timestamp,
246 'threshold': hr_threshold
248 self.update(slice_details)
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)
258 def delete_slice_aggregate(self, hrn):
260 slicename = hrn_to_pl_slicename(hrn)
261 slices = self.api.plshell.GetSlices(self.api.plauth, {'name': slicename})
266 # determine if this is a peer slice
267 peer = self.get_peer(hrn)
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'])
272 self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
275 def delete_slice_smgr(self, hrn):
276 credential = self.api.getCredential()
277 caller_cred = self.caller_cred
278 aggregates = Aggregates(self.api)
279 for aggregate in aggregates:
281 # request hash is optional so lets try the call without it
284 aggregates[aggregate].delete_slice(credential, hrn, request_hash, caller_cred)
287 print >> log, "%s" % (traceback.format_exc())
288 print >> log, "Error calling list nodes at aggregate %s" % aggregate
290 # try sending the request hash if the previous call failed
293 arg_list = [credential, hrn]
294 request_hash = self.api.key.compute_hash(arg_list)
295 aggregates[aggregate].delete_slice(credential, hrn, request_hash, caller_cred)
298 print >> log, "%s" % (traceback.format_exc())
299 print >> log, "Error calling list nodes at aggregate %s" % aggregate
301 def create_slice(self, hrn, rspec):
303 # check our slice policy before we procede
304 whitelist = self.policy['slice_whitelist']
305 blacklist = self.policy['slice_blacklist']
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()
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)
318 def verify_site(self, registry, credential, slice_hrn, peer, sfa_peer):
319 authority = get_authority(slice_hrn)
321 site_records = registry.resolve(credential, authority)
323 arg_list = [credential, authority]
324 request_hash = self.api.key.compute_hash(arg_list)
325 site_records = registry.resolve(credential, authority, request_hash)
328 for site_record in site_records:
329 if site_record['type'] == 'authority':
332 raise RecordNotFound(authority)
333 remote_site_id = site.pop('site_id')
335 login_base = get_leaf(authority)
336 sites = self.api.plshell.GetSites(self.api.plauth, login_base)
338 site_id = self.api.plshell.AddSite(self.api.plauth, site)
340 self.api.plshell.BindObjectToPeer(self.api.plauth, 'site', site_id, peer, remote_site_id)
341 # mark this site as an sfa peer record
343 peer_dict = {'type': 'authority', 'hrn': authority, 'peer_authority': sfa_peer, 'pointer': site_id}
345 registry.register_peer_object(credential, peer_dict)
347 arg_list = [credential]
348 request_hash = self.api.key.compute_hash(arg_list)
349 registry.register_peer_object(credential, peer_dict, request_hash)
351 site_id = sites[0]['site_id']
352 remote_site_id = sites[0]['peer_site_id']
355 return (site_id, remote_site_id)
357 def verify_slice(self, registry, credential, slice_hrn, site_id, remote_site_id, peer, sfa_peer):
360 authority = get_authority(slice_hrn)
362 slice_records = registry.resolve(credential, slice_hrn)
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)
368 for record in slice_records:
369 if record['type'] in ['slice']:
370 slice_record = 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'])
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]
385 slice_id = self.api.plshell.AddSlice(self.api.plauth, slice_fields)
387 slice['slice_id'] = slice_id
389 # mark this slice as an sfa peer record
391 peer_dict = {'type': 'slice', 'hrn': slice_hrn, 'peer_authority': sfa_peer, 'pointer': slice_id}
393 registry.register_peer_object(credential, peer_dict)
395 arg_list = [credential]
396 request_hash = self.api.key.compute_hash(arg_list)
397 registry.register_peer_object(credential, peer_dict, request_hash)
399 #this belongs to a peer
401 self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice_id, peer, slice_record['pointer'])
402 slice['node_ids'] = []
405 slice_id = slice['slice_id']
406 site_id = slice['site_id']
408 slice['peer_slice_id'] = slice_record['pointer']
409 self.verify_persons(registry, credential, slice_record, site_id, remote_site_id, peer, sfa_peer)
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:
421 person_records = registry.resolve(credential, researcher)
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:
431 person_dict = person_record
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'])
437 persons = self.api.plshell.GetPersons(self.api.plauth, [person_dict['email']], ['person_id', 'key_ids'])
442 persons = self.api.plshell.GetPersons(self.api.plauth, [person_dict['email']], ['person_id', 'key_ids'])
445 person_id=self.api.plshell.AddPerson(self.api.plauth, person_dict)
446 self.api.plshell.UpdatePerson(self.api.plauth, person_id, {'enabled' : True})
448 # mark this person as an sfa peer record
450 peer_dict = {'type': 'user', 'hrn': researcher, 'peer_authority': sfa_peer, 'pointer': person_id}
452 registry.register_peer_object(credential, peer_dict)
454 arg_list = [credential]
455 request_hash = self.api.key.compute_hash(arg_list)
456 registry.register_peer_object(credential, peer_dict, request_hash)
459 self.api.plshell.BindObjectToPeer(self.api.plauth, 'person', person_id, peer, person_dict['pointer'])
462 person_id = persons[0]['person_id']
463 key_ids = persons[0]['key_ids']
466 # if this is a peer person, we must unbind them from the peer or PLCAPI will throw
469 self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'person', person_id, peer)
470 self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'site', site_id, peer)
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'])
477 self.api.plshell.BindObjectToPeer(self.api.plauth, 'site', site_id, peer, remote_site_id)
479 self.verify_keys(registry, credential, person_dict, key_ids, person_id, peer, local_person)
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]
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}
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'])
496 try: self.api.plshell.BindObjectToPeer(self.api.plauth, 'key', key_id, peer, key_ids.pop(0))
500 def create_slice_aggregate(self, hrn, rspec):
502 # Determine if this is a peer slice
503 peer = self.get_peer(hrn)
504 sfa_peer = self.get_sfa_peer(hrn)
507 # Get the slice record from sfa
508 slicename = hrn_to_pl_slicename(hrn)
511 registries = Registries(self.api)
512 registry = registries[self.api.hrn]
513 credential = self.api.getCredential()
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)
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]
522 # get netspec details
523 nodespecs = spec.getDictsByTagName('NodeSpec')
525 # dict in which to store slice attributes to set for the nodes
527 for nodespec in nodespecs:
528 if isinstance(nodespec['name'], list):
529 for nodename in nodespec['name']:
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']
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
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
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))
558 self.api.plshell.UnBindObjectFromPeer(self.api.plauth, 'slice', slice['slice_id'], peer)
560 self.api.plshell.AddSliceToNodes(self.api.plauth, slicename, added_nodes)
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)):
570 self.api.plshell.AddSliceTag(self.api.plauth, slicename, slice_tag, value, node_name)
572 self.api.plshell.DeleteSliceFromNodes(self.api.plauth, slicename, deleted_nodes)
574 self.api.plshell.BindObjectToPeer(self.api.plauth, 'slice', slice['slice_id'], peer, slice['peer_slice_id'])
578 def create_slice_smgr(self, hrn, 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']
587 if specDict.has_key('end_time'): end_time = specDict['end_time']
591 aggregates = Aggregates(self.api)
592 credential = self.api.getCredential()
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()
603 # send each rspec to the appropriate aggregate/sm
604 caller_cred = self.caller_cred
605 for net_hrn in rspecs:
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]:
614 aggregates[net_hrn].create_slice(credential, hrn, rspec, request_hash, caller_cred)
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, caller_cred)
622 aggregates[net_hrn].create_slice(credential, hrn, rspecs[net_hrn], request_hash, caller_cred)
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, caller_cred)
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:
633 network_found = aggregates[aggregate].get_aggregates(credential, net_hrn)
635 network_found = aggregates[aggregate].get_aggregates(credential, net_hrn, request_hash)
639 aggregates[aggregate].create_slice(credential, hrn, rspecs[net_hrn], request_hash, caller_cred)
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, caller_cred)
646 print >> log, "Error creating slice %(hrn)s at aggregate %(net_hrn)s" % locals()
647 traceback.print_exc()
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)
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'])
661 raise RecordNotFound(hrn)
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" )
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)
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)
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'])
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")
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:
700 aggregates[aggregate].stop_slice(credential, hrn)
702 aggregates[aggregate].stop_slice(credential, hrn, request_hash)