From: Mohamed Larabi Date: Mon, 25 Mar 2013 16:06:12 +0000 (+0100) Subject: Merge Master in geni-v3 conflict resolution X-Git-Tag: sfa-3.0-0 X-Git-Url: http://git.onelab.eu/?p=sfa.git;a=commitdiff_plain;h=1cc8e9613cab8b5b22478de369f259e591c54e6d Merge Master in geni-v3 conflict resolution --- 1cc8e9613cab8b5b22478de369f259e591c54e6d diff --cc sfa/client/sfi.py index 57cb37ee,15c83cd6..53d655b8 --- a/sfa/client/sfi.py +++ b/sfa/client/sfi.py @@@ -281,17 -250,17 +259,17 @@@ class Sfi ("version", ""), ("list", "authority"), ("show", "name"), - ("add", "record"), - ("update", "record"), + ("add", "[record]"), + ("update", "[record]"), ("remove", "name"), - ("slices", ""), - ("resources", "[slice_hrn]"), + ("resources", ""), + ("describe", "slice_hrn"), ("create", "slice_hrn rspec"), + ("allocate", "slice_hrn rspec"), + ("provision", "slice_hrn"), + ("action", "slice_hrn action"), ("delete", "slice_hrn"), ("status", "slice_hrn"), - ("start", "slice_hrn"), - ("stop", "slice_hrn"), - ("reset", "slice_hrn"), ("renew", "slice_hrn time"), ("shutdown", "slice_hrn"), ("get_ticket", "slice_hrn rspec"), @@@ -992,12 -941,9 +987,9 @@@ or version information about sfi itsel server = self.sliceapi() # creds creds = [self.my_credential_string] - if options.delegate: - delegated_cred = self.delegate_cred(self.my_credential_string, get_authority(self.authority)) - creds.append(delegated_cred) # options and call_id when supported api_options = {} - api_options['call_id']=unique_call_id() + api_options['call_id']=unique_call_id() if options.show_credential: show_credentials(creds) result = server.ListSlices(creds, *self.ois(server,api_options)) @@@ -1181,11 -1101,8 +1177,8 @@@ or with an slice hrn, shows currently p slice_urn = hrn_to_urn(slice_hrn, 'slice') # creds - slice_cred = self.slice_credential_string(slice_hrn) + slice_cred = self.slice_credential(slice_hrn) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) # options and call_id when supported api_options = {} @@@ -1305,11 -1128,8 +1298,8 @@@ slice_urn = hrn_to_urn(slice_hrn, 'slice') # creds - slice_cred = self.slice_credential_string(slice_hrn) + slice_cred = self.slice_credential(slice_hrn) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) # options and call_id when supported api_options = {} @@@ -1409,17 -1217,14 +1393,14 @@@ slice_urn = hrn_to_urn(slice_hrn, 'slice') # time: don't try to be smart on the time format, server-side will # creds - slice_cred = self.slice_credential_string(args[0]) + slice_cred = self.slice_credential(args[0]) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) # options and call_id when supported api_options = {} - api_options['call_id']=unique_call_id() + api_options['call_id']=unique_call_id() if options.show_credential: show_credentials(creds) - result = server.RenewSliver(slice_urn, creds, input_time, *self.ois(server,api_options)) + result = server.Renew([slice_urn], creds, input_time, *self.ois(server,api_options)) value = ReturnValue.get_value(result) if self.options.raw: save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner) @@@ -1437,11 -1242,8 +1418,8 @@@ slice_hrn = args[0] slice_urn = hrn_to_urn(slice_hrn, 'slice') # creds - slice_cred = self.slice_credential_string(slice_hrn) + slice_cred = self.slice_credential(slice_hrn) creds = [slice_cred] - if options.delegate: - delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)) - creds.append(delegated_cred) result = server.Shutdown(slice_urn, creds) value = ReturnValue.get_value(result) if self.options.raw: diff --cc sfa/importer/plimporter.py index 1fe64e8f,7994c8c9..8d197b63 --- a/sfa/importer/plimporter.py +++ b/sfa/importer/plimporter.py @@@ -250,13 -254,20 +254,20 @@@ class PlImporter pass node_record.stale=False - site_pis=[] + site_pis=set() # import persons for person_id in site['person_ids']: - try: - person = persons_by_id[person_id] - except: - self.logger.warning ("PlImporter: cannot locate person_id %s - ignored"%person_id) + proceed=False + if person_id in persons_by_id: + person=persons_by_id[person_id] + proceed=True + elif person_id in disabled_person_ids: + pass + else: + self.logger.warning ("PlImporter: cannot locate person_id %s in site %s - ignored"%(person_id,site_hrn)) + # make sure to NOT run this if anything is wrong + if not proceed: continue + person_hrn = email_to_hrn(site_hrn, person['email']) # xxx suspicious again if len(person_hrn) > 64: person_hrn = person_hrn[:64] @@@ -334,7 -367,13 +367,8 @@@ self.logger.log_exc("PlImporter: failed to import person %d %s"%(person['person_id'],person['email'])) # maintain the list of PIs for a given site - # for the record, Jordan had proposed the following addition as a welcome hotfix to a previous version: - # site_pis = list(set(site_pis)) - # this was likely due to a bug in the above logic, that had to do with disabled persons - # being improperly handled, and where the whole loop on persons - # could be performed twice with the same person... - # so hopefully we do not need to eliminate duplicates explicitly here anymore + site_record.reg_pis = list(site_pis) + site_record.reg_pis = site_pis dbsession.commit() # import slices @@@ -359,15 -398,12 +393,15 @@@ self.logger.info("PlImporter: imported slice: %s" % slice_record) self.remember_record ( slice_record ) except: - self.logger.log_exc("PlImporter: failed to import slice") + self.logger.log_exc("PlImporter: failed to import slice %s (%s)"%(slice_hrn,slice['name'])) else: + # update the pointer if it has changed + if slice_id != slice_record.pointer: + self.logger.info("updating record (slice) pointer") + slice_record.pointer = slice_id + dbsession.commit() # xxx update the record ... - # given that we record the current set of users anyways, there does not seem to be much left to do here - # self.logger.warning ("Slice update not yet implemented on slice %s (%s)"%(slice_hrn,slice['name'])) - pass + #self.logger.warning ("Slice update not yet implemented") # record current users affiliated with the slice slice_record.reg_researchers = \ [ self.locate_by_type_pointer ('user',user_id) for user_id in slice['person_ids'] ] diff --cc sfa/openstack/osaggregate.py index 332976f7,d603b083..de349955 --- a/sfa/openstack/osaggregate.py +++ b/sfa/openstack/osaggregate.py @@@ -194,57 -157,21 +195,56 @@@ class OSAggregate 'port':'22', 'username': 'root'}) service = Services({'login': login}) rspec_node['services'].append(service) - return rspec_node + return rspec_node - def get_slice_nodes(self, slice_xrn): - # update nova connection - tenant_name = OSXrn(xrn=slice_xrn, type='slice').get_tenant_name() - self.driver.shell.nova_manager.connect(tenant=tenant_name) - - zones = self.get_availability_zones() - name = hrn_to_os_slicename(slice_xrn) - instances = self.driver.shell.nova_manager.servers.findall(name=name) - rspec_nodes = [] - for instance in instances: - rspec_nodes.append(self.instance_to_rspec_node(slice_xrn, instance)) - return rspec_nodes + def instance_to_sliver(self, instance, xrn=None): + if xrn: + sliver_hrn = '%s.%s' % (self.driver.hrn, instance.id) + sliver_id = Xrn(sliver_hrn, type='sliver').urn + + sliver = Sliver({'sliver_id': sliver_id, + 'name': instance.name, + 'type': instance.name, + 'cpus': str(instance.vcpus), + 'memory': str(instance.ram), + 'storage': str(instance.disk)}) + return sliver + + def instance_to_geni_sliver(self, instance, sliver_allocations = {}): + sliver_hrn = '%s.%s' % (self.driver.hrn, instance.id) + sliver_id = Xrn(sliver_hrn, type='sliver').urn + + # set sliver allocation and operational status + sliver_allocation = sliver_allocations[sliver_id] + if sliver_allocation: + allocation_status = sliver_allocation.allocation_state + if allocation_status == 'geni_allocated': + op_status = 'geni_pending_allocation' + elif allocation_status == 'geni_provisioned': + state = instance.state.lower() + if state == 'active': + op_status = 'geni_ready' + elif state == 'building': + op_status = 'geni_notready' + elif state == 'failed': + op_status =' geni_failed' + else: + op_status = 'geni_unknown' + else: + allocation_status = 'geni_unallocated' + # required fields + geni_sliver = {'geni_sliver_urn': sliver_id, + 'geni_expires': None, + 'geni_allocation_status': allocation_status, + 'geni_operational_status': op_status, + 'geni_error': None, + 'plos_created_at': datetime_to_string(utcparse(instance.created)), + 'plos_sliver_type': self.shell.nova_manager.flavors.find(id=instance.flavor['id']).name, + } + - + return geni_sliver + def get_aggregate_nodes(self): zones = self.get_availability_zones() # available sliver/instance/vm types @@@ -353,8 -287,9 +358,9 @@@ files = {'/root/.ssh/authorized_keys': authorized_keys} rspec = RSpec(rspec) requested_instances = defaultdict(list) + # iterate over clouds/zones/nodes - created_instances = [] + slivers = [] for node in rspec.version.get_nodes_with_slivers(): instances = node.get('slivers', []) if not instances: diff --cc sfa/planetlab/plaggregate.py index 17ca1d6f,47c637bc..c6006fbb --- a/sfa/planetlab/plaggregate.py +++ b/sfa/planetlab/plaggregate.py @@@ -112,215 -99,170 +112,218 @@@ class PlAggregate pl_initscripts[initscript['initscript_id']] = initscript return pl_initscripts + def get_slivers(self, urns, options={}): + names = set() + slice_ids = set() + node_ids = [] + for urn in urns: + xrn = PlXrn(xrn=urn) + if xrn.type == 'sliver': + # id: slice_id-node_id + try: + sliver_id_parts = xrn.get_sliver_id_parts() + slice_id = int(sliver_id_parts[0]) + node_id = int(sliver_id_parts[1]) + slice_ids.add(slice_id) + node_ids.append(node_id) + except ValueError: + pass + else: + names.add(xrn.pl_slicename()) - def get_slice_and_slivers(self, slice_xrn): - """ - Returns a dict of slivers keyed on the sliver's node_id - """ - slivers = {} - slice = None - if not slice_xrn: - return (slice, slivers) - slice_urn = hrn_to_urn(slice_xrn, 'slice') - slice_hrn, _ = urn_to_hrn(slice_xrn) - slice_name = hrn_to_pl_slicename(slice_hrn) - slices = self.driver.shell.GetSlices(slice_name) + filter = {} + if names: + filter['name'] = list(names) + if slice_ids: + filter['slice_id'] = list(slice_ids) + # get slices + slices = self.driver.shell.GetSlices(filter) if not slices: - return (slice, slivers) - slice = slices[0] - - # sort slivers by node id - for node_id in slice['node_ids']: - sliver_xrn = Xrn(slice_urn, type='sliver', id=node_id) - sliver_xrn.set_authority(self.driver.hrn) - sliver = Sliver({'sliver_id': sliver_xrn.urn, - 'name': slice['name'], - 'type': 'plab-vserver', - 'tags': []}) - slivers[node_id]= sliver - - # sort sliver attributes by node id - tags = self.driver.shell.GetSliceTags({'slice_tag_id': slice['slice_tag_ids']}) - for tag in tags: - # most likely a default/global sliver attribute (node_id == None) - if tag['node_id'] not in slivers: - sliver_xrn = Xrn(slice_urn, type='sliver', id=tag['node_id']) - sliver_xrn.set_authority(self.driver.hrn) - sliver = Sliver({'sliver_id': sliver_xrn.urn, - 'name': slice['name'], - 'type': 'plab-vserver', - 'tags': []}) - slivers[tag['node_id']] = sliver - slivers[tag['node_id']]['tags'].append(tag) + return [] + slice = slices[0] + slice['hrn'] = PlXrn(auth=self.driver.hrn, slicename=slice['name']).hrn + + # get sliver users + persons = [] + person_ids = [] + for slice in slices: + person_ids.extend(slice['person_ids']) + if person_ids: + persons = self.driver.shell.GetPersons(person_ids) + + # get user keys + keys = {} + key_ids = [] + for person in persons: + key_ids.extend(person['key_ids']) - return (slice, slivers) - - def get_nodes_and_links(self, slice_xrn, slice=None,slivers=[], options={}): - # if we are dealing with a slice that has no node just return - # and empty list - if slice_xrn: - if not slice or not slice['node_ids']: - return ([],[]) + if key_ids: + key_list = self.driver.shell.GetKeys(key_ids) + for key in key_list: + keys[key['key_id']] = key + + # construct user key info + users = [] + for person in persons: + name = person['email'][0:person['email'].index('@')] + user = { + 'login': slice['name'], + 'user_urn': Xrn('%s.%s' % (self.driver.hrn, name), type='user').urn, + 'keys': [keys[k_id]['key'] for k_id in person['key_ids'] if k_id in keys] + } + users.append(user) + + if node_ids: + node_ids = [node_id for node_id in node_ids if node_id in slice['node_ids']] + slice['node_ids'] = node_ids + tags_dict = self.get_slice_tags(slice) + nodes_dict = self.get_slice_nodes(slice, options) + slivers = [] + for node in nodes_dict.values(): + node.update(slice) + node['tags'] = tags_dict[node['node_id']] + sliver_hrn = '%s.%s-%s' % (self.driver.hrn, slice['slice_id'], node['node_id']) + node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn + node['urn'] = node['sliver_id'] + node['services_user'] = users + slivers.append(node) + return slivers + + def node_to_rspec_node(self, node, sites, interfaces, node_tags, pl_initscripts=[], grain=None, options={}): + rspec_node = NodeElement() + # xxx how to retrieve site['login_base'] + site=sites[node['site_id']] + rspec_node['component_id'] = PlXrn(self.driver.hrn, hostname=node['hostname']).get_urn() + rspec_node['component_name'] = node['hostname'] + rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn() + rspec_node['authority_id'] = hrn_to_urn(PlXrn.site_hrn(self.driver.hrn, site['login_base']), 'authority+sa') + # do not include boot state ( element) in the manifest rspec + rspec_node['boot_state'] = node['boot_state'] + if node['boot_state'] == 'boot': + rspec_node['available'] = 'true' + else: + rspec_node['available'] = 'false' + rspec_node['exclusive'] = 'false' + rspec_node['hardware_types'] = [HardwareType({'name': 'plab-pc'}), + HardwareType({'name': 'pc'})] + # only doing this because protogeni rspec needs + # to advertise available initscripts + rspec_node['pl_initscripts'] = pl_initscripts.values() + # add site/interface info to nodes. + # assumes that sites, interfaces and tags have already been prepared. + if site['longitude'] and site['latitude']: + location = Location({'longitude': site['longitude'], 'latitude': site['latitude'], 'country': 'unknown'}) + rspec_node['location'] = location + # Granularity + granularity = Granularity({'grain': grain}) + rspec_node['granularity'] = granularity + rspec_node['interfaces'] = [] + if_count=0 + for if_id in node['interface_ids']: + interface = Interface(interfaces[if_id]) + interface['ipv4'] = interface['ip'] + interface['component_id'] = PlXrn(auth=self.driver.hrn, + interface='node%s:eth%s' % (node['node_id'], if_count)).get_urn() + # interfaces in the manifest need a client id + if slice: + interface['client_id'] = "%s:%s" % (node['node_id'], if_id) + rspec_node['interfaces'].append(interface) + if_count+=1 + tags = [PLTag(node_tags[tag_id]) for tag_id in node['node_tag_ids'] if tag_id in node_tags] + rspec_node['tags'] = tags + return rspec_node + + def sliver_to_rspec_node(self, sliver, sites, interfaces, node_tags, \ + pl_initscripts, sliver_allocations): + # get the granularity in second for the reservation system + grain = self.driver.shell.GetLeaseGranularity() + rspec_node = self.node_to_rspec_node(sliver, sites, interfaces, node_tags, pl_initscripts, grain) + # xxx how to retrieve site['login_base'] + rspec_node['expires'] = datetime_to_string(utcparse(sliver['expires'])) + # remove interfaces from manifest + rspec_node['interfaces'] = [] + # add sliver info + rspec_sliver = Sliver({'sliver_id': sliver['urn'], + 'name': sliver['name'], + 'type': 'plab-vserver', + 'tags': []}) + rspec_node['sliver_id'] = rspec_sliver['sliver_id'] + rspec_node['client_id'] = sliver_allocations[sliver['urn']].client_id + if sliver_allocations[sliver['urn']].component_id: + rspec_node['component_id'] = sliver_allocations[sliver['urn']].component_id + rspec_node['slivers'] = [rspec_sliver] + + # slivers always provide the ssh service + login = Login({'authentication': 'ssh-keys', + 'hostname': sliver['hostname'], + 'port':'22', + 'username': sliver['name'], + 'login': sliver['name'] + }) + service = ServicesElement({'login': login, + 'services_user': sliver['services_user']}) + rspec_node['services'] = [service] + return rspec_node + + def get_slice_tags(self, slice): + slice_tag_ids = [] + slice_tag_ids.extend(slice['slice_tag_ids']) + tags = self.driver.shell.GetSliceTags({'slice_tag_id': slice_tag_ids}) + # sorted by node_id + tags_dict = defaultdict(list) + for tag in tags: + tags_dict[tag['node_id']] = tag + return tags_dict - filter = {} + def get_slice_nodes(self, slice, options={}): + nodes_dict = {} + filter = {'peer_id': None} tags_filter = {} - if slice and 'node_ids' in slice and slice['node_ids']: + if slice and slice.get('node_ids'): filter['node_id'] = slice['node_ids'] - tags_filter=filter.copy() - - geni_available = options.get('geni_available') + else: + # there are no nodes to look up + return nodes_dict + tags_filter=filter.copy() + geni_available = options.get('geni_available') if geni_available == True: - filter['boot_state'] = 'boot' - - filter.update({'peer_id': None}) + filter['boot_state'] = 'boot' nodes = self.driver.shell.GetNodes(filter) - - # get the granularity in second for the reservation system - grain = self.driver.shell.GetLeaseGranularity() - - site_ids = [] - interface_ids = [] - tag_ids = [] - nodes_dict = {} for node in nodes: - site_ids.append(node['site_id']) - interface_ids.extend(node['interface_ids']) - tag_ids.extend(node['node_tag_ids']) nodes_dict[node['node_id']] = node - - # get sites - sites_dict = self.get_sites({'site_id': site_ids}) - # get interfaces - interfaces = self.get_interfaces({'interface_id':interface_ids}) - # get tags - node_tags = self.get_node_tags(tags_filter) - # get initscripts - pl_initscripts = self.get_pl_initscripts() - - links = self.get_links(sites_dict, nodes_dict, interfaces) - - rspec_nodes = [] - for node in nodes: - # skip whitelisted nodes - if node['slice_ids_whitelist']: - if not slice or slice['slice_id'] not in node['slice_ids_whitelist']: - continue - rspec_node = Node() - # xxx how to retrieve site['login_base'] - site_id=node['site_id'] - site=sites_dict[site_id] - rspec_node['component_id'] = hostname_to_urn(self.driver.hrn, site['login_base'], node['hostname']) - rspec_node['component_name'] = node['hostname'] - rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn() - rspec_node['authority_id'] = hrn_to_urn(PlXrn.site_hrn(self.driver.hrn, site['login_base']), 'authority+sa') - # do not include boot state ( element) in the manifest rspec - if not slice: - rspec_node['boot_state'] = node['boot_state'] - - #add the exclusive tag to distinguish between Shared and Reservable nodes - if node['node_type'] == 'reservable': - rspec_node['exclusive'] = 'true' + return nodes_dict + + def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = {}): + if rspec_node['sliver_id'] in sliver_allocations: + # set sliver allocation and operational status + sliver_allocation = sliver_allocations[rspec_node['sliver_id']] + if sliver_allocation: + allocation_status = sliver_allocation.allocation_state + if allocation_status == 'geni_allocated': + op_status = 'geni_pending_allocation' + elif allocation_status == 'geni_provisioned': + if rspec_node['boot_state'] == 'boot': + op_status = 'geni_ready' + else: + op_status = 'geni_failed' + else: + op_status = 'geni_unknown' else: - rspec_node['exclusive'] = 'false' - - rspec_node['hardware_types'] = [HardwareType({'name': 'plab-pc'}), - HardwareType({'name': 'pc'})] - # only doing this because protogeni rspec needs - # to advertise available initscripts - rspec_node['pl_initscripts'] = pl_initscripts.values() - # add site/interface info to nodes. - # assumes that sites, interfaces and tags have already been prepared. - site = sites_dict[node['site_id']] - if site['longitude'] and site['latitude']: - location = Location({'longitude': site['longitude'], 'latitude': site['latitude'], 'country': 'unknown'}) - rspec_node['location'] = location - # Granularity - granularity = Granularity({'grain': grain}) - rspec_node['granularity'] = granularity - - rspec_node['interfaces'] = [] - if_count=0 - for if_id in node['interface_ids']: - interface = Interface(interfaces[if_id]) - interface['ipv4'] = interface['ip'] - interface['component_id'] = PlXrn(auth=self.driver.hrn, - interface='node%s:eth%s' % (node['node_id'], if_count)).get_urn() - # interfaces in the manifest need a client id - if slice: - interface['client_id'] = "%s:%s" % (node['node_id'], if_id) - rspec_node['interfaces'].append(interface) - if_count+=1 - - tags = [PLTag(node_tags[tag_id]) for tag_id in node['node_tag_ids']\ - if tag_id in node_tags] - rspec_node['tags'] = tags - if node['node_id'] in slivers: - # add sliver info - sliver = slivers[node['node_id']] - rspec_node['sliver_id'] = sliver['sliver_id'] - rspec_node['slivers'] = [sliver] - for tag in sliver['tags']: - if tag['tagname'] == 'client_id': - rspec_node['client_id'] = tag['value'] - - # slivers always provide the ssh service - login = Login({'authentication': 'ssh-keys', 'hostname': node['hostname'], 'port':'22', 'username': sliver['name']}) - service = Services({'login': login}) - rspec_node['services'] = [service] - rspec_nodes.append(rspec_node) - return (rspec_nodes, links) - + allocation_status = 'geni_unallocated' + # required fields + geni_sliver = {'geni_sliver_urn': rspec_node['sliver_id'], + 'geni_expires': rspec_node['expires'], + 'geni_allocation_status' : allocation_status, + 'geni_operational_status': op_status, + 'geni_error': '', + } + return geni_sliver - def get_leases(self, slice=None, options={}): + def get_leases(self, slice_xrn=None, slice=None, options={}): + if slice_xrn and not slice: + return [] + now = int(time.time()) filter={} filter.update({'clip':now}) @@@ -346,10 -288,14 +349,13 @@@ site_id=lease['site_id'] site=sites_dict[site_id] - rspec_lease['lease_id'] = lease['lease_id'] - rspec_lease['component_id'] = PlXrn(self.driver.hrn, hostname=lease['hostname']).urn - slice_hrn = slicename_to_hrn(self.driver.hrn, lease['name']) - slice_urn = hrn_to_urn(slice_hrn, 'slice') - #rspec_lease['lease_id'] = lease['lease_id'] + rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn, site['login_base'], lease['hostname']) + if slice_xrn: + slice_urn = slice_xrn + slice_hrn = urn_to_hrn(slice_urn) + else: + slice_hrn = slicename_to_hrn(self.driver.hrn, lease['name']) + slice_urn = hrn_to_urn(slice_hrn, 'slice') rspec_lease['slice_id'] = slice_urn rspec_lease['start_time'] = lease['t_from'] rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) / grain @@@ -361,107 -307,35 +367,112 @@@ version_manager = VersionManager() version = version_manager.get_version(version) - if not slice_xrn: - rspec_version = version_manager._get_version(version.type, version.version, 'ad') - else: - rspec_version = version_manager._get_version(version.type, version.version, 'manifest') - - slice, slivers = self.get_slice_and_slivers(slice_xrn) + rspec_version = version_manager._get_version(version.type, version.version, 'ad') rspec = RSpec(version=rspec_version, user_options=options) - if slice and 'expires' in slice: - rspec.xml.set('expires', datetime_to_string(utcparse(slice['expires']))) - - if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'leases': - if slice_xrn and not slivers: - nodes, links = [], [] - else: - nodes, links = self.get_nodes_and_links(slice_xrn, slice, slivers, options) - rspec.version.add_nodes(nodes) + + if not options.get('list_leases') or options['list_leases'] != 'leases': + # get nodes + nodes = self.get_nodes(options) + site_ids = [] + interface_ids = [] + tag_ids = [] + nodes_dict = {} + for node in nodes: + site_ids.append(node['site_id']) + interface_ids.extend(node['interface_ids']) + tag_ids.extend(node['node_tag_ids']) + nodes_dict[node['node_id']] = node + sites = self.get_sites({'site_id': site_ids}) + interfaces = self.get_interfaces({'interface_id':interface_ids}) + node_tags = self.get_node_tags({'node_tag_id': tag_ids}) + pl_initscripts = self.get_pl_initscripts() + # convert nodes to rspec nodes + rspec_nodes = [] + for node in nodes: + rspec_node = self.node_to_rspec_node(node, sites, interfaces, node_tags, pl_initscripts) + rspec_nodes.append(rspec_node) + rspec.version.add_nodes(rspec_nodes) + + # add links + links = self.get_links(sites, nodes_dict, interfaces) rspec.version.add_links(links) - # add sliver defaults - default_sliver = slivers.get(None, []) - if default_sliver: - default_sliver_attribs = default_sliver.get('tags', []) - for attrib in default_sliver_attribs: - logger.info(attrib) - rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value']) - ++ + if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'resources': + leases = self.get_leases(slice_xrn, slice) + rspec.version.add_leases(leases) + return rspec.toxml() + def describe(self, urns, version=None, options={}): + version_manager = VersionManager() + version = version_manager.get_version(version) + rspec_version = version_manager._get_version(version.type, version.version, 'manifest') + rspec = RSpec(version=rspec_version, user_options=options) + + # get slivers + geni_slivers = [] + slivers = self.get_slivers(urns, options) + if slivers: + rspec_expires = datetime_to_string(utcparse(slivers[0]['expires'])) + else: + rspec_expires = datetime_to_string(utcparse(time.time())) + rspec.xml.set('expires', rspec_expires) + + # lookup the sliver allocations + geni_urn = urns[0] + sliver_ids = [sliver['sliver_id'] for sliver in slivers] + constraint = SliverAllocation.sliver_id.in_(sliver_ids) + sliver_allocations = dbsession.query(SliverAllocation).filter(constraint) + sliver_allocation_dict = {} + for sliver_allocation in sliver_allocations: + geni_urn = sliver_allocation.slice_urn + sliver_allocation_dict[sliver_allocation.sliver_id] = sliver_allocation + + if not options.get('list_leases') or options['list_leases'] != 'leases': + # add slivers + site_ids = [] + interface_ids = [] + tag_ids = [] + nodes_dict = {} + for sliver in slivers: + site_ids.append(sliver['site_id']) + interface_ids.extend(sliver['interface_ids']) + tag_ids.extend(sliver['node_tag_ids']) + nodes_dict[sliver['node_id']] = sliver + sites = self.get_sites({'site_id': site_ids}) + interfaces = self.get_interfaces({'interface_id':interface_ids}) + node_tags = self.get_node_tags({'node_tag_id': tag_ids}) + pl_initscripts = self.get_pl_initscripts() + rspec_nodes = [] + for sliver in slivers: + if sliver['slice_ids_whitelist'] and sliver['slice_id'] not in sliver['slice_ids_whitelist']: + continue + rspec_node = self.sliver_to_rspec_node(sliver, sites, interfaces, node_tags, + pl_initscripts, sliver_allocation_dict) + # manifest node element shouldn't contain available attribute + rspec_node.pop('available') + rspec_nodes.append(rspec_node) + geni_sliver = self.rspec_node_to_geni_sliver(rspec_node, sliver_allocation_dict) + geni_slivers.append(geni_sliver) + rspec.version.add_nodes(rspec_nodes) + + # add sliver defaults + #default_sliver = slivers.get(None, []) + #if default_sliver: + # default_sliver_attribs = default_sliver.get('tags', []) + # for attrib in default_sliver_attribs: + # rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value']) + + # add links + links = self.get_links(sites, nodes_dict, interfaces) + rspec.version.add_links(links) + + if not options.get('list_leases') or options['list_leases'] != 'resources': + if slivers: + leases = self.get_leases(slivers[0]) + rspec.version.add_leases(leases) + + return {'geni_urn': geni_urn, + 'geni_rspec': rspec.toxml(), + 'geni_slivers': geni_slivers} diff --cc sfa/planetlab/pldriver.py index 4977fe05,6c88a14f..4bcb7937 --- a/sfa/planetlab/pldriver.py +++ b/sfa/planetlab/pldriver.py @@@ -658,120 -745,89 +658,112 @@@ class PlDriver (Driver) slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes) # add/remove leases - requested_leases = [] - kept_leases = [] - for lease in rspec.version.get_leases(): - requested_lease = {} - if not lease.get('lease_id'): - requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip()) - requested_lease['start_time'] = lease.get('start_time') - requested_lease['duration'] = lease.get('duration') - else: - kept_leases.append(int(lease['lease_id'])) - if requested_lease.get('hostname'): - requested_leases.append(requested_lease) + try: + rspec_requested_leases = rspec.version.get_leases() + leases = slices.verify_slice_leases(slice, rspec_requested_leases, peer) + except: + pass - #requested_leases = [] - #kept_leases = [] - #for lease in rspec.version.get_leases(): - # requested_lease = {} - # if not lease.get('lease_id'): - # requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip()) - # requested_lease['start_time'] = lease.get('start_time') - # requested_lease['duration'] = lease.get('duration') - # else: - # kept_leases.append(int(lease['lease_id'])) - # if requested_lease.get('hostname'): - # requested_leases.append(requested_lease) - - #leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer) - + - leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer) # handle MyPLC peer association. # only used by plc and ple. - slices.handle_peer(site, slice, persons, peer) + slices.handle_peer(site, slice, None, peer) - return aggregate.get_rspec(slice_xrn=slice_urn, - version=rspec.version) + return aggregate.describe([xrn.get_urn()], version=rspec.version) - def delete_sliver (self, slice_urn, slice_hrn, creds, options): - slicename = hrn_to_pl_slicename(slice_hrn) - slices = self.shell.GetSlices({'name': slicename}) - if not slices: - return True - slice = slices[0] - - # leases - leases = self.shell.GetLeases({'name': slicename}) - leases_ids = [lease['lease_id'] for lease in leases ] - # determine if this is a peer slice - # xxx I wonder if this would not need to use PlSlices.get_peer instead - # in which case plc.peers could be deprecated as this here - # is the only/last call to this last method in plc.peers - peer = peers.get_peer(self, slice_hrn) - try: - if peer: - self.shell.UnBindObjectFromPeer('slice', slice['slice_id'], peer) - self.shell.DeleteSliceFromNodes(slicename, slice['node_ids']) - if len(leases_ids) > 0: - self.shell.DeleteLeases(leases_ids) - finally: - if peer: - self.shell.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id']) - return True - - def renew_sliver (self, slice_urn, slice_hrn, creds, expiration_time, options): - slicename = hrn_to_pl_slicename(slice_hrn) - slices = self.shell.GetSlices({'name': slicename}, ['slice_id']) - if not slices: - raise RecordNotFound(slice_hrn) - slice = slices[0] + def provision(self, urns, options={}): + # update users + slices = PlSlices(self) + aggregate = PlAggregate(self) + slivers = aggregate.get_slivers(urns) + slice = slivers[0] + peer = slices.get_peer(slice['hrn']) + sfa_peer = slices.get_sfa_peer(slice['hrn']) + users = options.get('geni_users', []) + persons = slices.verify_persons(None, slice, users, peer, sfa_peer, options=options) + slices.handle_peer(None, None, persons, peer) + # update sliver allocation states and set them to geni_provisioned + sliver_ids = [sliver['sliver_id'] for sliver in slivers] + SliverAllocation.set_allocations(sliver_ids, 'geni_provisioned') + version_manager = VersionManager() + rspec_version = version_manager.get_version(options['geni_rspec_version']) + return self.describe(urns, rspec_version, options=options) + + def delete(self, urns, options={}): + # collect sliver ids so we can update sliver allocation states after + # we remove the slivers. + aggregate = PlAggregate(self) + slivers = aggregate.get_slivers(urns) + if slivers: + slice_id = slivers[0]['slice_id'] + node_ids = [] + sliver_ids = [] + for sliver in slivers: + node_ids.append(sliver['node_id']) + sliver_ids.append(sliver['sliver_id']) + + # determine if this is a peer slice + # xxx I wonder if this would not need to use PlSlices.get_peer instead + # in which case plc.peers could be deprecated as this here + # is the only/last call to this last method in plc.peers + slice_hrn = PlXrn(auth=self.hrn, slicename=slivers[0]['name']).get_hrn() + peer = peers.get_peer(self, slice_hrn) + try: + if peer: + self.shell.UnBindObjectFromPeer('slice', slice_id, peer) + + self.shell.DeleteSliceFromNodes(slice_id, node_ids) + + # delete sliver allocation states + SliverAllocation.delete_allocations(sliver_ids) + finally: + if peer: + self.shell.BindObjectToPeer('slice', slice_id, peer, slice['peer_slice_id']) + + # prepare return struct + geni_slivers = [] + for sliver in slivers: + geni_slivers.append( + {'geni_sliver_urn': sliver['sliver_id'], + 'geni_allocation_status': 'geni_unallocated', + 'geni_expires': datetime_to_string(utcparse(sliver['expires']))}) + return geni_slivers - ++ + def renew (self, urns, expiration_time, options={}): + aggregate = PlAggregate(self) + slivers = aggregate.get_slivers(urns) + if not slivers: + raise SearchFailed(urns) + slice = slivers[0] requested_time = utcparse(expiration_time) record = {'expires': int(datetime_to_epoch(requested_time))} - try: - self.shell.UpdateSlice(slice['slice_id'], record) - return True - except: - return False + self.shell.UpdateSlice(slice['slice_id'], record) + description = self.describe(urns, None, options) + return description['geni_slivers'] + - # remove the 'enabled' tag - def start_slice (self, slice_urn, slice_hrn, creds): - slicename = hrn_to_pl_slicename(slice_hrn) - slices = self.shell.GetSlices({'name': slicename}, ['slice_id']) - if not slices: - raise RecordNotFound(slice_hrn) - slice_id = slices[0]['slice_id'] - slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'}, ['slice_tag_id']) - # just remove the tag if it exists - if slice_tags: - self.shell.DeleteSliceTag(slice_tags[0]['slice_tag_id']) - return 1 + def perform_operational_action (self, urns, action, options={}): + # MyPLC doesn't support operational actions. Lets pretend like it + # supports start, but reject everything else. + action = action.lower() + if action not in ['geni_start']: + raise UnsupportedOperation(action) + + # fault if sliver is not full allocated (operational status is geni_pending_allocation) + description = self.describe(urns, None, options) + for sliver in description['geni_slivers']: + if sliver['geni_operational_status'] == 'geni_pending_allocation': + raise UnsupportedOperation(action, "Sliver must be fully allocated (operational status is not geni_pending_allocation)") + # + # Perform Operational Action Here + # + + geni_slivers = self.describe(urns, None, options)['geni_slivers'] + return geni_slivers # set the 'enabled' tag to 0 - def stop_slice (self, slice_urn, slice_hrn, creds): - slicename = hrn_to_pl_slicename(slice_hrn) + def shutdown (self, xrn, options={}): + xrn = PlXrn(xrn=xrn, type='slice') + slicename = xrn.pl_slicename() slices = self.shell.GetSlices({'name': slicename}, ['slice_id']) if not slices: raise RecordNotFound(slice_hrn) diff --cc sfa/planetlab/plslices.py index ec60f36e,0d76b593..351335e2 --- a/sfa/planetlab/plslices.py +++ b/sfa/planetlab/plslices.py @@@ -197,11 -221,27 +232,27 @@@ class PlSlices nodes = self.driver.shell.GetNodes(slice['node_ids'], ['node_id', 'hostname', 'interface_ids']) current_slivers = [node['hostname'] for node in nodes] + requested_slivers = [] + tags = [] + for node in slivers: + hostname = None + if node.get('component_name'): + hostname = node.get('component_name').strip() + elif node.get('component_id'): + hostname = xrn_to_hostname(node.get('component_id').strip()) + if node.get('client_id'): + tags.append({'slicename': slice['name'], + 'tagname': 'client_id', + 'value': node['client_id'], + 'node': hostname}) + if hostname: + requested_slivers.append(hostname) + # remove nodes not in rspec - deleted_nodes = list(set(current_slivers).difference(requested_slivers)) + deleted_nodes = list(set(current_slivers).difference(slivers.keys())) # add nodes from rspec - added_nodes = list(set(requested_slivers).difference(current_slivers)) + added_nodes = list(set(slivers.keys()).difference(current_slivers)) try: if peer: diff --cc sfa/rspecs/elements/node.py index 26fcfdd5,7c467f4c..e0f65e40 --- a/sfa/rspecs/elements/node.py +++ b/sfa/rspecs/elements/node.py @@@ -1,8 -1,9 +1,9 @@@ from sfa.rspecs.elements.element import Element -class Node(Element): +class NodeElement(Element): fields = [ + 'client_id', 'component_id', 'component_name', 'component_manager_id',