3 from sfa.util.faults import MissingSfaInfo, UnknownSfaType, \
4 RecordNotFound, SfaNotImplemented, SliverDoesNotExist, SearchFailed, \
6 from sfa.util.sfalogging import logger
7 from sfa.util.defaultdict import defaultdict
8 from sfa.util.sfatime import utcparse, datetime_to_string, datetime_to_epoch
9 from sfa.util.xrn import Xrn, hrn_to_urn, get_leaf
10 from sfa.util.cache import Cache
12 # one would think the driver should not need to mess with the SFA db, but..
13 from sfa.storage.alchemy import dbsession
14 from sfa.storage.model import RegRecord, SliverAllocation
16 # used to be used in get_ticket
17 #from sfa.trust.sfaticket import SfaTicket
18 from sfa.rspecs.version_manager import VersionManager
19 from sfa.rspecs.rspec import RSpec
21 # the driver interface, mostly provides default behaviours
22 from sfa.managers.driver import Driver
23 from sfa.planetlab.plshell import PlShell
24 import sfa.planetlab.peers as peers
25 from sfa.planetlab.plaggregate import PlAggregate
26 from sfa.planetlab.plslices import PlSlices
27 from sfa.planetlab.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, xrn_to_hostname
30 def list_to_dict(recs, key):
32 convert a list of dictionaries into a dictionary keyed on the
33 specified dictionary key
35 return dict ( [ (rec[key],rec) for rec in recs ] )
38 # PlShell is just an xmlrpc serverproxy where methods
39 # can be sent as-is; it takes care of authentication
40 # from the global config
42 class PlDriver (Driver):
44 # the cache instance is a class member so it survives across incoming requests
47 def __init__ (self, config):
48 Driver.__init__ (self, config)
49 self.shell = PlShell (config)
51 if config.SFA_AGGREGATE_CACHING:
52 if PlDriver.cache is None:
53 PlDriver.cache = Cache()
54 self.cache = PlDriver.cache
56 ########################################
57 ########## registry oriented
58 ########################################
60 def augment_records_with_testbed_info (self, sfa_records):
61 return self.fill_record_info (sfa_records)
64 def register (self, sfa_record, hrn, pub_key):
65 type = sfa_record['type']
66 pl_record = self.sfa_fields_to_pl_fields(type, hrn, sfa_record)
68 if type == 'authority':
69 sites = self.shell.GetSites([pl_record['login_base']])
71 # xxx when a site gets registered through SFA we need to set its max_slices
72 if 'max_slices' not in pl_record:
73 pl_record['max_slices']=2
74 pointer = self.shell.AddSite(pl_record)
76 pointer = sites[0]['site_id']
79 acceptable_fields=['url', 'instantiation', 'name', 'description']
80 for key in pl_record.keys():
81 if key not in acceptable_fields:
83 slices = self.shell.GetSlices([pl_record['name']])
85 pointer = self.shell.AddSlice(pl_record)
87 pointer = slices[0]['slice_id']
90 persons = self.shell.GetPersons({'email':sfa_record['email']})
92 for key in ['first_name','last_name']:
93 if key not in sfa_record: sfa_record[key]='*from*sfa*'
94 # AddPerson does not allow everything to be set
95 can_add = ['first_name', 'last_name', 'title','email', 'password', 'phone', 'url', 'bio']
96 add_person_dict=dict ( [ (k,sfa_record[k]) for k in sfa_record if k in can_add ] )
97 pointer = self.shell.AddPerson(add_person_dict)
99 pointer = persons[0]['person_id']
101 if 'enabled' in sfa_record and sfa_record['enabled']:
102 self.shell.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
103 # add this person to the site only if she is being added for the first
104 # time by sfa and doesont already exist in plc
105 if not persons or not persons[0]['site_ids']:
106 login_base = get_leaf(sfa_record['authority'])
107 self.shell.AddPersonToSite(pointer, login_base)
109 # What roles should this user have?
111 if 'roles' in sfa_record:
112 # if specified in xml, but only low-level roles
113 roles = [ role for role in sfa_record['roles'] if role in ['user','tech'] ]
114 # at least user if no other cluse could be found
118 self.shell.AddRoleToPerson(role, pointer)
121 self.shell.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
124 login_base = PlXrn(xrn=sfa_record['authority'],type='node').pl_login_base()
125 nodes = self.shell.GetNodes([pl_record['hostname']])
127 pointer = self.shell.AddNode(login_base, pl_record)
129 pointer = nodes[0]['node_id']
134 # xxx actually old_sfa_record comes filled with plc stuff as well in the original code
135 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
136 pointer = old_sfa_record['pointer']
137 type = old_sfa_record['type']
139 # new_key implemented for users only
140 if new_key and type not in [ 'user' ]:
141 raise UnknownSfaType(type)
143 if (type == "authority"):
144 self.shell.UpdateSite(pointer, new_sfa_record)
146 elif type == "slice":
147 pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
148 if 'name' in pl_record:
149 pl_record.pop('name')
150 self.shell.UpdateSlice(pointer, pl_record)
153 # SMBAKER: UpdatePerson only allows a limited set of fields to be
154 # updated. Ideally we should have a more generic way of doing
155 # this. I copied the field names from UpdatePerson.py...
157 all_fields = new_sfa_record
158 for key in all_fields.keys():
159 if key in ['first_name', 'last_name', 'title', 'email',
160 'password', 'phone', 'url', 'bio', 'accepted_aup',
162 update_fields[key] = all_fields[key]
163 # when updating a user, we always get a 'email' field at this point
164 # this is because 'email' is a native field in the RegUser object...
165 if 'email' in update_fields and not update_fields['email']:
166 del update_fields['email']
167 self.shell.UpdatePerson(pointer, update_fields)
170 # must check this key against the previous one if it exists
171 persons = self.shell.GetPersons([pointer], ['key_ids'])
173 keys = person['key_ids']
174 keys = self.shell.GetKeys(person['key_ids'])
176 # Delete all stale keys
179 if new_key != key['key']:
180 self.shell.DeleteKey(key['key_id'])
184 self.shell.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
187 self.shell.UpdateNode(pointer, new_sfa_record)
193 def remove (self, sfa_record):
194 type=sfa_record['type']
195 pointer=sfa_record['pointer']
197 persons = self.shell.GetPersons(pointer)
198 # only delete this person if he has site ids. if he doesnt, it probably means
199 # he was just removed from a site, not actually deleted
200 if persons and persons[0]['site_ids']:
201 self.shell.DeletePerson(pointer)
202 elif type == 'slice':
203 if self.shell.GetSlices(pointer):
204 self.shell.DeleteSlice(pointer)
206 if self.shell.GetNodes(pointer):
207 self.shell.DeleteNode(pointer)
208 elif type == 'authority':
209 if self.shell.GetSites(pointer):
210 self.shell.DeleteSite(pointer)
219 # Convert SFA fields to PLC fields for use when registering or updating
220 # registry record in the PLC database
223 def sfa_fields_to_pl_fields(self, type, hrn, sfa_record):
228 pl_record["name"] = hrn_to_pl_slicename(hrn)
229 if "instantiation" in sfa_record:
230 pl_record['instantiation']=sfa_record['instantiation']
232 pl_record["instantiation"] = "plc-instantiated"
233 if "url" in sfa_record:
234 pl_record["url"] = sfa_record["url"]
235 if "description" in sfa_record:
236 pl_record["description"] = sfa_record["description"]
237 if "expires" in sfa_record:
238 date = utcparse(sfa_record['expires'])
239 expires = datetime_to_epoch(date)
240 pl_record["expires"] = expires
243 if not "hostname" in pl_record:
244 # fetch from sfa_record
245 if "hostname" not in sfa_record:
246 raise MissingSfaInfo("hostname")
247 pl_record["hostname"] = sfa_record["hostname"]
248 if "model" in sfa_record:
249 pl_record["model"] = sfa_record["model"]
251 pl_record["model"] = "geni"
253 elif type == "authority":
254 pl_record["login_base"] = PlXrn(xrn=hrn,type='authority').pl_login_base()
255 if "name" not in sfa_record:
256 pl_record["name"] = hrn
257 if "abbreviated_name" not in sfa_record:
258 pl_record["abbreviated_name"] = hrn
259 if "enabled" not in sfa_record:
260 pl_record["enabled"] = True
261 if "is_public" not in sfa_record:
262 pl_record["is_public"] = True
267 def fill_record_info(self, records):
269 Given a (list of) SFA record, fill in the PLC specific
270 and SFA specific fields in the record.
272 if not isinstance(records, list):
275 self.fill_record_pl_info(records)
276 self.fill_record_hrns(records)
277 self.fill_record_sfa_info(records)
280 def fill_record_pl_info(self, records):
282 Fill in the planetlab specific fields of a SFA record. This
283 involves calling the appropriate PLC method to retrieve the
284 database record for the object.
286 @param record: record to fill in field (in/out param)
289 node_ids, site_ids, slice_ids = [], [], []
290 person_ids, key_ids = [], []
291 type_map = {'node': node_ids, 'authority': site_ids,
292 'slice': slice_ids, 'user': person_ids}
294 for record in records:
295 for type in type_map:
296 if type == record['type']:
297 type_map[type].append(record['pointer'])
300 nodes, sites, slices, persons, keys = {}, {}, {}, {}, {}
302 node_list = self.shell.GetNodes(node_ids)
303 nodes = list_to_dict(node_list, 'node_id')
305 site_list = self.shell.GetSites(site_ids)
306 sites = list_to_dict(site_list, 'site_id')
308 slice_list = self.shell.GetSlices(slice_ids)
309 slices = list_to_dict(slice_list, 'slice_id')
311 person_list = self.shell.GetPersons(person_ids)
312 persons = list_to_dict(person_list, 'person_id')
313 for person in persons:
314 key_ids.extend(persons[person]['key_ids'])
316 pl_records = {'node': nodes, 'authority': sites,
317 'slice': slices, 'user': persons}
320 key_list = self.shell.GetKeys(key_ids)
321 keys = list_to_dict(key_list, 'key_id')
324 for record in records:
325 # records with pointer==-1 do not have plc info.
326 # for example, the top level authority records which are
327 # authorities, but not PL "sites"
328 if record['pointer'] == -1:
331 for type in pl_records:
332 if record['type'] == type:
333 if record['pointer'] in pl_records[type]:
334 record.update(pl_records[type][record['pointer']])
337 if record['type'] == 'user':
338 if 'key_ids' not in record:
339 logger.info("user record has no 'key_ids' - need to import from myplc ?")
341 pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
342 record['keys'] = pubkeys
346 def fill_record_hrns(self, records):
348 convert pl ids to hrns
352 slice_ids, person_ids, site_ids, node_ids = [], [], [], []
353 for record in records:
354 if 'site_id' in record:
355 site_ids.append(record['site_id'])
356 if 'site_ids' in record:
357 site_ids.extend(record['site_ids'])
358 if 'person_ids' in record:
359 person_ids.extend(record['person_ids'])
360 if 'slice_ids' in record:
361 slice_ids.extend(record['slice_ids'])
362 if 'node_ids' in record:
363 node_ids.extend(record['node_ids'])
366 slices, persons, sites, nodes = {}, {}, {}, {}
368 site_list = self.shell.GetSites(site_ids, ['site_id', 'login_base'])
369 sites = list_to_dict(site_list, 'site_id')
371 person_list = self.shell.GetPersons(person_ids, ['person_id', 'email'])
372 persons = list_to_dict(person_list, 'person_id')
374 slice_list = self.shell.GetSlices(slice_ids, ['slice_id', 'name'])
375 slices = list_to_dict(slice_list, 'slice_id')
377 node_list = self.shell.GetNodes(node_ids, ['node_id', 'hostname'])
378 nodes = list_to_dict(node_list, 'node_id')
380 # convert ids to hrns
381 for record in records:
382 # get all relevant data
383 type = record['type']
384 pointer = record['pointer']
390 if 'site_id' in record:
391 site = sites[record['site_id']]
392 login_base = site['login_base']
393 record['site'] = ".".join([auth_hrn, login_base])
394 if 'person_ids' in record:
395 emails = [persons[person_id]['email'] for person_id in record['person_ids'] \
396 if person_id in persons]
397 usernames = [email.split('@')[0] for email in emails]
398 person_hrns = [".".join([auth_hrn, login_base, username]) for username in usernames]
399 record['persons'] = person_hrns
400 if 'slice_ids' in record:
401 slicenames = [slices[slice_id]['name'] for slice_id in record['slice_ids'] \
402 if slice_id in slices]
403 slice_hrns = [slicename_to_hrn(auth_hrn, slicename) for slicename in slicenames]
404 record['slices'] = slice_hrns
405 if 'node_ids' in record:
406 hostnames = [nodes[node_id]['hostname'] for node_id in record['node_ids'] \
408 node_hrns = [hostname_to_hrn(auth_hrn, login_base, hostname) for hostname in hostnames]
409 record['nodes'] = node_hrns
410 if 'site_ids' in record:
411 login_bases = [sites[site_id]['login_base'] for site_id in record['site_ids'] \
413 site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
414 record['sites'] = site_hrns
416 if 'expires' in record:
417 date = utcparse(record['expires'])
418 datestring = datetime_to_string(date)
419 record['expires'] = datestring
423 def fill_record_sfa_info(self, records):
425 def startswith(prefix, values):
426 return [value for value in values if value.startswith(prefix)]
431 for record in records:
432 person_ids.extend(record.get("person_ids", []))
433 site_ids.extend(record.get("site_ids", []))
434 if 'site_id' in record:
435 site_ids.append(record['site_id'])
437 # get all pis from the sites we've encountered
438 # and store them in a dictionary keyed on site_id
441 pi_filter = {'|roles': ['pi'], '|site_ids': site_ids}
442 pi_list = self.shell.GetPersons(pi_filter, ['person_id', 'site_ids'])
444 # we will need the pi's hrns also
445 person_ids.append(pi['person_id'])
447 # we also need to keep track of the sites these pis
449 for site_id in pi['site_ids']:
450 if site_id in site_pis:
451 site_pis[site_id].append(pi)
453 site_pis[site_id] = [pi]
455 # get sfa records for all records associated with these records.
456 # we'll replace pl ids (person_ids) with hrns from the sfa records
459 # get the registry records
460 person_list, persons = [], {}
461 person_list = dbsession.query (RegRecord).filter(RegRecord.pointer.in_(person_ids))
462 # create a hrns keyed on the sfa record's pointer.
463 # Its possible for multiple records to have the same pointer so
464 # the dict's value will be a list of hrns.
465 persons = defaultdict(list)
466 for person in person_list:
467 persons[person.pointer].append(person)
470 pl_person_list, pl_persons = [], {}
471 pl_person_list = self.shell.GetPersons(person_ids, ['person_id', 'roles'])
472 pl_persons = list_to_dict(pl_person_list, 'person_id')
475 for record in records:
476 # skip records with no pl info (top level authorities)
477 #if record['pointer'] == -1:
480 type = record['type']
481 logger.info("fill_record_sfa_info - incoming record typed %s"%type)
482 if (type == "slice"):
483 # all slice users are researchers
484 record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
486 record['researcher'] = []
487 for person_id in record.get('person_ids', []):
488 hrns = [person.hrn for person in persons[person_id]]
489 record['researcher'].extend(hrns)
491 # pis at the slice's site
492 if 'site_id' in record and record['site_id'] in site_pis:
493 pl_pis = site_pis[record['site_id']]
494 pi_ids = [pi['person_id'] for pi in pl_pis]
495 for person_id in pi_ids:
496 hrns = [person.hrn for person in persons[person_id]]
497 record['PI'].extend(hrns)
498 record['geni_creator'] = record['PI']
500 elif (type.startswith("authority")):
502 logger.info("fill_record_sfa_info - authority xherex")
503 if record['pointer'] != -1:
505 record['operator'] = []
507 for pointer in record.get('person_ids', []):
508 if pointer not in persons or pointer not in pl_persons:
509 # this means there is not sfa or pl record for this user
511 hrns = [person.hrn for person in persons[pointer]]
512 roles = pl_persons[pointer]['roles']
514 record['PI'].extend(hrns)
516 record['operator'].extend(hrns)
518 record['owner'].extend(hrns)
519 # xxx TODO: OrganizationName
520 elif (type == "node"):
521 sfa_info['dns'] = record.get("hostname", "")
522 # xxx TODO: URI, LatLong, IP, DNS
524 elif (type == "user"):
525 logger.info('setting user.email')
526 sfa_info['email'] = record.get("email", "")
527 sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
528 sfa_info['geni_certificate'] = record['gid']
529 # xxx TODO: PostalAddress, Phone
530 record.update(sfa_info)
534 # plcapi works by changes, compute what needs to be added/deleted
535 def update_relation (self, subject_type, target_type, relation_name, subject_id, target_ids):
536 # hard-wire the code for slice/user for now, could be smarter if needed
537 if subject_type =='slice' and target_type == 'user' and relation_name == 'researcher':
538 subject=self.shell.GetSlices (subject_id)[0]
539 current_target_ids = subject['person_ids']
540 add_target_ids = list ( set (target_ids).difference(current_target_ids))
541 del_target_ids = list ( set (current_target_ids).difference(target_ids))
542 logger.debug ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
543 for target_id in add_target_ids:
544 self.shell.AddPersonToSlice (target_id,subject_id)
545 logger.debug ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
546 for target_id in del_target_ids:
547 logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
548 self.shell.DeletePersonFromSlice (target_id, subject_id)
549 elif subject_type == 'authority' and target_type == 'user' and relation_name == 'pi':
550 # due to the plcapi limitations this means essentially adding pi role to all people in the list
551 # it's tricky to remove any pi role here, although it might be desirable
552 persons = self.shell.GetPersons (target_ids)
553 for person in persons:
554 if 'pi' not in person['roles']:
555 self.shell.AddRoleToPerson('pi',person['person_id'])
557 logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type))
560 ########################################
561 ########## aggregate oriented
562 ########################################
564 def testbed_name (self): return "myplc"
566 def aggregate_version (self):
569 # first 2 args are None in case of resource discovery
570 def list_resources (self, version=None, options={}):
571 aggregate = PlAggregate(self)
572 rspec = aggregate.list_resources(version=version, options=options)
575 def describe(self, urns, version, options={}):
576 aggregate = PlAggregate(self)
577 return aggregate.describe(urns, version=version, options=options)
579 def status (self, urns, options={}):
580 aggregate = PlAggregate(self)
581 desc = aggregate.describe(urns)
582 status = {'geni_urn': desc['geni_urn'],
583 'geni_slivers': desc['geni_slivers']}
586 def allocate (self, urn, rspec_string, options={}):
588 aggregate = PlAggregate(self)
589 slices = PlSlices(self)
590 peer = slices.get_peer(xrn.get_hrn())
591 sfa_peer = slices.get_sfa_peer(xrn.get_hrn())
593 users = options.get('geni_users', [])
595 slice_record = users[0].get('slice_record', {})
598 rspec = RSpec(rspec_string)
599 requested_attributes = rspec.version.get_slice_attributes()
601 # ensure site record exists
602 site = slices.verify_site(xrn.hrn, slice_record, peer, sfa_peer, options=options)
603 # ensure slice record exists
604 slice = slices.verify_slice(xrn.hrn, slice_record, peer, sfa_peer, options=options)
605 # ensure person records exists
606 persons = slices.verify_persons(xrn.hrn, slice, users, peer, sfa_peer, options=options)
607 # ensure slice attributes exists
608 slices.verify_slice_attributes(slice, requested_attributes, options=options)
610 # add/remove slice from nodes
611 request_nodes = rspec.version.get_nodes_with_slivers()
612 nodes = slices.verify_slice_nodes(slice, request_nodes, peer)
614 # add/remove links links
615 slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
618 requested_leases = []
620 for lease in rspec.version.get_leases():
622 if not lease.get('lease_id'):
623 requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip())
624 requested_lease['start_time'] = lease.get('start_time')
625 requested_lease['duration'] = lease.get('duration')
627 kept_leases.append(int(lease['lease_id']))
628 if requested_lease.get('hostname'):
629 requested_leases.append(requested_lease)
631 leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer)
632 # handle MyPLC peer association.
633 # only used by plc and ple.
634 slices.handle_peer(site, slice, persons, peer)
636 return aggregate.describe([xrn.get_urn()], version=rspec.version)
638 def provision(self, urns, options={}):
639 # update sliver allocation states and set them to geni_provisioned
640 aggregate = PlAggregate(self)
641 slivers = aggregate.get_slivers(urns)
642 sliver_ids = [sliver['sliver_id'] for sliver in slivers]
643 SliverAllocation.set_allocations(sliver_ids, 'geni_provisioned')
644 version_manager = VersionManager()
645 rspec_version = version_manager.get_version(options['geni_rspec_version'])
646 return self.describe(urns, rspec_version, options=options)
648 def delete(self, urns, options={}):
649 # collect sliver ids so we can update sliver allocation states after
650 # we remove the slivers.
651 aggregate = PlAggregate(self)
652 slivers = aggregate.get_slivers(urns)
654 slice_id = slivers[0]['slice_id']
657 for sliver in slivers:
658 node_ids.append(sliver['node_id'])
659 sliver_ids.append(sliver['sliver_id'])
661 # determine if this is a peer slice
662 # xxx I wonder if this would not need to use PlSlices.get_peer instead
663 # in which case plc.peers could be deprecated as this here
664 # is the only/last call to this last method in plc.peers
665 slice_hrn = PlXrn(auth=self.hrn, slicename=slivers[0]['name']).get_hrn()
666 peer = peers.get_peer(self, slice_hrn)
669 self.shell.UnBindObjectFromPeer('slice', slice_id, peer)
671 self.shell.DeleteSliceFromNodes(slice_id, node_ids)
673 # delete sliver allocation states
674 SliverAllocation.delete_allocations(sliver_ids)
677 self.shell.BindObjectToPeer('slice', slice_id, peer, slice['peer_slice_id'])
679 # prepare return struct
681 for sliver in slivers:
683 {'geni_sliver_urn': sliver['sliver_id'],
684 'geni_allocation_status': 'geni_unallocated',
685 'geni_expires': datetime_to_string(utcparse(sliver['expires']))})
688 def renew (self, urns, expiration_time, options={}):
689 # we can only renew slices, not individual slivers. ignore sliver
693 xrn = PlXrn(xrn=urn, type='slice')
694 names.append(xrn.pl_slicename())
695 slices = self.shell.GetSlices(names, ['slice_id'])
697 raise SearchFailed(urns)
699 requested_time = utcparse(expiration_time)
700 record = {'expires': int(datetime_to_epoch(requested_time))}
701 self.shell.UpdateSlice(slice['slice_id'], record)
702 description = self.describe(urns, None, options)
703 return description['geni_slivers']
706 def perform_operational_action (self, urns, action, options={}):
707 # MyPLC doesn't support operational actions. Lets pretend like it
708 # supports start, but reject everything else.
709 action = action.lower()
710 if action not in ['geni_start']:
711 raise UnsupportedOperation(action)
713 # fault if sliver is not full allocated (operational status is geni_pending_allocation)
714 description = self.describe(urns, None, options)
715 for sliver in description['geni_slivers']:
716 if sliver['geni_operational_status'] == 'geni_pending_allocation':
717 raise UnsupportedOperation(action, "Sliver must be fully allocated (operational status is not geni_pending_allocation)")
719 # Perform Operational Action Here
722 geni_slivers = self.describe(urns, None, options)['geni_slivers']
725 # set the 'enabled' tag to 0
726 def shutdown (self, xrn, options={}):
727 xrn = PlXrn(xrn=xrn, type='slice')
728 slicename = xrn.pl_slicename()
729 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
731 raise RecordNotFound(slice_hrn)
732 slice_id = slices[0]['slice_id']
733 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'})
735 self.shell.AddSliceTag(slice_id, 'enabled', '0')
736 elif slice_tags[0]['value'] != "0":
737 tag_id = slice_tags[0]['slice_tag_id']
738 self.shell.UpdateSliceTag(tag_id, '0')