-from sqlalchemy.orm import joinedload
-from sfa.storage.model import RegRecord, RegUser, RegSlice, RegKey
-from sfa.iotlab.iotlabpostgres import TestbedAdditionalSfaDB, LeaseTableXP
-from sfa.iotlab.OARrestapi import OARrestapi
-from sfa.iotlab.LDAPapi import LDAPapi
-
-from sfa.util.xrn import Xrn, hrn_to_urn, get_authority
-
-from sfa.trust.certificate import Keypair, convert_public_key
-from sfa.trust.gid import create_uuid
-from sfa.trust.hierarchy import Hierarchy
-
-from sfa.iotlab.iotlabxrn import xrn_object
-
-class IotlabShell():
- """ Class enabled to use LDAP and OAR api calls. """
-
- _MINIMUM_DURATION = 10 # 10 units of granularity 60 s, 10 mins
-
- def __init__(self, api):
- """Creates an instance of OARrestapi and LDAPapi which will be used to
- issue calls to OAR or LDAP methods.
- Set the time format and the testbed granularity used for OAR
- reservation and leases.
-
- :param config: configuration object from sfa.util.config
- :type config: Config object
- """
- self.api = api
- config = api.config
- self.leases_db = TestbedAdditionalSfaDB(config)
- self.oar = OARrestapi()
- self.ldap = LDAPapi()
- self.time_format = "%Y-%m-%d %H:%M:%S"
- self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
- self.grain = 60 # 10 mins lease minimum, 60 sec granularity
- #import logging, logging.handlers
- #from sfa.util.sfalogging import _SfaLogger
- #sql_logger = _SfaLogger(loggername = 'sqlalchemy.engine', \
- #level=logging.DEBUG)
- return
-
- @staticmethod
- def GetMinExperimentDurationInGranularity():
- """ Returns the minimum allowed duration for an experiment on the
- testbed. In seconds.
-
- """
- return IotlabShell._MINIMUM_DURATION
-
-
- def GetPeers(self, peer_filter=None ):
- """ Gathers registered authorities in SFA DB and looks for specific peer
- if peer_filter is specified.
- :param peer_filter: name of the site authority looked for.
- :type peer_filter: string
- :returns: list of records.
-
- """
-
- existing_records = {}
- existing_hrns_by_types = {}
- logger.debug("IOTLAB_API \tGetPeers peer_filter %s " % (peer_filter))
- all_records = self.api.dbsession().query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
-
- for record in all_records:
- existing_records[(record.hrn, record.type)] = record
- if record.type not in existing_hrns_by_types:
- existing_hrns_by_types[record.type] = [record.hrn]
- else:
- existing_hrns_by_types[record.type].append(record.hrn)
-
- logger.debug("IOTLAB_API \tGetPeer\texisting_hrns_by_types %s "
- % (existing_hrns_by_types))
- records_list = []
-
- try:
- if peer_filter:
- records_list.append(existing_records[(peer_filter,
- 'authority')])
- else:
- for hrn in existing_hrns_by_types['authority']:
- records_list.append(existing_records[(hrn, 'authority')])
-
- logger.debug("IOTLAB_API \tGetPeer \trecords_list %s "
- % (records_list))
-
- except KeyError:
- pass
-
- return_records = records_list
- logger.debug("IOTLAB_API \tGetPeer return_records %s "
- % (return_records))
- return return_records
-
- #TODO : Handling OR request in make_ldap_filters_from_records
- #instead of the for loop
- #over the records' list
- def GetPersons(self, person_filter=None):
- """
- Get the enabled users and their properties from Iotlab LDAP.
- If a filter is specified, looks for the user whose properties match
- the filter, otherwise returns the whole enabled users'list.
-
- :param person_filter: Must be a list of dictionnaries with users
- properties when not set to None.
- :type person_filter: list of dict
-
- :returns: Returns a list of users whose accounts are enabled
- found in ldap.
- :rtype: list of dicts
-
- """
- logger.debug("IOTLAB_API \tGetPersons person_filter %s"
- % (person_filter))
- person_list = []
- if person_filter and isinstance(person_filter, list):
- #If we are looking for a list of users (list of dict records)
- #Usually the list contains only one user record
- for searched_attributes in person_filter:
-
- #Get only enabled user accounts in iotlab LDAP :
- #add a filter for make_ldap_filters_from_record
- person = self.ldap.LdapFindUser(searched_attributes,
- is_user_enabled=True)
- #If a person was found, append it to the list
- if person:
- person_list.append(person)
-
- #If the list is empty, return None
- if len(person_list) is 0:
- person_list = None
-
- else:
- #Get only enabled user accounts in iotlab LDAP :
- #add a filter for make_ldap_filters_from_record
- person_list = self.ldap.LdapFindUser(is_user_enabled=True)
-
- return person_list
-
-
- #def GetTimezone(self):
- #""" Returns the OAR server time and timezone.
- #Unused SA 30/05/13"""
- #server_timestamp, server_tz = self.oar.parser.\
- #SendRequest("GET_timezone")
- #return server_timestamp, server_tz
-
- def DeleteJobs(self, job_id, username):
- """
-
- Deletes the job with the specified job_id and username on OAR by
- posting a delete request to OAR.
-
- :param job_id: job id in OAR.
- :param username: user's iotlab login in LDAP.
- :type job_id: integer
- :type username: string
-
- :returns: dictionary with the job id and if delete has been successful
- (True) or no (False)
- :rtype: dict
-
- """
- logger.debug("IOTLAB_API \tDeleteJobs jobid %s username %s "
- % (job_id, username))
- if not job_id or job_id is -1:
- return
-
- reqdict = {}
- reqdict['method'] = "delete"
- reqdict['strval'] = str(job_id)
-
- answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id',
- reqdict, username)
- if answer['status'] == 'Delete request registered':
- ret = {job_id: True}
- else:
- ret = {job_id: False}
- logger.debug("IOTLAB_API \tDeleteJobs jobid %s \r\n answer %s \
- username %s" % (job_id, answer, username))
- return ret
-
-
-
- ##TODO : Unused GetJobsId ? SA 05/07/12
- #def GetJobsId(self, job_id, username = None ):
- #"""
- #Details about a specific job.
- #Includes details about submission time, jot type, state, events,
- #owner, assigned ressources, walltime etc...
-
- #"""
- #req = "GET_jobs_id"
- #node_list_k = 'assigned_network_address'
- ##Get job info from OAR
- #job_info = self.oar.parser.SendRequest(req, job_id, username)
-
- #logger.debug("IOTLAB_API \t GetJobsId %s " %(job_info))
- #try:
- #if job_info['state'] == 'Terminated':
- #logger.debug("IOTLAB_API \t GetJobsId job %s TERMINATED"\
- #%(job_id))
- #return None
- #if job_info['state'] == 'Error':
- #logger.debug("IOTLAB_API \t GetJobsId ERROR message %s "\
- #%(job_info))
- #return None
-
- #except KeyError:
- #logger.error("IOTLAB_API \tGetJobsId KeyError")
- #return None
-
- #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \
- #node_list_k)
- ##Replaces the previous entry
- ##"assigned_network_address" / "reserved_resources"
- ##with "node_ids"
- #job_info.update({'node_ids':parsed_job_info[node_list_k]})
- #del job_info[node_list_k]
- #logger.debug(" \r\nIOTLAB_API \t GetJobsId job_info %s " %(job_info))
- #return job_info
-
-
- def GetJobsResources(self, job_id, username = None):
- """ Gets the list of nodes associated with the job_id and username
- if provided.
- Transforms the iotlab hostnames to the corresponding
- SFA nodes hrns.
- Rertuns dict key :'node_ids' , value : hostnames list
- :param username: user's LDAP login
- :paran job_id: job's OAR identifier.
- :type username: string
- :type job_id: integer
-
- :returns: dicionary with nodes' hostnames belonging to the job.
- :rtype: dict
- .. warning: Unused. SA 16/10/13
- """
-
- req = "GET_jobs_id_resources"
-
-
- #Get job resources list from OAR
- node_id_list = self.oar.parser.SendRequest(req, job_id, username)
- logger.debug("IOTLAB_API \t GetJobsResources %s " %(node_id_list))
-
- hostname_list = \
- self.__get_hostnames_from_oar_node_ids(node_id_list)
-
-
- #Replaces the previous entry "assigned_network_address" /
- #"reserved_resources" with "node_ids"
- job_info = {'node_ids': hostname_list}
-
- return job_info
-
-
- #def get_info_on_reserved_nodes(self, job_info, node_list_name):
- #"""
- #..warning:unused SA 23/05/13
- #"""
- ##Get the list of the testbed nodes records and make a
- ##dictionnary keyed on the hostname out of it
- #node_list_dict = self.GetNodes()
- ##node_hostname_list = []
- #node_hostname_list = [node['hostname'] for node in node_list_dict]
- ##for node in node_list_dict:
- ##node_hostname_list.append(node['hostname'])
- #node_dict = dict(zip(node_hostname_list, node_list_dict))
- #try :
- #reserved_node_hostname_list = []
- #for index in range(len(job_info[node_list_name])):
- ##job_info[node_list_name][k] =
- #reserved_node_hostname_list[index] = \
- #node_dict[job_info[node_list_name][index]]['hostname']
-
- #logger.debug("IOTLAB_API \t get_info_on_reserved_nodes \
- #reserved_node_hostname_list %s" \
- #%(reserved_node_hostname_list))
- #except KeyError:
- #logger.error("IOTLAB_API \t get_info_on_reserved_nodes KEYERROR " )
-
- #return reserved_node_hostname_list
-
- def GetNodesCurrentlyInUse(self):
- """Returns a list of all the nodes already involved in an oar running
- job.
- :rtype: list of nodes hostnames.
- """
- return self.oar.parser.SendRequest("GET_running_jobs")
-
- def __get_hostnames_from_oar_node_ids(self, oar_id_node_dict,
- resource_id_list ):
- """Get the hostnames of the nodes from their OAR identifiers.
- Get the list of nodes dict using GetNodes and find the hostname
- associated with the identifier.
- :param oar_id_node_dict: full node dictionary list keyed by oar node id
- :param resource_id_list: list of nodes identifiers
- :returns: list of node hostnames.
- """
-
- hostname_list = []
- for resource_id in resource_id_list:
- #Because jobs requested "asap" do not have defined resources
- if resource_id is not "Undefined":
- hostname_list.append(\
- oar_id_node_dict[resource_id]['hostname'])
-
- #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
- return hostname_list
-
- def GetReservedNodes(self, username=None):
- """ Get list of leases. Get the leases for the username if specified,
- otherwise get all the leases. Finds the nodes hostnames for each
- OAR node identifier.
- :param username: user's LDAP login
- :type username: string
- :returns: list of reservations dict
- :rtype: dict list
- """
-
- #Get the nodes in use and the reserved nodes
- reservation_dict_list = \
- self.oar.parser.SendRequest("GET_reserved_nodes", \
- username = username)
-
- # Get the full node dict list once for all
- # so that we can get the hostnames given their oar node id afterwards
- # when the reservations are checked.
- full_nodes_dict_list = self.GetNodes()
- #Put the full node list into a dictionary keyed by oar node id
- oar_id_node_dict = {}
- for node in full_nodes_dict_list:
- oar_id_node_dict[node['oar_id']] = node
-
- for resa in reservation_dict_list:
- logger.debug ("GetReservedNodes resa %s"%(resa))
- #dict list of hostnames and their site
- resa['reserved_nodes'] = \
- self.__get_hostnames_from_oar_node_ids(oar_id_node_dict,
- resa['resource_ids'])
-
- #del resa['resource_ids']
- return reservation_dict_list
-
- def GetNodes(self, node_filter_dict=None, return_fields_list=None):
- """
-
- Make a list of iotlab nodes and their properties from information
- given by OAR. Search for specific nodes if some filters are
- specified. Nodes properties returned if no return_fields_list given:
- 'hrn','archi','mobile','hostname','site','boot_state','node_id',
- 'radio','posx','posy','oar_id','posz'.
-
- :param node_filter_dict: dictionnary of lists with node properties. For
- instance, if you want to look for a specific node with its hrn,
- the node_filter_dict should be {'hrn': [hrn_of_the_node]}
- :type node_filter_dict: dict
- :param return_fields_list: list of specific fields the user wants to be
- returned.
- :type return_fields_list: list
- :returns: list of dictionaries with node properties
- :rtype: list
-
- """
- node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
- node_dict_list = node_dict_by_id.values()
- logger.debug (" IOTLAB_API GetNodes node_filter_dict %s \
- return_fields_list %s " % (node_filter_dict, return_fields_list))
- #No filtering needed return the list directly
- if not (node_filter_dict or return_fields_list):
- return node_dict_list
-
- return_node_list = []
- if node_filter_dict:
- for filter_key in node_filter_dict:
- try:
- #Filter the node_dict_list by each value contained in the
- #list node_filter_dict[filter_key]
- for value in node_filter_dict[filter_key]:
- for node in node_dict_list:
- if node[filter_key] == value:
- if return_fields_list:
- tmp = {}
- for k in return_fields_list:
- tmp[k] = node[k]
- return_node_list.append(tmp)
- else:
- return_node_list.append(node)
- except KeyError:
- logger.log_exc("GetNodes KeyError")
- return