X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fiotlab%2Fiotlabaggregate.py;h=cffc1eff3e077ce23a211b4269add12029eee866;hb=a18ad5b1dbc2a1dd346784105c89a0714086ebc4;hp=73fca1bcfd191baed41245c6e0b9897578d6dd5e;hpb=efa9ed860628dba98c63b7722f472d922fbe8a87;p=sfa.git diff --git a/sfa/iotlab/iotlabaggregate.py b/sfa/iotlab/iotlabaggregate.py index 73fca1bc..cffc1eff 100644 --- a/sfa/iotlab/iotlabaggregate.py +++ b/sfa/iotlab/iotlabaggregate.py @@ -1,42 +1,57 @@ -#import time +""" +File providing methods to generate valid RSpecs for the Iotlab testbed. +Contains methods to get information on slice, slivers, nodes and leases, +formatting them and turn it into a RSpec. +""" from sfa.util.xrn import hrn_to_urn, urn_to_hrn, get_authority from sfa.rspecs.rspec import RSpec #from sfa.rspecs.elements.location import Location from sfa.rspecs.elements.hardware_type import HardwareType from sfa.rspecs.elements.login import Login -from sfa.rspecs.elements.services import ServicesElement +from sfa.rspecs.elements.services import Services from sfa.rspecs.elements.sliver import Sliver from sfa.rspecs.elements.lease import Lease from sfa.rspecs.elements.granularity import Granularity from sfa.rspecs.version_manager import VersionManager +from sfa.rspecs.elements.versions.iotlabv1Node import IotlabPosition, \ + IotlabNode, IotlabLocation -from sfa.rspecs.elements.versions.iotlabv1Node import IotlabPosition, IotlabNode, \ - IotlabLocation from sfa.util.sfalogging import logger - from sfa.util.xrn import Xrn + def iotlab_xrn_to_hostname(xrn): + """Returns a node's hostname from its xrn. + :param xrn: The nodes xrn identifier. + :type xrn: Xrn (from sfa.util.xrn) + + :returns: node's hostname. + :rtype: string + + """ return Xrn.unescape(Xrn(xrn=xrn, type='node').get_leaf()) + def iotlab_xrn_object(root_auth, hostname): - """Attributes are urn and hrn. -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py - Get the hostname using iotlab_xrn_to_hostname on the urn. + """Creates a valid xrn object from the node's hostname and the authority + of the SFA server. - :return: the iotlab node's xrn -======= - Get the hostname using slab_xrn_to_hostname on the urn. + :param hostname: the node's hostname. + :param root_auth: the SFA root authority. + :type hostname: string + :type root_auth: string - :return: the senslab node's xrn ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py + :returns: the iotlab node's xrn :rtype: Xrn + """ - return Xrn('.'.join( [root_auth, Xrn.escape(hostname)]), type='node') + return Xrn('.'.join([root_auth, Xrn.escape(hostname)]), type='node') + class IotlabAggregate: + """Aggregate manager class for Iotlab. """ sites = {} nodes = {} @@ -55,30 +70,24 @@ class IotlabAggregate: def get_slice_and_slivers(self, slice_xrn, login=None): """ Get the slices and the associated leases if any from the iotlab - testbed. For each slice, get the nodes in the associated lease - and create a sliver with the necessary info and insertinto the sliver - dictionary, keyed on the node hostnames. - Returns a dict of slivers based on the sliver's node_id. - Called by get_rspec. + testbed. One slice can have mutliple leases. + For each slice, get the nodes in the associated lease + and create a sliver with the necessary info and insert it into the + sliver dictionary, keyed on the node hostnames. + Returns a dict of slivers based on the sliver's node_id. + Called by get_rspec. :param slice_xrn: xrn of the slice -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py :param login: user's login on iotlab ldap -======= - :param login: user's login on senslab ldap ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py :type slice_xrn: string :type login: string - :reutnr : a list of slices dict and a dictionary of Sliver object - :rtype: (list, dict) + :returns: a list of slices dict and a list of Sliver object + :rtype: (list, list) -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py - ..note: There is no slivers in iotlab, only leases. -======= - ..note: There is no slivers in senslab, only leases. ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py + .. note: There is no real slivers in iotlab, only leases. The goal + is to be consistent with the SFA standard. """ slivers = {} @@ -89,149 +98,116 @@ class IotlabAggregate: slice_hrn, _ = urn_to_hrn(slice_xrn) slice_name = slice_hrn - slices = self.driver.iotlab_api.GetSlices(slice_filter= str(slice_name), \ - slice_filter_type = 'slice_hrn', \ - login=login) + slices = self.driver.iotlab_api.GetSlices(slice_filter=str(slice_name), + slice_filter_type='slice_hrn', + login=login) - logger.debug("Slabaggregate api \tget_slice_and_slivers \ - sfa_slice %s \r\n slices %s self.driver.hrn %s" \ - %(sfa_slice, slices, self.driver.hrn)) - if slices == []: + logger.debug("IotlabAggregate api \tget_slice_and_slivers \ + sfa_slice %s \r\n slices %s self.driver.hrn %s" + % (sfa_slice, slices, self.driver.hrn)) + if slices == []: return (sfa_slice, slivers) - # sort slivers by node id , if there is a job #and therefore, node allocated to this slice for sfa_slice in slices: try: - node_ids_list = sfa_slice['node_ids'] + node_ids_list = sfa_slice['node_ids'] except KeyError: - logger.log_exc("SLABAGGREGATE \t \ - get_slice_and_slivers No nodes in the slice - KeyError ") + logger.log_exc("IOTLABAGGREGATE \t \ + get_slice_and_slivers No nodes in the slice \ + - KeyError ") continue for node in node_ids_list: sliver_xrn = Xrn(slice_urn, type='sliver', id=node) sliver_xrn.set_authority(self.driver.hrn) - sliver = Sliver({'sliver_id':sliver_xrn.urn, + sliver = Sliver({'sliver_id': sliver_xrn.urn, 'name': sfa_slice['hrn'], -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py 'type': 'iotlab-node', -======= - 'type': 'slab-node', ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py 'tags': []}) slivers[node] = sliver - #Add default sliver attribute : -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py #connection information for iotlab - if get_authority (sfa_slice['hrn']) == self.driver.iotlab_api.root_auth: -======= - #connection information for senslab - if get_authority (sfa_slice['hrn']) == self.driver.slab_api.root_auth: ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py + if get_authority(sfa_slice['hrn']) == self.driver.iotlab_api.root_auth: tmp = sfa_slice['hrn'].split('.') ldap_username = tmp[1].split('_')[0] ssh_access = None - slivers['default_sliver'] = {'ssh': ssh_access , \ - 'login': ldap_username} + slivers['default_sliver'] = {'ssh': ssh_access, + 'login': ldap_username} #TODO get_slice_and_slivers Find the login of the external user - logger.debug("SLABAGGREGATE api get_slice_and_slivers slivers %s "\ - %(slivers)) + logger.debug("IOTLABAGGREGATE api get_slice_and_slivers slivers %s " + % (slivers)) return (slices, slivers) - def get_nodes(self, slices=None, slivers=[], options=None): + """Returns the nodes in the slice using the rspec format, with all the + nodes' properties. + + Fetch the nodes ids in the slices dictionary and get all the nodes + properties from OAR. Makes a rspec dicitonary out of this and returns + it. If the slice does not have any job running or scheduled, that is + it has no reserved nodes, then returns an empty list. + + :param slices: list of slices (record dictionaries) + :param slivers: the list of slivers in all the slices + :type slices: list of dicts + :type slivers: list of Sliver object (dictionaries) + :returns: An empty list if the slice has no reserved nodes, a rspec + list with all the nodes and their properties (a dict per node) + otherwise. + :rtype: list + + .. seealso:: get_slice_and_slivers + + """ # NT: the semantic of this function is not clear to me : # if slice is not defined, then all the nodes should be returned # if slice is defined, we should return only the nodes that # are part of this slice # but what is the role of the slivers parameter ? # So i assume that slice['node_ids'] will be the same as slivers for us - #filter_dict = {} - #if slice_xrn: - #if not slices or not slices['node_ids']: - #return ([],[]) - #tags_filter = {} + slice_nodes_list = [] + if slices is not None: + for one_slice in slices: + try: + slice_nodes_list = one_slice['node_ids'] + # if we are dealing with a slice that has no node just + # return an empty list. In iotlab a slice can have multiple + # jobs scheduled, so it either has at least one lease or + # not at all. + except KeyError: + return [] # get the granularity in second for the reservation system -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py grain = self.driver.iotlab_api.GetLeaseGranularity() - nodes = self.driver.iotlab_api.GetNodes() -======= - grain = self.driver.slab_api.GetLeaseGranularity() - - - nodes = self.driver.slab_api.GetNodes() ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py - #geni_available = options.get('geni_available') - #if geni_available: - #filter['boot_state'] = 'boot' - - #filter.update({'peer_id': None}) -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py - #nodes = self.driver.iotlab_api.GetNodes(filter['hostname']) -======= - #nodes = self.driver.slab_api.GetNodes(filter['hostname']) ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py - - #site_ids = [] - #interface_ids = [] - #tag_ids = [] - nodes_dict = {} - - #for node in nodes: - #nodes_dict[node['node_id']] = node - #logger.debug("SLABAGGREGATE api get_nodes nodes %s "\ - #%(nodes )) - # 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) + nodes_dict = {} #if slices, this means we got to list all the nodes given to this slice # Make a list of all the nodes in the slice before getting their #attributes rspec_nodes = [] - slice_nodes_list = [] - logger.debug("SLABAGGREGATE api get_nodes slice_nodes_list %s "\ - %(slices )) - if slices is not None: - for one_slice in slices: - try: - slice_nodes_list = one_slice['node_ids'] - except KeyError: - pass - #for node in one_slice['node_ids']: - #slice_nodes_list.append(node) -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py + logger.debug("IOTLABAGGREGATE api get_nodes slice_nodes_list %s " + % (slices)) + + reserved_nodes = self.driver.iotlab_api.GetNodesCurrentlyInUse() -======= - reserved_nodes = self.driver.slab_api.GetNodesCurrentlyInUse() ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py - logger.debug("SLABAGGREGATE api get_nodes slice_nodes_list %s "\ - %(slice_nodes_list)) + logger.debug("IOTLABAGGREGATE api get_nodes slice_nodes_list %s " + % (slice_nodes_list)) for node in nodes: nodes_dict[node['node_id']] = node if slice_nodes_list == [] or node['hostname'] in slice_nodes_list: -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py rspec_node = IotlabNode() -======= - rspec_node = SlabNode() ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py # xxx how to retrieve site['login_base'] #site_id=node['site_id'] #site=sites_dict[site_id] @@ -240,27 +216,16 @@ class IotlabAggregate: rspec_node['archi'] = node['archi'] rspec_node['radio'] = node['radio'] -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py - iotlab_xrn = iotlab_xrn_object(self.driver.iotlab_api.root_auth, \ - node['hostname']) + iotlab_xrn = iotlab_xrn_object(self.driver.iotlab_api.root_auth, + node['hostname']) rspec_node['component_id'] = iotlab_xrn.urn -======= - slab_xrn = slab_xrn_object(self.driver.slab_api.root_auth, \ - node['hostname']) - rspec_node['component_id'] = slab_xrn.urn ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py rspec_node['component_name'] = node['hostname'] rspec_node['component_manager_id'] = \ - hrn_to_urn(self.driver.iotlab_api.root_auth, \ + hrn_to_urn(self.driver.iotlab_api.root_auth, 'authority+sa') -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py # Iotlab's nodes are federated : there is only one authority # for all Iotlab sites, registered in SFA. -======= - # Senslab's nodes are federated : there is only one authority - # for all Senslab sites, registered in SFA. ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py # Removing the part including the site # in authority_id SA 27/07/12 rspec_node['authority_id'] = rspec_node['component_manager_id'] @@ -282,17 +247,13 @@ class IotlabAggregate: rspec_node['location'] = location -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py position = IotlabPosition() -======= - position = SlabPosition() ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py for field in position : try: position[field] = node[field] except KeyError, error : - logger.log_exc("SLABAGGREGATE\t get_nodes \ - position %s "%(error)) + logger.log_exc("IOTLABAGGREGATE\t get_nodes \ + position %s "% (error)) rspec_node['position'] = position #rspec_node['interfaces'] = [] @@ -317,17 +278,21 @@ class IotlabAggregate: rspec_nodes.append(rspec_node) return (rspec_nodes) - #def get_all_leases(self, slice_record = None): + def get_all_leases(self): """ + Get list of lease dictionaries which all have the mandatory keys ('lease_id', 'hostname', 'site_id', 'name', 'start_time', 'duration'). All the leases running or scheduled are returned. + :returns: rspec lease dictionary with keys lease_id, component_id, + slice_id, start_time, duration. + :rtype: dict - ..note::There is no filtering of leases within a given time frame. - All the running or scheduled leases are returned. options - removed SA 15/05/2013 + .. note::There is no filtering of leases within a given time frame. + All the running or scheduled leases are returned. options + removed SA 15/05/2013 """ @@ -341,7 +306,7 @@ class IotlabAggregate: #leases = self.driver.iotlab_api.GetLeases(lease_filter) leases = self.driver.iotlab_api.GetLeases() grain = self.driver.iotlab_api.GetLeaseGranularity() - site_ids = [] + # site_ids = [] rspec_leases = [] for lease in leases: #as many leases as there are nodes in the job @@ -349,7 +314,8 @@ class IotlabAggregate: rspec_lease = Lease() rspec_lease['lease_id'] = lease['lease_id'] #site = node['site_id'] - iotlab_xrn = iotlab_xrn_object(self.driver.iotlab_api.root_auth, node) + iotlab_xrn = iotlab_xrn_object(self.driver.iotlab_api.root_auth, + node) rspec_lease['component_id'] = iotlab_xrn.urn #rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn,\ #site, node['hostname']) @@ -360,49 +326,60 @@ class IotlabAggregate: pass rspec_lease['start_time'] = lease['t_from'] rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) \ - / grain + / grain rspec_leases.append(rspec_lease) return rspec_leases + 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 + :param login: user'uid (ldap login) on iotlab + :param version: can be set to sfa or iotlab + :param options: used to specify if the leases should also be included in + the returned rspec. + :type slice_xrn: string + :type login: string + :type version: RSpecVersion + :type options: dict + + :returns: Xml Rspec. + :rtype: XML -#from plc/aggregate.py - def get_rspec(self, slice_xrn=None, login=None, version = None, \ - options=None): + + """ rspec = None version_manager = VersionManager() version = version_manager.get_version(version) logger.debug("IotlabAggregate \t get_rspec ***version %s \ - version.type %s version.version %s options %s \r\n" \ - %(version,version.type,version.version,options)) + 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') + rspec_version = version_manager._get_version(version.type, + version.version, 'ad') else: - rspec_version = version_manager._get_version(version.type, \ - version.version, 'manifest') + rspec_version = version_manager._get_version( + version.type, version.version, 'manifest') slices, slivers = self.get_slice_and_slivers(slice_xrn, login) -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py #at this point sliver may be empty if no iotlab job -======= - #at this point sliver may be empty if no senslab job ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py #is running for this user/slice. rspec = RSpec(version=rspec_version, user_options=options) - - #if slice and 'expires' in slice: - #rspec.xml.set('expires',\ - #datetime_to_string(utcparse(slice['expires'])) - # add sliver defaults - #nodes, links = self.get_nodes(slice, slivers) logger.debug("\r\n \r\n IotlabAggregate \tget_rspec *** \ - slice_xrn %s slices %s\r\n \r\n"\ - %(slice_xrn, slices)) + slice_xrn %s slices %s\r\n \r\n" + % (slice_xrn, slices)) if options is not None: lease_option = options['list_leases'] @@ -412,57 +389,41 @@ class IotlabAggregate: #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(slices, slivers) -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py - logger.debug("\r\n \r\n IotlabAggregate \ lease_option %s \ -======= - logger.debug("\r\n \r\n SlabAggregate \ lease_option %s \ ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py - get rspec ******* nodes %s"\ - %(lease_option, nodes[0])) + logger.debug("\r\n \r\n IotlabAggregate \t lease_option %s \ + get rspec ******* nodes %s" + % (lease_option, nodes[0])) - sites_set = set([node['location']['site'] for node in 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 : + if slice_xrn: #Get user associated with this slice - #user = dbsession.query(RegRecord).filter_by(record_id = \ - #slices['record_id_user']).first() - - #ldap_username = (user.hrn).split('.')[1] - - #for one_slice in slices : ldap_username = slices[0]['hrn'] tmp = ldap_username.split('.') ldap_username = tmp[1].split('_')[0] - if version.type == "Slab": - rspec.version.add_connection_information(ldap_username, \ - sites_set) + if version.type == "Iotlab": + rspec.version.add_connection_information( + ldap_username, sites_set) default_sliver = slivers.get('default_sliver', []) if default_sliver: #default_sliver_attribs = default_sliver.get('tags', []) logger.debug("IotlabAggregate \tget_rspec **** \ - default_sliver%s \r\n" %(default_sliver)) + default_sliver%s \r\n" % (default_sliver)) for attrib in default_sliver: - rspec.version.add_default_sliver_attribute(attrib, \ - default_sliver[attrib]) + rspec.version.add_default_sliver_attribute( + attrib, default_sliver[attrib]) + if lease_option in ['all','leases']: - #leases = self.get_all_leases(slices) leases = self.get_all_leases() rspec.version.add_leases(leases) - -<<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py - #logger.debug("IotlabAggregate \tget_rspec ******* rspec_toxml %s \r\n"\ -======= - #logger.debug("SlabAggregate \tget_rspec ******* rspec_toxml %s \r\n"\ ->>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py - #%(rspec.toxml())) + logger.debug("IotlabAggregate \tget_rspec **** \ + FINAL RSPEC %s \r\n" % (rspec.toxml())) return rspec.toxml()