def merge(self, in_rspec): """ Merge contents for specified rspec with current rspec """ if not in_rspec: return from sfa.rspecs.rspec import RSpec if isinstance(in_rspec, RSpec): rspec = in_rspec else: rspec = RSpec(in_rspec) if rspec.version.type.lower() == 'protogeni': from sfa.rspecs.rspec_converter import RSpecConverter in_rspec = RSpecConverter.to_sfa_rspec(rspec.toxml()) rspec = RSpec(in_rspec) # just copy over all networks current_networks = self.get_networks() networks = rspec.version.get_networks() for network in networks: current_network = network.get('name') if current_network and current_network not in current_networks: self.xml.append(network.element) current_networks.append(current_network)
def to_sfa_rspec(rspec, content_type=None): if not isinstance(rspec, RSpec): pg_rspec = RSpec(rspec) else: pg_rspec = rspec version_manager = VersionManager() sfa_version = version_manager._get_version('sfa', '1') sfa_rspec = RSpec(version=sfa_version) #nodes = pg_rspec.version.get_nodes() #sfa_rspec.version.add_nodes(nodes()) #sfa_rspec.version.add_links(pg_rspec.version.get_links()) #return sfa_rspec.toxml() # get network networks = pg_rspec.version.get_networks() network_hrn = networks[0]["name"] network_element = sfa_rspec.xml.add_element('network', name=network_hrn, id=network_hrn) # get nodes pg_nodes_elements = pg_rspec.version.get_nodes() nodes_with_slivers = pg_rspec.version.get_nodes_with_slivers() i = 1 for pg_node in pg_nodes_elements: attribs = dict(pg_node.items()) attribs['id'] = 'n' + str(i) node_element = network_element.add_element('node') for attrib in attribs: if type(attribs[attrib]) == str: node_element.set(attrib, attribs[attrib]) urn = pg_node["component_id"] if urn: if type(urn) == list: # legacy code, not sure if urn is ever a list... urn = urn[0] hostname = Xrn.urn_split(urn)[-1] hostname_element = node_element.add_element('hostname') hostname_element.set_text(hostname) if hostname in nodes_with_slivers: node_element.add_element('sliver') for hardware_type in pg_node["hardware_types"]: if "name" in hardware_type: node_element.add_element("hardware_type", name=hardware_type["name"]) # just copy over remaining child elements #for child in pg_node_element.getchildren(): # node_element.append(transform(child).getroot()) i = i + 1 return sfa_rspec.toxml()
def allocate(self, urn, rspec_string, expiration, options={}): xrn = Xrn(urn) aggregate = OSAggregate(self) # assume first user is the caller and use their context # for the ec2/euca api connection. Also, use the first users # key as the project key. key_name = None if len(users) > 1: key_name = aggregate.create_instance_key(xrn.get_hrn(), users[0]) # collect public keys users = options.get('geni_users', []) pubkeys = [] for user in users: pubkeys.extend(user['keys']) rspec = RSpec(rspec_string) instance_name = hrn_to_os_slicename(slice_hrn) tenant_name = OSXrn(xrn=slice_hrn, type='slice').get_tenant_name() slivers = aggregate.run_instances(instance_name, tenant_name, \ rspec_string, key_name, pubkeys) # update all sliver allocation states setting then to geni_allocated sliver_ids = [sliver.id for sliver in slivers] dbsession = self.api.dbsession() SliverAllocation.set_allocations(sliver_ids, 'geni_provisioned', dbsession) return aggregate.describe(urns=[urn], version=rspec.version)
def parse_manifest(cls, rspec, rspec_version = 'GENI 3', slice_urn = None, start_time = None): rspec = RSpec(rspec, version=rspec_version) _resources = cls._get_resources(rspec) _nodes = cls._get_nodes(rspec) # XXX Not supported yet #_channels = cls._get_channels(rspec) #_links = cls._get_links(rspec) _leases = cls._get_leases(rspec) # XXX Until WiLab supports Leases end_time = cls._get_expiration(rspec) if start_time is None: start_time = 1388530800 resources = list() resources.extend(cls._process_resources(_resources)) resources.extend(cls._process_nodes(_nodes)) #resources.extend(cls._process_channels(_channels)) #resources.extend(cls._process_links(_links)) Log.warning("XXX Until WiLab supports Leases") # XXX Generate Leases based on the Resources instead of Leases leases = cls._process_leases(resources, slice_urn, start_time, end_time) return {'resource': resources, 'lease': leases }
def describe(self, urns, version=None, options={}): # update nova connection tenant_name = OSXrn(xrn=urns[0], type='slice').get_tenant_name() self.driver.shell.nova_manager.connect(tenant=tenant_name) instances = self.get_instances(urns) # lookup the sliver allocations sliver_ids = [sliver['sliver_id'] for sliver in slivers] constraint = SliverAllocation.sliver_id.in_(sliver_ids) sliver_allocations = self.driver.api.dbsession().query(SliverAllocation).filter(constraint) sliver_allocation_dict = {} for sliver_allocation in sliver_allocations: sliver_allocation_dict[sliver_allocation.sliver_id] = sliver_allocation geni_slivers = [] rspec_nodes = [] for instance in instances: rspec_nodes.append(self.instance_to_rspec_node(instance)) geni_sliver = self.instance_to_geni_sliver(instance, sliver_sllocation_dict) geni_slivers.append(geni_sliver) 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) rspec.xml.set('expires', datetime_to_string(utcparse(time.time()))) rspec.version.add_nodes(rspec_nodes) result = {'geni_urn': Xrn(urns[0]).get_urn(), 'geni_rspec': rspec.toxml(), 'geni_slivers': geni_slivers} return result
def allocate(self, urn, rspec_string, expiration, options={}): xrn = Xrn(urn) aggregate = DummyAggregate(self) slices = DummySlices(self) slice_record = None users = options.get('geni_users', []) if users: slice_record = users[0].get('slice_record', {}) # parse rspec rspec = RSpec(rspec_string) requested_attributes = rspec.version.get_slice_attributes() # ensure slice record exists slice = slices.verify_slice(xrn.hrn, slice_record, expiration=expiration, options=options) # ensure person records exists #persons = slices.verify_persons(xrn.hrn, slice, users, peer, sfa_peer, options=options) # add/remove slice from nodes request_nodes = rspec.version.get_nodes_with_slivers() nodes = slices.verify_slice_nodes(urn, slice, request_nodes) return aggregate.describe([xrn.get_urn()], version=rspec.version)
def merge(self, in_rspec): """ Merge contents for specified rspec with current rspec """ from sfa.rspecs.rspec import RSpec # just copy over all the child elements under the root element if isinstance(in_rspec, basestring): in_rspec = RSpec(in_rspec) nodes = in_rspec.version.get_nodes() # protogeni rspecs need to advertise the availabel sliver types main_nodes = [] for node in nodes: if not node['component_name']: # this node element is part of a lease continue if not node.has_key('sliver') or not node['sliver']: node['sliver'] = {'name': 'plab-vserver'} main_nodes.append(node) self.add_nodes(main_nodes) self.add_links(in_rspec.version.get_links()) # Leases leases = in_rspec.version.get_leases() self.add_leases(leases)
def list_resources(self, version=None, options={}): version_manager = VersionManager() version = version_manager.get_version(version) rspec_version = version_manager._get_version(version.type, version.version, 'ad') rspec = RSpec(version=version, user_options=options) nodes = self.get_aggregate_nodes() rspec.version.add_nodes(nodes) return rspec.toxml()
def Provision(self, api, xrn, creds, options): call_id = options.get('call_id') if Callids().already_handled(call_id): return "" version_manager = VersionManager() def _Provision(aggregate, server, xrn, credential, options): tStart = time.time() try: # Need to call GetVersion at an aggregate to determine the supported # rspec type/format beofre calling CreateSliver at an Aggregate. server_version = api.get_cached_server_version(server) result = server.Provision(xrn, credential, options) return {"aggregate": aggregate, "result": result, "elapsed": time.time()-tStart, "status": "success"} except: logger.log_exc('Something wrong in _Allocate with URL %s'%server.url) return {"aggregate": aggregate, "elapsed": time.time()-tStart, "status": "exception", "exc_info": sys.exc_info()} # attempt to use delegated credential first cred = api.getDelegatedCredential(creds) if not cred: cred = api.getCredential() # get the callers hrn valid_cred = api.auth.checkCredentials(creds, 'createsliver', xrn)[0] caller_hrn = Credential(cred=valid_cred).get_gid_caller().get_hrn() multiclient = MultiClient() for aggregate in api.aggregates: # prevent infinite loop. Dont send request back to caller # unless the caller is the aggregate's SM if caller_hrn == aggregate and aggregate != api.hrn: continue interface = api.aggregates[aggregate] server = api.server_proxy(interface, cred) # Just send entire RSpec to each aggregate multiclient.run(_Provision, aggregate, server, xrn, [cred], options) results = multiclient.get_results() manifest_version = version_manager._get_version('GENI', '3', 'manifest') result_rspec = RSpec(version=manifest_version) geni_slivers = [] geni_urn = None for result in results: self.add_slicemgr_stat(result_rspec, "Provision", result["aggregate"], result["elapsed"], result["status"], result.get("exc_info",None)) if result["status"]=="success": try: res = result['result']['value'] geni_urn = res['geni_urn'] result_rspec.version.merge(ReturnValue.get_value(res['geni_rspec'])) geni_slivers.extend(res['geni_slivers']) except: api.logger.log_exc("SM.Provision: Failed to merge aggregate rspec") return { 'geni_urn': geni_urn, 'geni_rspec': result_rspec.toxml(), 'geni_slivers': geni_slivers }
def run_instances(self, instance_name, tenant_name, rspec, key_name, pubkeys): #logger.debug('Reserving an instance: image: %s, flavor: ' \ # '%s, key: %s, name: %s' % \ # (image_id, flavor_id, key_name, slicename)) # make sure a tenant exists for this slice tenant = self.create_tenant(tenant_name) # add the sfa admin user to this tenant and update our nova client connection # to use these credentials for the rest of this session. This emsures that the instances # we create will be assigned to the correct tenant. sfa_admin_user = self.driver.shell.auth_manager.users.find(name=self.driver.shell.auth_manager.opts['OS_USERNAME']) user_role = self.driver.shell.auth_manager.roles.find(name='user') admin_role = self.driver.shell.auth_manager.roles.find(name='admin') self.driver.shell.auth_manager.roles.add_user_role(sfa_admin_user, admin_role, tenant) self.driver.shell.auth_manager.roles.add_user_role(sfa_admin_user, user_role, tenant) self.driver.shell.nova_manager.connect(tenant=tenant.name) authorized_keys = "\n".join(pubkeys) files = {'/root/.ssh/authorized_keys': authorized_keys} rspec = RSpec(rspec) requested_instances = defaultdict(list) # iterate over clouds/zones/nodes slivers = [] for node in rspec.version.get_nodes_with_slivers(): instances = node.get('slivers', []) if not instances: continue for instance in instances: try: metadata = {} flavor_id = self.driver.shell.nova_manager.flavors.find(name=instance['name']) image = instance.get('disk_image') if image and isinstance(image, list): image = image[0] else: raise InvalidRSpec("Must specify a disk_image for each VM") image_id = self.driver.shell.nova_manager.images.find(name=image['name']) fw_rules = instance.get('fw_rules', []) group_name = self.create_security_group(instance_name, fw_rules) metadata['security_groups'] = group_name if node.get('component_id'): metadata['component_id'] = node['component_id'] if node.get('client_id'): metadata['client_id'] = node['client_id'] server = self.driver.shell.nova_manager.servers.create( flavor=flavor_id, image=image_id, key_name = key_name, security_groups = [group_name], files=files, meta=metadata, name=instance_name) slivers.append(server) except Exception, err: logger.log_exc(err)
def call(self, xrn, creds, rspec, options): xrn = Xrn(xrn, type='slice') self.api.logger.info("interface: %s\ttarget-hrn: %s\tmethod-name: %s" % (self.api.interface, xrn.get_hrn(), self.name)) (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for')) # Find the valid credentials valid_creds = self.api.auth.checkCredentials( creds, 'createsliver', xrn.get_hrn(), speaking_for_hrn=speaking_for) # use the expiration from the first valid credential to determine when # the slivers should expire. expiration = datetime_to_string( Credential(cred=valid_creds[0]).expiration) # make sure request is not empty slivers = RSpec(rspec).version.get_nodes_with_slivers() if not slivers: raise InvalidRSpec( "Missing <sliver_type> or <sliver> element. Request rspec must explicitly allocate slivers" ) # flter rspec through sfatables if self.api.interface in ['aggregate']: chain_name = 'INCOMING' elif self.api.interface in ['slicemgr']: chain_name = 'FORWARD-INCOMING' self.api.logger.debug("Allocate: sfatables on chain %s" % chain_name) origin_hrn = Credential(cred=valid_creds[0]).get_gid_caller().get_hrn() self.api.logger.info( "interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s" % (self.api.interface, origin_hrn, xrn, self.name)) rspec = run_sfatables(chain_name, xrn.get_hrn(), origin_hrn, rspec) slivers = RSpec(rspec).version.get_nodes_with_slivers() if not slivers: raise SfatablesRejected(slice_xrn) result = self.api.manager.Allocate(self.api, xrn.get_urn(), creds, rspec, expiration, options) return result
def to_sfa_rspec(in_rspec, content_type=None): rspec = RSpec(in_rspec) version_manager = VersionManager() sfa_version = version_manager._get_version('sfa', '1') pg_version = version_manager._get_version('protogeni', '2') if rspec.version.type.lower() == sfa_version.type.lower(): return in_rspec elif rspec.version.type.lower() == pg_version.type.lower(): return PGRSpecConverter.to_sfa_rspec(in_rspec, content_type) else: return in_rspec
def list_resources(self, version=None, options={}): """ Returns an advertisement Rspec of available resources at this aggregate. This Rspec contains a resource listing along with their description, providing sufficient information for clients to be able to select among available resources. :param options: various options. The valid options are: {boolean geni_compressed <optional>; struct geni_rspec_version { string type; #case insensitive , string version; # case insensitive}} . The only mandatory options if options is specified is geni_rspec_version. :type options: dictionary :returns: On success, the value field of the return struct will contain a geni.rspec advertisment RSpec :rtype: Rspec advertisement in xml. .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#RSpecdatatype .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#ListResources """ version_manager = VersionManager() version = version_manager.get_version(version) rspec_version = version_manager._get_version(version.type, version.version, 'ad') rspec = RSpec(version=rspec_version, user_options=options) # variable ldap_username to be compliant with get_all_leases # prototype. Now unused in geni-v3 since we are getting all the leases # here ldap_username = None if not options.get( 'list_leases') or options['list_leases'] != 'leases': # get nodes nodes_dict = self.get_nodes(options) # no interfaces on iotlab nodes # convert nodes to rspec nodes rspec_nodes = [] for node_id in nodes_dict: node = nodes_dict[node_id] rspec_node = self.node_to_rspec_node(node) 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) if not options.get('list_leases') or options.get('list_leases') \ and options['list_leases'] != 'resources': leases = self.get_all_leases(ldap_username) 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 = self.driver.api.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 # add slivers nodes_dict = {} for sliver in slivers: nodes_dict[sliver['node_id']] = sliver rspec_nodes = [] for sliver in slivers: rspec_node = self.sliver_to_rspec_node(sliver, sliver_allocation_dict) 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) return { 'geni_urn': geni_urn, 'geni_rspec': rspec.toxml(), 'geni_slivers': geni_slivers }
def parse(cls, rspec, rspec_version = 'GENI 3', slice_urn = None): rspec = RSpec(rspec, version=rspec_version) _resources = cls._get_resources(rspec) _nodes = cls._get_nodes(rspec) _channels = cls._get_channels(rspec) _links = cls._get_links(rspec) _leases = cls._get_leases(rspec) resources = list() resources.extend(cls._process_resources(_resources)) resources.extend(cls._process_nodes(_nodes)) resources.extend(cls._process_channels(_channels)) resources.extend(cls._process_links(_links)) leases = cls._process_leases(_leases) return {'resource': resources, 'lease': leases }
def create_sliver(self, slice_urn, slice_hrn, creds, rspec_string, users, options): aggregate = NitosAggregate(self) slices = NitosSlices(self) sfa_peer = slices.get_sfa_peer(slice_hrn) slice_record = None if users: slice_record = users[0].get('slice_record', {}) # parse rspec rspec = RSpec(rspec_string, version='NITOS 1') # ensure slice record exists slice = slices.verify_slice(slice_hrn, slice_record, sfa_peer, options=options) # ensure user records exists users = slices.verify_users(slice_hrn, slice, users, sfa_peer, options=options) # add/remove leases (nodes and channels) # a lease in Nitos RSpec case is a reservation of nodes and channels grouped by (slice,timeslot) rspec_requested_leases = rspec.version.get_leases() rspec_requested_nodes = [] rspec_requested_channels = [] for lease in rspec_requested_leases: if lease['type'] == 'node': lease.pop('type', None) rspec_requested_nodes.append(lease) else: lease.pop('type', None) rspec_requested_channels.append(lease) nodes = slices.verify_slice_leases_nodes(slice, rspec_requested_nodes) channels = slices.verify_slice_leases_channels( slice, rspec_requested_channels) return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
def list_resources(self, version=None, options={}): version_manager = VersionManager() version = version_manager.get_version(version) rspec_version = version_manager._get_version(version.type, version.version, 'ad') rspec = RSpec(version=rspec_version, user_options=options) 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) if not options.get('list_leases') or options.get( 'list_leases') and options['list_leases'] != 'resources': leases = self.get_leases() rspec.version.add_leases(leases) return rspec.toxml()
def parse_sfa_rspec(self, rspec_string): """ Parse the RSpec XML as a string. """ # rspec_type and rspec_version should be set in the config of the platform, # we use GENIv3 as default one if not if self.config: if 'rspec_type' and 'rspec_version' in self.config: rspec_version = self.config['rspec_type'] + ' ' + self.config[ 'rspec_version'] else: rspec_version = 'GENI 3' self._log.debug(rspec_version) rspec = RSpec(rspec_string, version=rspec_version) try: nodes = rspec.version.get_nodes() except Exception, e: self._log.warn("Could not retrieve nodes in RSpec: %s" % e)
def get_rspec(self, slice_xrn=None, version=None, options={}): 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 = 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': nodes = self.get_nodes(slice_xrn, slice, slivers, options) rspec.version.add_nodes(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: logger.info(attrib) rspec.version.add_default_sliver_attribute( attrib['tagname'], attrib['value']) # add wifi channels channels = self.get_channels(slice, options) rspec.version.add_channels(channels) if not options.get('list_leases') or options.get( 'list_leases') and options['list_leases'] != 'resources': leases_channels = self.get_leases_and_channels(slice, slice_xrn) rspec.version.add_leases(leases_channels) return rspec.toxml()
def Describe(self, api, creds, xrns, options): def _Describe(server, xrn, creds, options): return server.Describe(xrn, creds, options) call_id = options.get('call_id') if Callids().already_handled(call_id): return {} # attempt to use delegated credential first cred = api.getDelegatedCredential(creds) if not cred: cred = api.getCredential() multiclient = MultiClient() for aggregate in api.aggregates: interface = api.aggregates[aggregate] server = api.server_proxy(interface, cred) multiclient.run (_Describe, server, xrns, [cred], options) results = [ReturnValue.get_value(result) for result in multiclient.get_results()] # get rid of any void result - e.g. when call_id was hit, where by convention we return {} results = [ result for result in results if result and result.get('geni_urn')] # do not try to combine if there's no result if not results : return {} # otherwise let's merge stuff version_manager = VersionManager() manifest_version = version_manager._get_version('GENI', '3', 'manifest') result_rspec = RSpec(version=manifest_version) geni_slivers = [] geni_urn = None for result in results: try: geni_urn = result['geni_urn'] result_rspec.version.merge(ReturnValue.get_value(result['geni_rspec'])) geni_slivers.extend(result['geni_slivers']) except: api.logger.log_exc("SM.Provision: Failed to merge aggregate rspec") return { 'geni_urn': geni_urn, 'geni_rspec': result_rspec.toxml(), 'geni_slivers': geni_slivers }
def list_resources(self, version = None, options={}): version_manager = VersionManager() version = version_manager.get_version(version) rspec_version = version_manager._get_version(version.type, version.version, 'ad') rspec = RSpec(version=rspec_version, user_options=options) # get nodes nodes = self.get_nodes(options) nodes_dict = {} for node in nodes: nodes_dict[node['node_id']] = node # convert nodes to rspec nodes rspec_nodes = [] for node in nodes: rspec_node = self.node_to_rspec_node(node) rspec_nodes.append(rspec_node) rspec.version.add_nodes(rspec_nodes) return rspec.toxml()
def __init__(self, *args): """ SFAv1Parser(rspec) or SFAv1Parser(resources, leases) """ # SFAv1Parser(rspec) # if len(args) == 1: rspec = args[0] self.rspec = RSpec(rspec).version # SFAv1Parser(resources, leases) # elif len(args) == 2: resources = args[0] leases = args[1] self.resources_by_network = {} for r in resources: val = r['urn'] if isinstance(r, dict) else r auth = Xrn(val).authority if not auth: raise Exception, "No authority in specified URN %s" % val network = auth[0] if not network in self.resources_by_network: self.resources_by_network[network] = [] self.resources_by_network[network].append(val) self.leases_by_network = {} for l in leases: val = l['urn'] if isinstance(l, dict) else l[0] auth = Xrn(val).authority if not auth: raise Exception, "No authority in specified URN" network = auth[0] if not network in self.leases_by_network: self.leases_by_network[network] = [] self.leases_by_network[network].append(l)
def merge(self, in_rspec): """ Merge contents for specified rspec with current rspec """ if not in_rspec: return None from sfa.rspecs.rspec import RSpec # just copy over all the child elements under the root element if isinstance(in_rspec, basestring): in_rspec = RSpec(in_rspec) if str(in_rspec.version) == 'OcfOf 1': networks = in_rspec.xml.xpath('//rspec/network') for network in networks: self.xml.xpath('//rspec')[0].append(network) else: nodes = in_rspec.version.get_nodes() for node in nodes: if not node.has_key('sliver') or not node['sliver']: node['sliver'] = {'name': 'plab-vserver'} self.add_nodes(nodes) self.add_links(in_rspec.version.get_links())
def get_rspec(self, slice_xrn=None, login=None, version=None, options=None): """ Returns xml rspec: - a full advertisement rspec with the testbed resources if slice_xrn is not specified.If a lease option is given, also returns the leases scheduled on the testbed. - a manifest Rspec with the leases and nodes in slice's leases if slice_xrn is not None. :param slice_xrn: srn of the slice :type slice_xrn: string :param login: user'uid (ldap login) on cortexlab :type login: string :param version: can be set to sfa or cortexlab :type version: RSpecVersion :param options: used to specify if the leases should also be included in the returned rspec. :type options: dict :returns: Xml Rspec. :rtype: XML """ ldap_username = None rspec = None version_manager = VersionManager() version = version_manager.get_version(version) logger.debug("CortexlabAggregate \t get_rspec ***version %s \ version.type %s version.version %s options %s \r\n" % (version, version.type, version.version, options)) if slice_xrn is None: rspec_version = version_manager._get_version( version.type, version.version, 'ad') else: rspec_version = version_manager._get_version( version.type, version.version, 'manifest') slices, slivers = self.get_slice_and_slivers(slice_xrn, login) if slice_xrn and slices is not None: #Get user associated with this slice #for one_slice in slices : ldap_username = self.find_ldap_username_from_slice(slices[0]) # ldap_username = slices[0]['reg_researchers'][0].__dict__['hrn'] # # ldap_username = slices[0]['user'] # tmp = ldap_username.split('.') # ldap_username = tmp[1] logger.debug("CortexlabAggregate \tget_rspec **** \ LDAP USERNAME %s \r\n" \ % (ldap_username)) #at this point sliver may be empty if no cortexlab job #is running for this user/slice. rspec = RSpec(version=rspec_version, user_options=options) logger.debug("\r\n \r\n CortexlabAggregate \tget_rspec *** \ slice_xrn %s slices %s\r\n \r\n" % (slice_xrn, slices)) if options is not None: lease_option = options['list_leases'] else: #If no options are specified, at least print the resources lease_option = 'all' #if slice_xrn : #lease_option = 'all' if lease_option in ['all', 'resources']: #if not options.get('list_leases') or options.get('list_leases') #and options['list_leases'] != 'leases': nodes = self.get_nodes() logger.debug("\r\n") logger.debug("CortexlabAggregate \t lease_option %s \ get rspec ******* nodes %s" % (lease_option, nodes)) sites_set = set([node['location']['site'] for node in nodes]) #In case creating a job, slice_xrn is not set to None rspec.version.add_nodes(nodes) if slice_xrn and slices is not None: # #Get user associated with this slice # #for one_slice in slices : # ldap_username = slices[0]['reg_researchers'] # # ldap_username = slices[0]['user'] # tmp = ldap_username.split('.') # ldap_username = tmp[1] # # ldap_username = tmp[1].split('_')[0] logger.debug("CortexlabAggregate \tget_rspec **** \ version type %s ldap_ user %s \r\n" \ % (version.type, ldap_username)) #TODO : Change the version of Rspec here in case of pbm -SA 09/01/14 if version.type in ["Cortexlab", "Iotlab"]: rspec.version.add_connection_information( ldap_username, sites_set) default_sliver = slivers.get('default_sliver', []) if default_sliver and len(nodes) is not 0: #default_sliver_attribs = default_sliver.get('tags', []) logger.debug("CortexlabAggregate \tget_rspec **** \ default_sliver%s \r\n" % (default_sliver)) for attrib in default_sliver: rspec.version.add_default_sliver_attribute( attrib, default_sliver[attrib]) if lease_option in ['all', 'leases']: leases = self.get_all_leases(ldap_username) rspec.version.add_leases(leases) logger.debug("CortexlabAggregate \tget_rspec **** \ FINAL RSPEC %s \r\n" % (rspec.toxml())) return rspec.toxml()
template = '<rspec type="advertisement" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 https://github.com/fp7-ofelia/ocf/blob/ocf.rspecs/server_schema.xsd http://www.protogeni.net/resources/rspec/2/ad.xsd"/>' #template = '<rspec type="advertisement" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 /opt/ofelia/vt_manager/src/python/vt_manager/communication/sfa/tests/server_schema.xsd http://www.protogeni.net/resources/rspec/2/ad.xsd"/>' class OcfVtRequest(OcfVt): enabled = True content_type = 'request' schema = 'https://github.com/fp7-ofelia/ocf/blob/ocf.rspecs/vm_schema.xsd' #'/opt/ofelia/vt_manager/src/python/vt_manager/communication/sfa/tests/vm_schema.xsd'#'http://www.protogeni.net/resources/rspec/2/ad.xsd' template = '<rspec type="request" xmlns="http://www.protogeni.net/resources/rspec/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 https://github.com/fp7-ofelia/ocf/blob/ocf.rspecs/vm_schema.xsd http://www.protogeni.net/resources/rspec/2/ad.xsd "/>' #template = '<rspec type="request" xmlns="http://www.protogeni.net/resources/rspec/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 /opt/ofelia/vt_manager/src/python/vt_manager/communication/sfa/tests/vm_schema.xsd http://www.protogeni.net/resources/rspec/2/ad.xsd "/>' #schema = 'http://www.protogeni.net/resources/rspec/2/request.xsd' #template = '<rspec type="request" xmlns="http://www.protogeni.net/resources/rspec/2" xmlns:flack="http://www.protogeni.net/resources/rspec/ext/flack/1" xmlns:plos="http://www.planet-lab.org/resources/sfa/ext/plos/1" xmlns:planetlab="http://www.planet-lab.org/resources/sfa/ext/planetlab/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 http://www.protogeni.net/resources/rspec/2/request.xsd http://www.planet-lab.org/resources/sfa/ext/planetlab/1 http://www.planet-lab.org/resources/sfa/ext/planetlab/1/planetlab.xsd http://www.planet-lab.org/resources/sfa/ext/plos/1 http://www.planet-lab.org/resources/sfa/ext/plos/1/plos.xsd"/>' class OcfVtManifest(OcfVt): enabled = True content_type = 'manifest' schema = 'https://github.com/fp7-ofelia/ocf/blob/ocf.rspecs/server_schema.xsd' #'/opt/ofelia/vt_manager/src/python/vt_manager/communication/sfa/tests/server_schema.xsd'#'http://www.protogeni.net/resources/rspec/2/manifest.xsd' template = '<rspec type="manifest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 https://github.com/fp7-ofelia/ocf/blob/ocf.rspecs/server_schema.xsd http://www.protogeni.net/resources/rspec/2/ad.xsd"/>' #template = '<rspec type="manifest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 /opt/ofelia/vt_manager/src/python/vt_manager/communication/sfa/tests/server_schema.xsd http://www.protogeni.net/resources/rspec/2/ad.xsd"/>' # template = '<rspec type="manifest" xmlns="http://www.protogeni.net/resources/rspec/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 /opt/ofelia/vt_manager/src/python/vt_manager/communication/sfa/tests/server_schema.xsd http://www.protogeni.net/resources/rspec/2/ad.xsd"/>' if __name__ == '__main__': from vt_manager.communication.sfa.rspecs.rspec import RSpec from vt_manager.communication.sfa.rspecs.rspec_elements import * r = RSpec('/tmp/ocf.rspec') r.load_rspec_elements(OcfVt.elements) print r.get(RSpecElements.NODE)
def Allocate(self, api, xrn, creds, rspec_str, expiration, options): call_id = options.get('call_id') if Callids().already_handled(call_id): return "" version_manager = VersionManager() def _Allocate(aggregate, server, xrn, credential, rspec, options): tStart = time.time() try: # Need to call GetVersion at an aggregate to determine the supported # rspec type/format beofre calling CreateSliver at an Aggregate. #server_version = api.get_cached_server_version(server) #if 'sfa' not in server_version and 'geni_api' in server_version: # sfa aggregtes support both sfa and pg rspecs, no need to convert # if aggregate supports sfa rspecs. otherwise convert to pg rspec #rspec = RSpec(RSpecConverter.to_pg_rspec(rspec, 'request')) #filter = {'component_manager_id': server_version['urn']} #rspec.filter(filter) #rspec = rspec.toxml() result = server.Allocate(xrn, credential, rspec, options) return {"aggregate": aggregate, "result": result, "elapsed": time.time()-tStart, "status": "success"} except: logger.log_exc('Something wrong in _Allocate with URL %s'%server.url) return {"aggregate": aggregate, "elapsed": time.time()-tStart, "status": "exception", "exc_info": sys.exc_info()} # Validate the RSpec against PlanetLab's schema --disabled for now # The schema used here needs to aggregate the PL and VINI schemas # schema = "/var/www/html/schemas/pl.rng" rspec = RSpec(rspec_str) # schema = None # if schema: # rspec.validate(schema) # if there is a <statistics> section, the aggregates don't care about it, # so delete it. self.drop_slicemgr_stats(rspec) # attempt to use delegated credential first cred = api.getDelegatedCredential(creds) if not cred: cred = api.getCredential() # get the callers hrn hrn, type = urn_to_hrn(xrn) valid_cred = api.auth.checkCredentials(creds, 'createsliver', hrn)[0] caller_hrn = Credential(cred=valid_cred).get_gid_caller().get_hrn() multiclient = MultiClient() for aggregate in api.aggregates: # prevent infinite loop. Dont send request back to caller # unless the caller is the aggregate's SM if caller_hrn == aggregate and aggregate != api.hrn: continue interface = api.aggregates[aggregate] server = api.server_proxy(interface, cred) # Just send entire RSpec to each aggregate multiclient.run(_Allocate, aggregate, server, xrn, [cred], rspec.toxml(), options) results = multiclient.get_results() manifest_version = version_manager._get_version(rspec.version.type, rspec.version.version, 'manifest') result_rspec = RSpec(version=manifest_version) geni_urn = None geni_slivers = [] for result in results: self.add_slicemgr_stat(result_rspec, "Allocate", result["aggregate"], result["elapsed"], result["status"], result.get("exc_info",None)) if result["status"]=="success": try: res = result['result']['value'] geni_urn = res['geni_urn'] result_rspec.version.merge(ReturnValue.get_value(res['geni_rspec'])) geni_slivers.extend(res['geni_slivers']) except: api.logger.log_exc("SM.Allocate: Failed to merge aggregate rspec") return { 'geni_urn': geni_urn, 'geni_rspec': result_rspec.toxml(), 'geni_slivers': geni_slivers }
if caller_hrn == aggregate and aggregate != api.hrn: continue # get the rspec from the aggregate interface = api.aggregates[aggregate] server = api.server_proxy(interface, cred) multiclient.run(_ListResources, aggregate, server, [cred], options) results = multiclient.get_results() rspec_version = version_manager.get_version(options.get('geni_rspec_version')) if xrn: result_version = version_manager._get_version(rspec_version.type, rspec_version.version, 'manifest') else: result_version = version_manager._get_version(rspec_version.type, rspec_version.version, 'ad') rspec = RSpec(version=result_version) for result in results: self.add_slicemgr_stat(rspec, "ListResources", result["aggregate"], result["elapsed"], result["status"], result.get("exc_info",None)) if result["status"]=="success": res = result['result']['value'] try: rspec.version.merge(ReturnValue.get_value(res)) except: api.logger.log_exc("SM.ListResources: Failed to merge aggregate rspec") # cache the result if self.cache and not xrn: api.logger.debug("SliceManager.ListResources caches advertisement") self.cache.add(version_string, rspec.toxml())
def describe(self, urns, version=None, options={}): """ Retrieve a manifest RSpec describing the resources contained by the named entities, e.g. a single slice or a set of the slivers in a slice. This listing and description should be sufficiently descriptive to allow experimenters to use the resources. :param urns: If a slice urn is supplied and there are no slivers in the given slice at this aggregate, then geni_rspec shall be a valid manifest RSpec, containing no node elements - no resources. :type urns: list or strings :param options: various options. the valid options are: {boolean geni_compressed <optional>; struct geni_rspec_version { string type; #case insensitive , string version; # case insensitive}} :type options: dictionary :returns: On success returns the following dictionary {geni_rspec: <geni.rspec, a Manifest RSpec>, geni_urn: <string slice urn of the containing slice>, geni_slivers:{ geni_sliver_urn: <string sliver urn>, geni_expires: <dateTime.rfc3339 allocation expiration string, as in geni_expires from SliversStatus>, geni_allocation_status: <string sliver state - e.g. geni_allocated or geni_provisioned >, geni_operational_status: <string sliver operational state>, geni_error: <optional string. The field may be omitted entirely but may not be null/None, explaining any failure for a sliver.>} .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#Describe .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns """ 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] logger.debug(" Cortexlabaggregate.PY \tDescribe sliver_ids %s " % (sliver_ids)) constraint = SliverAllocation.sliver_id.in_(sliver_ids) query = self.driver.api.dbsession().query(SliverAllocation) sliver_allocations = query.filter((constraint)).all() logger.debug( " Cortexlabaggregate.PY \tDescribe sliver_allocations %s " % (sliver_allocations)) sliver_allocation_dict = {} for sliver_allocation in sliver_allocations: geni_urn = sliver_allocation.slice_urn sliver_allocation_dict[sliver_allocation.sliver_id] = \ sliver_allocation # add slivers nodes_dict = {} for sliver in slivers: nodes_dict[sliver['node_id']] = sliver rspec_nodes = [] for sliver in slivers: rspec_node = self.sliver_to_rspec_node(sliver, sliver_allocation_dict) rspec_nodes.append(rspec_node) logger.debug( " Cortexlabaggregate.PY \tDescribe sliver_allocation_dict %s " % (sliver_allocation_dict)) geni_sliver = self.rspec_node_to_geni_sliver( rspec_node, sliver_allocation_dict) geni_slivers.append(geni_sliver) logger.debug(" Cortexlabaggregate.PY \tDescribe rspec_nodes %s\ rspec %s " % (rspec_nodes, rspec)) rspec.version.add_nodes(rspec_nodes) return { 'geni_urn': geni_urn, 'geni_rspec': rspec.toxml(), 'geni_slivers': geni_slivers }
def parse(cls, rspec, rspec_version=None, slice_urn=None): resources = list() leases = list() rspec = RSpec(rspec) # Parse leases first, so that they can be completed when encountering # their ids in resources lease_map = dict() # id -> lease_dict elements = rspec.xml.xpath('//ol:lease') network = cls.get_network() for el in elements: try: lease_tmp = cls.dict_from_elt(network, el.element) start = calendar.timegm( dateutil.parser.parse( lease_tmp['valid_from']).utctimetuple()) end = calendar.timegm( dateutil.parser.parse( lease_tmp['valid_until']).utctimetuple()) lease = { 'lease_id': lease_tmp['id'], 'slice': slice_urn, 'start_time': start, 'end_time': end, 'duration': (end - start) / cls.get_grain(), 'granularity': cls.get_grain() } lease_map[lease_tmp['id']] = lease except: import traceback Log.warning("this lease has not the right format") traceback.print_exc() # Parse nodes for tag, resource_type in RESOURCE_TYPES.items(): if ':' in tag: ns, _, tag = tag.partition(':') XPATH_RESOURCE = "//%(ns)s:%(tag)s" else: XPATH_RESOURCE = "//default:%(tag)s | //%(tag)s" elements = rspec.xml.xpath(XPATH_RESOURCE % locals()) for el in elements: resource = cls.dict_from_elt(network, el.element, LIST_ELEMENTS.get(resource_type)) if resource_type in cls.MAP: resource = cls.dict_rename(resource, resource_type) resource['network_hrn'] = network #resource['facility_name'] = 'NITOS' resource['facility_name'] = 'Wireless' if 'hrn' in resource: hrn = resource['hrn'].replace('\\', '') elif 'component_id' in resource: urn = resource['component_id'] hrn, type = urn_to_hrn(urn) resource['hrn'] = hrn resource['urn'] = urn t_hrn = hrn.split('.') if 'omf' in hrn: if t_hrn[1] == 'nitos': resource['testbed_name'] = 'NITOS-Volos' resource['country'] = 'Greece' resource['latitude'] = '39.3666667' resource['longitude'] = '22.9458333' elif t_hrn[1] == 'netmode': resource['testbed_name'] = 'Netmode' resource['country'] = 'Greece' resource['latitude'] = '37.978377' resource['longitude'] = '23.782707' elif t_hrn[1] == 'gaia': resource['testbed_name'] = 'UMU' resource['country'] = 'Spain' resource['latitude'] = '38.023681' resource['longitude'] = '-1.174462' elif t_hrn[1] == 'snu': resource['testbed_name'] = 'SNU' resource['country'] = 'South Korea' resource['latitude'] = '37.460263' resource['longitude'] = '126.953598' elif t_hrn[1] == 'kaist': resource['testbed_name'] = 'KAIST' resource['country'] = 'South Korea' resource['latitude'] = '36.369362' resource['longitude'] = '127.364025' elif t_hrn[1] == 'etri': resource['testbed_name'] = 'ETRI' resource['country'] = 'South Korea' resource['latitude'] = '36.3808653' resource['longitude'] = '127.3650244' elif 'paris' in hrn: resource[ 'testbed_name'] = 'FIT NITOS ' + t_hrn[1].title() # XXX Hardcoded for Paris @ UPMC resource['country'] = 'France' resource['latitude'] = '48.847104' resource['longitude'] = '2.357499' else: resource['testbed_name'] = 'FIT ' + t_hrn[1].title() resource['country'] = 'France' else: if 'component_manager_id' in resource: t, tp = urn_to_hrn(resource['component_manager_id']) resource['testbed_name'] = 'FIT ' + t.title() else: resource['testbed_name'] = 'FIT ' + t_hrn[1].title() #resource['testbed_name'] = 'Nitos' if 'services.login.username' in resource: if resource['services.login.username']: resource['login'] = { 'username': resource['services.login.username'], 'hostname': resource['services.login.hostname'] } resource = set_status(resource) resources.append(resource) # Leases if 'lease_ref.id_ref' in resource: lease_id_refs = resource.pop('lease_ref.id_ref') for lease_id_ref in lease_id_refs: lease = copy.deepcopy(lease_map[lease_id_ref]) lease['resource'] = resource['urn'] leases.append(lease) return {'resource': resources, 'lease': leases}
self.xml.remove_element('//default:available | //available') class PGv2Ad(PGv2): enabled = True content_type = 'ad' schema = 'http://www.protogeni.net/resources/rspec/2/ad.xsd' template = '<rspec type="advertisement" xmlns="http://www.protogeni.net/resources/rspec/2" xmlns:flack="http://www.protogeni.net/resources/rspec/ext/flack/1" xmlns:plos="http://www.planet-lab.org/resources/sfa/ext/plos/1" xmlns:planetlab="http://www.planet-lab.org/resources/sfa/ext/planetlab/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 http://www.protogeni.net/resources/rspec/2/ad.xsd http://www.planet-lab.org/resources/sfa/ext/planetlab/1 http://www.planet-lab.org/resources/sfa/ext/planetlab/1/planetlab.xsd http://www.planet-lab.org/resources/sfa/ext/plos/1 http://www.planet-lab.org/resources/sfa/ext/plos/1/plos.xsd"/>' class PGv2Request(PGv2): enabled = True content_type = 'request' schema = 'http://www.protogeni.net/resources/rspec/2/request.xsd' template = '<rspec type="request" xmlns="http://www.protogeni.net/resources/rspec/2" xmlns:flack="http://www.protogeni.net/resources/rspec/ext/flack/1" xmlns:plos="http://www.planet-lab.org/resources/sfa/ext/plos/1" xmlns:planetlab="http://www.planet-lab.org/resources/sfa/ext/planetlab/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 http://www.protogeni.net/resources/rspec/2/request.xsd http://www.planet-lab.org/resources/sfa/ext/planetlab/1 http://www.planet-lab.org/resources/sfa/ext/planetlab/1/planetlab.xsd http://www.planet-lab.org/resources/sfa/ext/plos/1 http://www.planet-lab.org/resources/sfa/ext/plos/1/plos.xsd"/>' class PGv2Manifest(PGv2): enabled = True content_type = 'manifest' schema = 'http://www.protogeni.net/resources/rspec/2/manifest.xsd' template = '<rspec type="manifest" xmlns="http://www.protogeni.net/resources/rspec/2" xmlns:plos="http://www.planet-lab.org/resources/sfa/ext/plos/1" xmlns:flack="http://www.protogeni.net/resources/rspec/ext/flack/1" xmlns:planetlab="http://www.planet-lab.org/resources/sfa/ext/planetlab/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 http://www.protogeni.net/resources/rspec/2/manifest.xsd http://www.planet-lab.org/resources/sfa/ext/planetlab/1 http://www.planet-lab.org/resources/sfa/ext/planetlab/1/planetlab.xsd http://www.planet-lab.org/resources/sfa/ext/plos/1 http://www.planet-lab.org/resources/sfa/ext/plos/1/plos.xsd"/>' if __name__ == '__main__': from sfa.rspecs.rspec import RSpec from sfa.rspecs.rspec_elements import * r = RSpec('/tmp/pg.rspec') r.load_rspec_elements(PGv2.elements) r.namespaces = PGv2.namespaces print r.get(RSpecElements.NODE)