X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fiotlab%2Fiotlabapi.py;h=f50441d379487a9034b0719c5771421fc1159676;hb=9fd509abe353d65f6f0a6a35c721b9d1694cda23;hp=0c0f79870b2253cb48ef1ca8c99e35afed0e1699;hpb=b0995f45712c5ea9dd26fdf0c4347ccba2d77fce;p=sfa.git diff --git a/sfa/iotlab/iotlabapi.py b/sfa/iotlab/iotlabapi.py index 0c0f7987..f50441d3 100644 --- a/sfa/iotlab/iotlabapi.py +++ b/sfa/iotlab/iotlabapi.py @@ -1,3 +1,9 @@ +""" +File containing the IotlabTestbedAPI, used to interact with nodes, users, +slices, leases and keys, as well as the dedicated iotlab database and table, +holding information about which slice is running which job. + +""" from datetime import datetime from sfa.util.sfalogging import logger @@ -5,9 +11,8 @@ from sfa.util.sfalogging import logger from sfa.storage.alchemy import dbsession from sqlalchemy.orm import joinedload from sfa.storage.model import RegRecord, RegUser, RegSlice, RegKey -from sfa.iotlab.iotlabpostgres import iotlab_dbsession, IotlabXP - -from sfa.iotlab.OARrestapi import OARrestapi +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 @@ -21,6 +26,8 @@ from sfa.iotlab.iotlabaggregate import iotlab_xrn_object class IotlabTestbedAPI(): """ Class enabled to use LDAP and OAR api calls. """ + _MINIMUM_DURATION = 10 # 10 units of granularity 60 s, 10 mins + def __init__(self, config): """Creates an instance of OARrestapi and LDAPapi which will be used to issue calls to OAR or LDAP methods. @@ -30,36 +37,39 @@ class IotlabTestbedAPI(): :param config: configuration object from sfa.util.config :type config: Config object """ + self.iotlab_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 = 1 # 10 mins lease minimum + 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 GetMinExperimentDurationInSec(): - return 600 + def GetMinExperimentDurationInGranularity(): + """ Returns the minimum allowed duration for an experiment on the + testbed. In seconds. + + """ + return IotlabTestbedAPI._MINIMUM_DURATION @staticmethod - def GetPeers (peer_filter=None ): + def GetPeers(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 - :return: list of records. + :returns: list of records. """ existing_records = {} existing_hrns_by_types = {} - logger.debug("IOTLABDRIVER \tGetPeers peer_filter %s, \ - " %(peer_filter)) + logger.debug("IOTLAB_API \tGetPeers peer_filter %s " % (peer_filter)) all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all() for record in all_records: @@ -69,31 +79,29 @@ class IotlabTestbedAPI(): else: existing_hrns_by_types[record.type].append(record.hrn) - - logger.debug("IOTLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\ - %( existing_hrns_by_types)) + 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 : + records_list.append(existing_records[(peer_filter, + 'authority')]) + else: for hrn in existing_hrns_by_types['authority']: - records_list.append(existing_records[(hrn,'authority')]) + records_list.append(existing_records[(hrn, 'authority')]) - logger.debug("IOTLABDRIVER \tGetPeer \trecords_list %s " \ - %(records_list)) + logger.debug("IOTLAB_API \tGetPeer \trecords_list %s " + % (records_list)) except KeyError: pass return_records = records_list - logger.debug("IOTLABDRIVER \tGetPeer return_records %s " \ - %(return_records)) + 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 @@ -102,16 +110,18 @@ class IotlabTestbedAPI(): 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. - :param person_filter: list of dict - :return:Returns a list of users whose accounts are enabled - found in ldap. + + :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("IOTLABDRIVER \tGetPersons person_filter %s" \ - %(person_filter)) + 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) @@ -120,8 +130,8 @@ class IotlabTestbedAPI(): #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) + 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) @@ -146,21 +156,23 @@ class IotlabTestbedAPI(): #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. + 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 job_id: integer :type username: string - :return: dictionary with the job id and if delete has been successful - (True) or no (False) + :returns: dictionary with the job id and if delete has been successful + (True) or no (False) :rtype: dict + """ - logger.debug("IOTLABDRIVER \tDeleteJobs jobid %s username %s "\ - %(job_id, username)) + logger.debug("IOTLAB_API \tDeleteJobs jobid %s username %s " + % (job_id, username)) if not job_id or job_id is -1: return @@ -168,15 +180,14 @@ class IotlabTestbedAPI(): reqdict['method'] = "delete" reqdict['strval'] = str(job_id) - - answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \ - reqdict,username) + answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', + reqdict, username) if answer['status'] == 'Delete request registered': - ret = {job_id : True } + ret = {job_id: True} else: - ret = {job_id :False } - logger.debug("IOTLABDRIVER \tDeleteJobs jobid %s \r\n answer %s \ - username %s" %(job_id, answer, username)) + ret = {job_id: False} + logger.debug("IOTLAB_API \tDeleteJobs jobid %s \r\n answer %s \ + username %s" % (job_id, answer, username)) return ret @@ -194,19 +205,19 @@ class IotlabTestbedAPI(): ##Get job info from OAR #job_info = self.oar.parser.SendRequest(req, job_id, username) - #logger.debug("IOTLABDRIVER \t GetJobsId %s " %(job_info)) + #logger.debug("IOTLAB_API \t GetJobsId %s " %(job_info)) #try: #if job_info['state'] == 'Terminated': - #logger.debug("IOTLABDRIVER \t GetJobsId job %s TERMINATED"\ + #logger.debug("IOTLAB_API \t GetJobsId job %s TERMINATED"\ #%(job_id)) #return None #if job_info['state'] == 'Error': - #logger.debug("IOTLABDRIVER \t GetJobsId ERROR message %s "\ + #logger.debug("IOTLAB_API \t GetJobsId ERROR message %s "\ #%(job_info)) #return None #except KeyError: - #logger.error("IOTLABDRIVER \tGetJobsId KeyError") + #logger.error("IOTLAB_API \tGetJobsId KeyError") #return None #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \ @@ -216,7 +227,7 @@ class IotlabTestbedAPI(): ##with "node_ids" #job_info.update({'node_ids':parsed_job_info[node_list_k]}) #del job_info[node_list_k] - #logger.debug(" \r\nIOTLABDRIVER \t GetJobsId job_info %s " %(job_info)) + #logger.debug(" \r\nIOTLAB_API \t GetJobsId job_info %s " %(job_info)) #return job_info @@ -231,8 +242,9 @@ class IotlabTestbedAPI(): :type username: string :type job_id: integer - :return: dicionary with nodes' hostnames belonging to the job. + :returns: dicionary with nodes' hostnames belonging to the job. :rtype: dict + .. warning: Unused. SA 16/10/13 """ req = "GET_jobs_id_resources" @@ -240,7 +252,7 @@ class IotlabTestbedAPI(): #Get job resources list from OAR node_id_list = self.oar.parser.SendRequest(req, job_id, username) - logger.debug("IOTLABDRIVER \t GetJobsResources %s " %(node_id_list)) + logger.debug("IOTLAB_API \t GetJobsResources %s " %(node_id_list)) hostname_list = \ self.__get_hostnames_from_oar_node_ids(node_id_list) @@ -272,11 +284,11 @@ class IotlabTestbedAPI(): #reserved_node_hostname_list[index] = \ #node_dict[job_info[node_list_name][index]]['hostname'] - #logger.debug("IOTLABDRIVER \t get_info_on_reserved_nodes \ + #logger.debug("IOTLAB_API \t get_info_on_reserved_nodes \ #reserved_node_hostname_list %s" \ #%(reserved_node_hostname_list)) #except KeyError: - #logger.error("IOTLABDRIVER \t get_info_on_reserved_nodes KEYERROR " ) + #logger.error("IOTLAB_API \t get_info_on_reserved_nodes KEYERROR " ) #return reserved_node_hostname_list @@ -287,18 +299,15 @@ class IotlabTestbedAPI(): """ return self.oar.parser.SendRequest("GET_running_jobs") - def __get_hostnames_from_oar_node_ids(self, resource_id_list ): + 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. """ - 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 hostname_list = [] for resource_id in resource_id_list: @@ -310,13 +319,13 @@ class IotlabTestbedAPI(): #hostname_list.append(oar_id_node_dict[resource_id]['hostname']) return hostname_list - def GetReservedNodes(self, username = None): + 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 - :return: list of reservations dict + :returns: list of reservations dict :rtype: dict list """ @@ -325,38 +334,49 @@ class IotlabTestbedAPI(): 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(resa['resource_ids']) + 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): + 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 + 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. + returned. :type return_fields_list: list - :return: list of dictionaries with node properties + :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 (" IOTLABDRIVER GetNodes node_filter_dict %s \ - return_fields_list %s "%(node_filter_dict, return_fields_list)) + 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 @@ -370,7 +390,7 @@ class IotlabTestbedAPI(): for value in node_filter_dict[filter_key]: for node in node_dict_list: if node[filter_key] == value: - if return_fields_list : + if return_fields_list: tmp = {} for k in return_fields_list: tmp[k] = node[k] @@ -388,38 +408,59 @@ class IotlabTestbedAPI(): @staticmethod def AddSlice(slice_record, user_record): - """Add slice to the local iotlab sfa tables if the slice comes - from a federated site and is not yet in the iotlab sfa DB, - although the user has already a LDAP login. - Called by verify_slice during lease/sliver creation. + """ + + Add slice to the local iotlab sfa tables if the slice comes + from a federated site and is not yet in the iotlab sfa DB, + although the user has already a LDAP login. + Called by verify_slice during lease/sliver creation. + :param slice_record: record of slice, must contain hrn, gid, slice_id - and authority of the slice. + and authority of the slice. :type slice_record: dictionary :param user_record: record of the user :type user_record: RegUser + """ sfa_record = RegSlice(hrn=slice_record['hrn'], gid=slice_record['gid'], pointer=slice_record['slice_id'], authority=slice_record['authority']) - logger.debug("IOTLABDRIVER.PY AddSlice sfa_record %s user_record %s" + logger.debug("IOTLAB_API.PY AddSlice sfa_record %s user_record %s" % (sfa_record, user_record)) sfa_record.just_created() dbsession.add(sfa_record) dbsession.commit() #Update the reg-researcher dependance table - sfa_record.reg_researchers = [user_record] + sfa_record.reg_researchers = [user_record] dbsession.commit() return - def GetSites(self, site_filter_name_list = None, return_fields_list = None): + def GetSites(self, site_filter_name_list=None, return_fields_list=None): + """Returns the list of Iotlab's sites with the associated nodes and + the sites' properties as dictionaries. + + Site properties: + ['address_ids', 'slice_ids', 'name', 'node_ids', 'url', 'person_ids', + 'site_tag_ids', 'enabled', 'site', 'longitude', 'pcu_ids', + 'max_slivers', 'max_slices', 'ext_consortium_id', 'date_created', + 'latitude', 'is_public', 'peer_site_id', 'peer_id', 'abbreviated_name'] + Uses the OAR request GET_sites to find the Iotlab's sites. + + :param site_filter_name_list: used to specify specific sites + :param return_fields_list: field that has to be returned + :type site_filter_name_list: list + :type return_fields_list: list + + + """ site_dict = self.oar.parser.SendRequest("GET_sites") #site_dict : dict where the key is the sit ename return_site_list = [] - if not ( site_filter_name_list or return_fields_list): + if not (site_filter_name_list or return_fields_list): return_site_list = site_dict.values() return return_site_list @@ -431,44 +472,46 @@ class IotlabTestbedAPI(): try: tmp[field] = site_dict[site_filter_name][field] except KeyError: - logger.error("GetSites KeyError %s "%(field)) + logger.error("GetSites KeyError %s " % (field)) return None return_site_list.append(tmp) else: - return_site_list.append( site_dict[site_filter_name]) - + return_site_list.append(site_dict[site_filter_name]) return return_site_list - - - #TODO : Check rights to delete person def DeletePerson(self, person_record): - """ Disable an existing account in iotlab LDAP. + """Disable an existing account in iotlab LDAP. + Users and techs can only delete themselves. PIs can only - delete themselves and other non-PIs at their sites. - ins can delete anyone. + delete themselves and other non-PIs at their sites. + ins can delete anyone. + :param person_record: user's record :type person_record: dict - :return: True if successful, False otherwise. + :returns: True if successful, False otherwise. :rtype: boolean + .. todo:: CHECK THAT ONLY THE USER OR ADMIN CAN DEL HIMSELF. """ #Disable user account in iotlab LDAP ret = self.ldap.LdapMarkUserAsDeleted(person_record) - logger.warning("IOTLABDRIVER DeletePerson %s " %(person_record)) + logger.warning("IOTLAB_API DeletePerson %s " % (person_record)) return ret['bool'] - def DeleteSlice(self, slice_record): - """ Deletes the specified slice and kills the jobs associated with - the slice if any, using DeleteSliceFromNodes. + """Deletes the specified slice and kills the jobs associated with + the slice if any, using DeleteSliceFromNodes. - :return: True if all the jobs in the slice have been deleted, - or the list of jobs that could not be deleted otherwise. - :rtype: list or boolean + :param slice_record: record of the slice, must contain oar_job_id, user + :type slice_record: dict + :returns: True if all the jobs in the slice have been deleted, + or the list of jobs that could not be deleted otherwise. + :rtype: list or boolean + + .. seealso:: DeleteSliceFromNodes """ ret = self.DeleteSliceFromNodes(slice_record) @@ -479,7 +522,7 @@ class IotlabTestbedAPI(): delete_failed = [] delete_failed.append(job_id) - logger.info("IOTLABDRIVER DeleteSlice %s answer %s"%(slice_record, \ + logger.info("IOTLAB_API DeleteSlice %s answer %s"%(slice_record, \ delete_failed)) return delete_failed or True @@ -489,7 +532,7 @@ class IotlabTestbedAPI(): Add a federated user straight to db when the user issues a lease request with iotlab nodes and that he has not registered with iotlab yet (that is he does not have a LDAP entry yet). - Uses parts of the routines in SlabImport when importing user from LDAP. + Uses parts of the routines in IotlabImport when importing user from LDAP. Called by AddPerson, right after LdapAddUser. :param user_dict: Must contain email, hrn and pkey to get a GID and be added to the SFA db. @@ -520,7 +563,7 @@ class IotlabTestbedAPI(): pkey) if user_dict['email']: logger.debug("__add_person_to_db \r\n \r\n \ - SLAB IMPORTER PERSON EMAIL OK email %s "\ + IOTLAB IMPORTER PERSON EMAIL OK email %s "\ %(user_dict['email'])) person_gid.set_email(user_dict['email']) @@ -535,63 +578,75 @@ class IotlabTestbedAPI(): def AddPerson(self, record): - """Adds a new account. Any fields specified in records are used, - otherwise defaults are used. Creates an appropriate login by calling - LdapAddUser. + """ + + Adds a new account. Any fields specified in records are used, + otherwise defaults are used. Creates an appropriate login by calling + LdapAddUser. + :param record: dictionary with the sfa user's properties. - :return: The uid of the added person if sucessful, otherwise returns - the error message from LDAP. - :rtype: interger or string + :returns: a dicitonary with the status. If successful, the dictionary + boolean is set to True and there is a 'uid' key with the new login + added to LDAP, otherwise the bool is set to False and a key + 'message' is in the dictionary, with the error message. + :rtype: dict + """ ret = self.ldap.LdapAddUser(record) if ret['bool'] is True: record['hrn'] = self.root_auth + '.' + ret['uid'] - logger.debug("IOTLABDRIVER AddPerson return code %s record %s \r\n "\ - %(ret, record)) + logger.debug("IOTLAB_API AddPerson return code %s record %s " + % (ret, record)) self.__add_person_to_db(record) - return ret['uid'] - else: - return ret['message'] + return ret + + #TODO AddPersonKey 04/07/2012 SA def AddPersonKey(self, person_uid, old_attributes_dict, new_key_dict): """Adds a new key to the specified account. Adds the key to the - iotlab ldap, provided that the person_uid is valid. + iotlab ldap, provided that the person_uid is valid. + Non-admins can only modify their own keys. :param person_uid: user's iotlab login in LDAP :param old_attributes_dict: dict with the user's old sshPublicKey - :param new_key_dict:dict with the user's new sshPublicKey + :param new_key_dict: dict with the user's new sshPublicKey :type person_uid: string :rtype: Boolean - :return: True if the key has been modified, False otherwise. + :returns: True if the key has been modified, False otherwise. """ ret = self.ldap.LdapModify(person_uid, old_attributes_dict, \ new_key_dict) - logger.warning("IOTLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ") + logger.warning("IOTLAB_API AddPersonKey EMPTY - DO NOTHING \r\n ") return ret['bool'] - def DeleteLeases(self, leases_id_list, slice_hrn ): + def DeleteLeases(self, leases_id_list, slice_hrn): """ + Deletes several leases, based on their job ids and the slice - they are associated with. Uses DeleteJobs to delete the jobs - on OAR. Note that one slice can contain multiple jobs, and in this case - all the jobs in the leases_id_list MUST belong to ONE slice, - since there is only one slice hrn provided here. + they are associated with. Uses DeleteJobs to delete the jobs + on OAR. Note that one slice can contain multiple jobs, and in this + case all the jobs in the leases_id_list MUST belong to ONE slice, + since there is only one slice hrn provided here. + :param leases_id_list: list of job ids that belong to the slice whose - slice hrn is provided. - :param slice_hrn: the slice hrn . - ..warning: Does not have a return value since there was no easy - way to handle failure when dealing with multiple job delete. Plus, - there was no easy way to report it to the user. + slice hrn is provided. + :param slice_hrn: the slice hrn. + :type slice_hrn: string + + .. warning:: Does not have a return value since there was no easy + way to handle failure when dealing with multiple job delete. Plus, + there was no easy way to report it to the user. + """ - logger.debug("IOTLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \ + logger.debug("IOTLAB_API DeleteLeases leases_id_list %s slice_hrn %s \ \r\n " %(leases_id_list, slice_hrn)) for job_id in leases_id_list: self.DeleteJobs(job_id, slice_hrn) @@ -714,21 +769,21 @@ class IotlabTestbedAPI(): lease_dict['time_format'] = self.time_format - logger.debug("IOTLABDRIVER.PY \tLaunchExperimentOnOAR slice_user %s\ + logger.debug("IOTLAB_API.PY \tLaunchExperimentOnOAR slice_user %s\ \r\n " %(slice_user)) #Create the request for OAR reqdict = self._create_job_structure_request_for_OAR(lease_dict) # first step : start the OAR job and update the job - logger.debug("IOTLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\ + logger.debug("IOTLAB_API.PY \tLaunchExperimentOnOAR reqdict %s\ \r\n " %(reqdict)) answer = self.oar.POSTRequestToOARRestAPI('POST_job', \ reqdict, slice_user) - logger.debug("IOTLABDRIVER \tLaunchExperimentOnOAR jobid %s " %(answer)) + logger.debug("IOTLAB_API \tLaunchExperimentOnOAR jobid %s " %(answer)) try: jobid = answer['id'] except KeyError: - logger.log_exc("IOTLABDRIVER \tLaunchExperimentOnOAR \ + logger.log_exc("IOTLAB_API \tLaunchExperimentOnOAR \ Impossible to create job %s " %(answer)) return None @@ -736,7 +791,7 @@ class IotlabTestbedAPI(): if jobid : - logger.debug("IOTLABDRIVER \tLaunchExperimentOnOAR jobid %s \ + logger.debug("IOTLAB_API \tLaunchExperimentOnOAR jobid %s \ added_nodes %s slice_user %s" %(jobid, added_nodes, \ slice_user)) @@ -744,8 +799,8 @@ class IotlabTestbedAPI(): return jobid - def AddLeases(self, hostname_list, slice_record, \ - lease_start_time, lease_duration): + def AddLeases(self, hostname_list, slice_record, + lease_start_time, lease_duration): """Creates a job in OAR corresponding to the information provided as parameters. Adds the job id and the slice hrn in the iotlab @@ -762,7 +817,7 @@ class IotlabTestbedAPI(): :type lease_duration: integer """ - logger.debug("IOTLABDRIVER \r\n \r\n \t AddLeases hostname_list %s \ + logger.debug("IOTLAB_API \r\n \r\n \t AddLeases hostname_list %s \ slice_record %s lease_start_time %s lease_duration %s "\ %( hostname_list, slice_record , lease_start_time, \ lease_duration)) @@ -780,22 +835,22 @@ class IotlabTestbedAPI(): end_time = lease_start_time + lease_duration - logger.debug("IOTLABDRIVER \r\n \r\n \t AddLeases TURN ON LOGGING SQL \ + logger.debug("IOTLAB_API \r\n \r\n \t AddLeases TURN ON LOGGING SQL \ %s %s %s "%(slice_record['hrn'], job_id, end_time)) - logger.debug("IOTLABDRIVER \r\n \r\n \t AddLeases %s %s %s " \ + logger.debug("IOTLAB_API \r\n \r\n \t AddLeases %s %s %s " \ %(type(slice_record['hrn']), type(job_id), type(end_time))) - iotlab_ex_row = IotlabXP(slice_hrn = slice_record['hrn'], \ - job_id = job_id, end_time= end_time) + iotlab_ex_row = LeaseTableXP(slice_hrn = slice_record['hrn'], experiment_id=job_id, + end_time= end_time) - logger.debug("IOTLABDRIVER \r\n \r\n \t AddLeases iotlab_ex_row %s" \ + logger.debug("IOTLAB_API \r\n \r\n \t AddLeases iotlab_ex_row %s" \ %(iotlab_ex_row)) - iotlab_dbsession.add(iotlab_ex_row) - iotlab_dbsession.commit() + self.iotlab_db.testbed_session.add(iotlab_ex_row) + self.iotlab_db.testbed_session.commit() - logger.debug("IOTLABDRIVER \t AddLeases hostname_list start_time %s " \ + logger.debug("IOTLAB_API \t AddLeases hostname_list start_time %s " \ %(start_time)) return @@ -803,16 +858,21 @@ class IotlabTestbedAPI(): #Delete the jobs from job_iotlab table def DeleteSliceFromNodes(self, slice_record): - """ Deletes all the running or scheduled jobs of a given slice - given its record. - :param slice_record: record of the slice + """ + + Deletes all the running or scheduled jobs of a given slice + given its record. + + :param slice_record: record of the slice, must contain oar_job_id, user :type slice_record: dict - :return: dict of the jobs'deletion status. Success= True, Failure= - False, for each job id. + :returns: dict of the jobs'deletion status. Success= True, Failure= + False, for each job id. :rtype: dict + """ - logger.debug("IOTLABDRIVER \t DeleteSliceFromNodese %s " %(slice_record)) + logger.debug("IOTLAB_API \t DeleteSliceFromNodes %s " + % (slice_record)) if isinstance(slice_record['oar_job_id'], list): oar_bool_answer = {} @@ -822,8 +882,8 @@ class IotlabTestbedAPI(): oar_bool_answer.update(ret) else: - oar_bool_answer = [self.DeleteJobs(slice_record['oar_job_id'], \ - slice_record['user'])] + oar_bool_answer = [self.DeleteJobs(slice_record['oar_job_id'], + slice_record['user'])] return oar_bool_answer @@ -837,85 +897,113 @@ class IotlabTestbedAPI(): return self.grain + # @staticmethod + # def update_experiments_in_additional_sfa_db( job_oar_list, jobs_psql): + # """ Cleans the iotlab db by deleting expired and cancelled jobs. + # Compares the list of job ids given by OAR with the job ids that + # are already in the database, deletes the jobs that are no longer in + # the OAR job id list. + # :param job_oar_list: list of job ids coming from OAR + # :type job_oar_list: list + # :param job_psql: list of job ids cfrom the database. + # type job_psql: list + # """ + # #Turn the list into a set + # set_jobs_psql = set(jobs_psql) + + # kept_jobs = set(job_oar_list).intersection(set_jobs_psql) + # logger.debug ( "\r\n \t\ update_experiments_in_additional_sfa_db jobs_psql %s \r\n \t \ + # job_oar_list %s kept_jobs %s "%(set_jobs_psql, job_oar_list, kept_jobs)) + # deleted_jobs = set_jobs_psql.difference(kept_jobs) + # deleted_jobs = list(deleted_jobs) + # if len(deleted_jobs) > 0: + # self.iotlab_db.testbed_session.query(LeaseTableXP).filter(LeaseTableXP.job_id.in_(deleted_jobs)).delete(synchronize_session='fetch') + # self.iotlab_db.testbed_session.commit() + + # return + @staticmethod - def update_jobs_in_iotlabdb( job_oar_list, jobs_psql): - """ Cleans the iotlab db by deleting expired and cancelled jobs. - Compares the list of job ids given by OAR with the job ids that - are already in the database, deletes the jobs that are no longer in - the OAR job id list. - :param job_oar_list: list of job ids coming from OAR - :type job_oar_list: list - :param job_psql: list of job ids cfrom the database. - type job_psql: list - """ - #Turn the list into a set - set_jobs_psql = set(jobs_psql) - - kept_jobs = set(job_oar_list).intersection(set_jobs_psql) - logger.debug ( "\r\n \t\ update_jobs_in_iotlabdb jobs_psql %s \r\n \t \ - job_oar_list %s kept_jobs %s "%(set_jobs_psql, job_oar_list, kept_jobs)) - deleted_jobs = set_jobs_psql.difference(kept_jobs) - deleted_jobs = list(deleted_jobs) - if len(deleted_jobs) > 0: - iotlab_dbsession.query(IotlabXP).filter(IotlabXP.job_id.in_(deleted_jobs)).delete(synchronize_session='fetch') - iotlab_dbsession.commit() + def filter_lease_name(reservation_list, filter_value): + filtered_reservation_list = list(reservation_list) + logger.debug("IOTLAB_API \t filter_lease_name reservation_list %s" \ + % (reservation_list)) + for reservation in reservation_list: + if 'slice_hrn' in reservation and \ + reservation['slice_hrn'] != filter_value: + filtered_reservation_list.remove(reservation) + + logger.debug("IOTLAB_API \t filter_lease_name filtered_reservation_list %s" \ + % (filtered_reservation_list)) + return filtered_reservation_list - return + @staticmethod + def filter_lease_start_time(reservation_list, filter_value): + filtered_reservation_list = list(reservation_list) + for reservation in reservation_list: + if 't_from' in reservation and \ + reservation['t_from'] > filter_value: + filtered_reservation_list.remove(reservation) + + return filtered_reservation_list def GetLeases(self, lease_filter_dict=None, login=None): - """ Get the list of leases from OAR with complete information - about which slice owns which jobs and nodes. - Two purposes: - -Fetch all the jobs from OAR (running, waiting..) - complete the reservation information with slice hrn - found in iotlab_xp table. If not available in the table, - assume it is a iotlab slice. - -Updates the iotlab table, deleting jobs when necessary. - :return: reservation_list, list of dictionaries with 'lease_id', - 'reserved_nodes','slice_id', 'state', 'user', 'component_id_list', - 'slice_hrn', 'resource_ids', 't_from', 't_until' + """ + + Get the list of leases from OAR with complete information + about which slice owns which jobs and nodes. + Two purposes: + -Fetch all the jobs from OAR (running, waiting..) + complete the reservation information with slice hrn + found in testbed_xp table. If not available in the table, + assume it is a iotlab slice. + -Updates the iotlab table, deleting jobs when necessary. + + :returns: reservation_list, list of dictionaries with 'lease_id', + 'reserved_nodes','slice_id', 'state', 'user', 'component_id_list', + 'slice_hrn', 'resource_ids', 't_from', 't_until' :rtype: list + """ unfiltered_reservation_list = self.GetReservedNodes(login) reservation_list = [] #Find the slice associated with this user iotlab ldap uid - logger.debug(" IOTLABDRIVER.PY \tGetLeases login %s\ - unfiltered_reservation_list %s " %(login, unfiltered_reservation_list)) + logger.debug(" IOTLAB_API.PY \tGetLeases login %s\ + unfiltered_reservation_list %s " + % (login, unfiltered_reservation_list)) #Create user dict first to avoid looking several times for #the same user in LDAP SA 27/07/12 job_oar_list = [] - jobs_psql_query = iotlab_dbsession.query(IotlabXP).all() - jobs_psql_dict = dict([(row.job_id, row.__dict__ ) for row in jobs_psql_query ]) + jobs_psql_query = self.iotlab_db.testbed_session.query(LeaseTableXP).all() + jobs_psql_dict = dict([(row.experiment_id, row.__dict__) + for row in jobs_psql_query]) #jobs_psql_dict = jobs_psql_dict) - logger.debug("IOTLABDRIVER \tGetLeases jobs_psql_dict %s"\ - %(jobs_psql_dict)) - jobs_psql_id_list = [ row.job_id for row in jobs_psql_query ] - - + logger.debug("IOTLAB_API \tGetLeases jobs_psql_dict %s" + % (jobs_psql_dict)) + jobs_psql_id_list = [row.experiment_id for row in jobs_psql_query] for resa in unfiltered_reservation_list: - logger.debug("IOTLABDRIVER \tGetLeases USER %s"\ - %(resa['user'])) + logger.debug("IOTLAB_API \tGetLeases USER %s" + % (resa['user'])) #Construct list of jobs (runing, waiting..) in oar job_oar_list.append(resa['lease_id']) - #If there is information on the job in SLAB DB ] + #If there is information on the job in IOTLAB DB ] #(slice used and job id) if resa['lease_id'] in jobs_psql_dict: job_info = jobs_psql_dict[resa['lease_id']] - logger.debug("IOTLABDRIVER \tGetLeases job_info %s"\ - %(job_info)) + logger.debug("IOTLAB_API \tGetLeases job_info %s" + % (job_info)) resa['slice_hrn'] = job_info['slice_hrn'] resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice') #otherwise, assume it is a iotlab slice: else: - resa['slice_id'] = hrn_to_urn(self.root_auth+'.'+ \ - resa['user'] +"_slice" , 'slice') + resa['slice_id'] = hrn_to_urn(self.root_auth + '.' + + resa['user'] + "_slice", 'slice') resa['slice_hrn'] = Xrn(resa['slice_id']).get_hrn() resa['component_id_list'] = [] @@ -925,21 +1013,41 @@ class IotlabTestbedAPI(): iotlab_xrn = iotlab_xrn_object(self.root_auth, node) resa['component_id_list'].append(iotlab_xrn.urn) - if lease_filter_dict: - logger.debug("IOTLABDRIVER \tGetLeases resa_ %s \ - \r\n leasefilter %s" %(resa, lease_filter_dict)) + if lease_filter_dict: + logger.debug("IOTLAB_API \tGetLeases \ + \r\n leasefilter %s" % ( lease_filter_dict)) + + filter_dict_functions = { + 'slice_hrn' : IotlabTestbedAPI.filter_lease_name, + 't_from' : IotlabTestbedAPI.filter_lease_start_time + } + reservation_list = list(unfiltered_reservation_list) + for filter_type in lease_filter_dict: + logger.debug("IOTLAB_API \tGetLeases reservation_list %s" \ + % (reservation_list)) + reservation_list = filter_dict_functions[filter_type](\ + reservation_list,lease_filter_dict[filter_type] ) + + # Filter the reservation list with a maximum timespan so that the + # leases and jobs running after this timestamp do not appear + # in the result leases. + # if 'start_time' in : + # if resa['start_time'] < lease_filter_dict['start_time']: + # reservation_list.append(resa) + + + # if 'name' in lease_filter_dict and \ + # lease_filter_dict['name'] == resa['slice_hrn']: + # reservation_list.append(resa) - if lease_filter_dict['name'] == resa['slice_hrn']: - reservation_list.append(resa) if lease_filter_dict is None: reservation_list = unfiltered_reservation_list + self.iotlab_db.update_experiments_in_additional_sfa_db(job_oar_list, jobs_psql_id_list) - self.update_jobs_in_iotlabdb(job_oar_list, jobs_psql_id_list) - - logger.debug(" IOTLABDRIVER.PY \tGetLeases reservation_list %s"\ - %(reservation_list)) + logger.debug(" IOTLAB_API.PY \tGetLeases reservation_list %s" + % (reservation_list)) return reservation_list @@ -966,7 +1074,7 @@ class IotlabTestbedAPI(): #FROM PLC DOC #""" - #logger.warning("IOTLABDRIVER \tUnBindObjectFromPeer EMPTY-\ + #logger.warning("IOTLAB_API \tUnBindObjectFromPeer EMPTY-\ #DO NOTHING \r\n ") #return @@ -985,7 +1093,7 @@ class IotlabTestbedAPI(): #FROM PLC API DOC #""" - #logger.warning("IOTLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ") + #logger.warning("IOTLAB_API \tBindObjectToPeer EMPTY - DO NOTHING \r\n ") #return ##TODO UpdateSlice 04/07/2012 SA || Commented out 28/05/13 SA @@ -1002,7 +1110,7 @@ class IotlabTestbedAPI(): #FROM PLC API DOC #""" - #logger.warning("IOTLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ") + #logger.warning("IOTLAB_API UpdateSlice EMPTY - DO NOTHING \r\n ") #return #Unused SA 30/05/13, we only update the user's key or we delete it. @@ -1017,10 +1125,10 @@ class IotlabTestbedAPI(): #""" ##new_row = FederatedToIotlab(iotlab_hrn, federated_hrn) - ##iotlab_dbsession.add(new_row) - ##iotlab_dbsession.commit() + ##self.iotlab_db.testbed_session.add(new_row) + ##self.iotlab_db.testbed_session.commit() - #logger.debug("IOTLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ") + #logger.debug("IOTLAB_API UpdatePerson EMPTY - DO NOTHING \r\n ") #return @staticmethod @@ -1034,109 +1142,119 @@ class IotlabTestbedAPI(): Admin may query all keys. Non-admins may only query their own keys. FROM PLC API DOC - :return: dict with ssh key as key and dicts as value. + :returns: dict with ssh key as key and dicts as value. :rtype: dict """ if key_filter is None: keys = dbsession.query(RegKey).options(joinedload('reg_user')).all() - else : + else: keys = dbsession.query(RegKey).options(joinedload('reg_user')).filter(RegKey.key.in_(key_filter)).all() key_dict = {} for key in keys: - key_dict[key.key] = {'key_id': key.key_id, 'key': key.key, \ - 'email': key.reg_user.email, 'hrn':key.reg_user.hrn} + key_dict[key.key] = {'key_id': key.key_id, 'key': key.key, + 'email': key.reg_user.email, + 'hrn': key.reg_user.hrn} #ldap_rslt = self.ldap.LdapSearch({'enabled']=True}) #user_by_email = dict((user[1]['mail'][0], user[1]['sshPublicKey']) \ #for user in ldap_rslt) - logger.debug("IOTLABDRIVER GetKeys -key_dict %s \r\n " %(key_dict)) + logger.debug("IOTLAB_API GetKeys -key_dict %s \r\n " % (key_dict)) return key_dict #TODO : test def DeleteKey(self, user_record, key_string): - """ Deletes a key in the LDAP entry of the specified user. + """Deletes a key in the LDAP entry of the specified user. + Removes the key_string from the user's key list and updates the LDAP - user's entry with the new key attributes. + user's entry with the new key attributes. + :param key_string: The ssh key to remove :param user_record: User's record :type key_string: string :type user_record: dict - :return: True if sucessful, False if not. + :returns: True if sucessful, False if not. :rtype: Boolean """ all_user_keys = user_record['keys'] all_user_keys.remove(key_string) - new_attributes = {'sshPublicKey':all_user_keys} + new_attributes = {'sshPublicKey':all_user_keys} ret = self.ldap.LdapModifyUser(user_record, new_attributes) - logger.debug("IOTLABDRIVER DeleteKey %s- "%(ret)) + logger.debug("IOTLAB_API DeleteKey %s- " % (ret)) return ret['bool'] @staticmethod - def _sql_get_slice_info( slice_filter ): + def _sql_get_slice_info(slice_filter): """ Get the slice record based on the slice hrn. Fetch the record of the - user associated with the slice by usingjoinedload based on t - he reg_researcher relationship. + user associated with the slice by using joinedload based on the + reg_researcher relationship. + :param slice_filter: the slice hrn we are looking for :type slice_filter: string - :return: the slice record enhanced with the user's information if the - slice was found, None it wasn't. + :returns: the slice record enhanced with the user's information if the + slice was found, None it wasn't. + :rtype: dict or None. """ #DO NOT USE RegSlice - reg_researchers to get the hrn #of the user otherwise will mess up the RegRecord in #Resolve, don't know why - SA 08/08/2012 - #Only one entry for one user = one slice in iotlab_xp table + #Only one entry for one user = one slice in testbed_xp table #slicerec = dbsession.query(RegRecord).filter_by(hrn = slice_filter).first() - raw_slicerec = dbsession.query(RegSlice).options(joinedload('reg_researchers')).filter_by(hrn = slice_filter).first() + raw_slicerec = dbsession.query(RegSlice).options(joinedload('reg_researchers')).filter_by(hrn=slice_filter).first() #raw_slicerec = dbsession.query(RegRecord).filter_by(hrn = slice_filter).first() if raw_slicerec: #load_reg_researcher #raw_slicerec.reg_researchers raw_slicerec = raw_slicerec.__dict__ - logger.debug(" IOTLABDRIVER \t get_slice_info slice_filter %s \ - raw_slicerec %s"%(slice_filter, raw_slicerec)) + logger.debug(" IOTLAB_API \t _sql_get_slice_info slice_filter %s \ + raw_slicerec %s" % (slice_filter, raw_slicerec)) slicerec = raw_slicerec #only one researcher per slice so take the first one #slicerec['reg_researchers'] = raw_slicerec['reg_researchers'] #del slicerec['reg_researchers']['_sa_instance_state'] return slicerec - else : + else: return None @staticmethod - def _sql_get_slice_info_from_user(slice_filter ): + def _sql_get_slice_info_from_user(slice_filter): """ Get the slice record based on the user recordid by using a joinedload on the relationship reg_slices_as_researcher. Format the sql record into a dict with the mandatory fields for user and slice. - :return: dict with slice record and user record if the record was found + :returns: dict with slice record and user record if the record was found based on the user's id, None if not.. :rtype:dict or None.. """ #slicerec = dbsession.query(RegRecord).filter_by(record_id = slice_filter).first() - raw_slicerec = dbsession.query(RegUser).options(joinedload('reg_slices_as_researcher')).filter_by(record_id = slice_filter).first() + raw_slicerec = dbsession.query(RegUser).options(joinedload('reg_slices_as_researcher')).filter_by(record_id=slice_filter).first() #raw_slicerec = dbsession.query(RegRecord).filter_by(record_id = slice_filter).first() #Put it in correct order - user_needed_fields = ['peer_authority', 'hrn', 'last_updated', 'classtype', 'authority', 'gid', 'record_id', 'date_created', 'type', 'email', 'pointer'] - slice_needed_fields = ['peer_authority', 'hrn', 'last_updated', 'classtype', 'authority', 'gid', 'record_id', 'date_created', 'type', 'pointer'] + user_needed_fields = ['peer_authority', 'hrn', 'last_updated', + 'classtype', 'authority', 'gid', 'record_id', + 'date_created', 'type', 'email', 'pointer'] + slice_needed_fields = ['peer_authority', 'hrn', 'last_updated', + 'classtype', 'authority', 'gid', 'record_id', + 'date_created', 'type', 'pointer'] if raw_slicerec: #raw_slicerec.reg_slices_as_researcher raw_slicerec = raw_slicerec.__dict__ slicerec = {} slicerec = \ - dict([(k, raw_slicerec['reg_slices_as_researcher'][0].__dict__[k]) \ - for k in slice_needed_fields]) - slicerec['reg_researchers'] = dict([(k, raw_slicerec[k]) \ - for k in user_needed_fields]) + dict([(k, raw_slicerec[ + 'reg_slices_as_researcher'][0].__dict__[k]) + for k in slice_needed_fields]) + slicerec['reg_researchers'] = dict([(k, raw_slicerec[k]) + for k in user_needed_fields]) #TODO Handle multiple slices for one user SA 10/12/12 #for now only take the first slice record associated to the rec user ##slicerec = raw_slicerec['reg_slices_as_researcher'][0].__dict__ @@ -1149,8 +1267,8 @@ class IotlabTestbedAPI(): else: return None - def _get_slice_records(self, slice_filter = None, \ - slice_filter_type = None): + def _get_slice_records(self, slice_filter=None, + slice_filter_type=None): """ Get the slice record depending on the slice filter and its type. :param slice_filter: Can be either the slice hrn or the user's record @@ -1159,10 +1277,10 @@ class IotlabTestbedAPI(): :param slice_filter_type: describes the slice filter type used, can be slice_hrn or record_id_user :type: string - :return: the slice record + :returns: the slice record :rtype:dict - ..seealso:_sql_get_slice_info_from_user - ..seealso: _sql_get_slice_info + .. seealso::_sql_get_slice_info_from_user + .. seealso:: _sql_get_slice_info """ #Get list of slices based on the slice hrn @@ -1174,7 +1292,7 @@ class IotlabTestbedAPI(): slicerec = self._sql_get_slice_info(slice_filter) if slicerec is None: - return None + return None #return login, None #Get slice based on user id @@ -1192,26 +1310,28 @@ class IotlabTestbedAPI(): #login = fixed_slicerec_dict['hrn'].split(".")[1].split("_")[0] #return login, fixed_slicerec_dict return fixed_slicerec_dict + else: + return None - - def GetSlices(self, slice_filter = None, slice_filter_type = None, \ - login=None): - """ Get the slice records from the iotlab db and add lease information - if any. + def GetSlices(self, slice_filter=None, slice_filter_type=None, + login=None): + """Get the slice records from the iotlab db and add lease information + if any. :param slice_filter: can be the slice hrn or slice record id in the db - depending on the slice_filter_type. + depending on the slice_filter_type. :param slice_filter_type: defines the type of the filtering used, Can be - either 'slice_hrn' or "record_id'. + either 'slice_hrn' or "record_id'. :type slice_filter: string :type slice_filter_type: string - :return: a slice dict if slice_filter and slice_filter_type - are specified and a matching entry is found in the db. The result - is put into a list.Or a list of slice dictionnaries if no filters are - specified. + :returns: a slice dict if slice_filter and slice_filter_type + are specified and a matching entry is found in the db. The result + is put into a list.Or a list of slice dictionnaries if no filters + arespecified. :rtype: list + """ #login = None authorized_filter_types_list = ['slice_hrn', 'record_id_user'] @@ -1219,14 +1339,18 @@ class IotlabTestbedAPI(): #First try to get information on the slice based on the filter provided if slice_filter_type in authorized_filter_types_list: - fixed_slicerec_dict = \ - self._get_slice_records(slice_filter, slice_filter_type) + fixed_slicerec_dict = self._get_slice_records(slice_filter, + slice_filter_type) + # if the slice was not found in the sfa db + if fixed_slicerec_dict is None: + return return_slicerec_dictlist + slice_hrn = fixed_slicerec_dict['hrn'] - logger.debug(" IOTLABDRIVER \tGetSlices login %s \ + logger.debug(" IOTLAB_API \tGetSlices login %s \ slice record %s slice_filter %s \ - slice_filter_type %s " %(login, \ - fixed_slicerec_dict, slice_filter, \ + slice_filter_type %s " % (login, + fixed_slicerec_dict, slice_filter, slice_filter_type)) @@ -1234,50 +1358,57 @@ class IotlabTestbedAPI(): #jobs associated to this slice leases_list = [] - leases_list = self.GetLeases(login = login) + leases_list = self.GetLeases(login=login) #If no job is running or no job scheduled #return only the slice record if leases_list == [] and fixed_slicerec_dict: return_slicerec_dictlist.append(fixed_slicerec_dict) + # if the jobs running don't belong to the user/slice we are looking + # for + leases_hrn = [lease['slice_hrn'] for lease in leases_list] + if slice_hrn not in leases_hrn: + return_slicerec_dictlist.append(fixed_slicerec_dict) #If several jobs for one slice , put the slice record into # each lease information dict - - - for lease in leases_list : + for lease in leases_list: slicerec_dict = {} - logger.debug("IOTLABDRIVER.PY \tGetSlices slice_filter %s \ - \ lease['slice_hrn'] %s" \ - %(slice_filter, lease['slice_hrn'])) - if lease['slice_hrn'] == slice_hrn: - slicerec_dict['slice_hrn'] = lease['slice_hrn'] - slicerec_dict['hrn'] = lease['slice_hrn'] - slicerec_dict['user'] = lease['user'] + logger.debug("IOTLAB_API.PY \tGetSlices slice_filter %s \ + \t lease['slice_hrn'] %s" + % (slice_filter, lease['slice_hrn'])) + if lease['slice_hrn'] == slice_hrn: slicerec_dict['oar_job_id'] = lease['lease_id'] - slicerec_dict.update({'list_node_ids':{'hostname':lease['reserved_nodes']}}) - slicerec_dict.update({'node_ids':lease['reserved_nodes']}) - #Update lease dict with the slice record if fixed_slicerec_dict: fixed_slicerec_dict['oar_job_id'] = [] - fixed_slicerec_dict['oar_job_id'].append(slicerec_dict['oar_job_id']) + fixed_slicerec_dict['oar_job_id'].append( + slicerec_dict['oar_job_id']) slicerec_dict.update(fixed_slicerec_dict) #slicerec_dict.update({'hrn':\ #str(fixed_slicerec_dict['slice_hrn'])}) + slicerec_dict['slice_hrn'] = lease['slice_hrn'] + slicerec_dict['hrn'] = lease['slice_hrn'] + slicerec_dict['user'] = lease['user'] + slicerec_dict.update( + {'list_node_ids': + {'hostname': lease['reserved_nodes']}}) + slicerec_dict.update({'node_ids': lease['reserved_nodes']}) + + return_slicerec_dictlist.append(slicerec_dict) - logger.debug("IOTLABDRIVER.PY \tGetSlices \ - OHOHOHOH %s" %(return_slicerec_dictlist )) + logger.debug("IOTLAB_API.PY \tGetSlices \ + OHOHOHOH %s" %(return_slicerec_dictlist)) - logger.debug("IOTLABDRIVER.PY \tGetSlices \ + logger.debug("IOTLAB_API.PY \tGetSlices \ slicerec_dict %s return_slicerec_dictlist %s \ lease['reserved_nodes'] \ - %s" %(slicerec_dict, return_slicerec_dictlist, \ - lease['reserved_nodes'] )) + %s" % (slicerec_dict, return_slicerec_dictlist, + lease['reserved_nodes'])) - logger.debug("IOTLABDRIVER.PY \tGetSlices RETURN \ - return_slicerec_dictlist %s" \ - %(return_slicerec_dictlist)) + logger.debug("IOTLAB_API.PY \tGetSlices RETURN \ + return_slicerec_dictlist %s" + % (return_slicerec_dictlist)) return return_slicerec_dictlist @@ -1286,7 +1417,8 @@ class IotlabTestbedAPI(): #Get all slices from the iotlab sfa database , #put them in dict format #query_slice_list = dbsession.query(RegRecord).all() - query_slice_list = dbsession.query(RegSlice).options(joinedload('reg_researchers')).all() + query_slice_list = \ + dbsession.query(RegSlice).options(joinedload('reg_researchers')).all() for record in query_slice_list: tmp = record.__dict__ @@ -1298,12 +1430,12 @@ class IotlabTestbedAPI(): #Get all the jobs reserved nodes leases_list = self.GetReservedNodes() - for fixed_slicerec_dict in return_slicerec_dictlist: slicerec_dict = {} #Check if the slice belongs to a iotlab user if fixed_slicerec_dict['peer_authority'] is None: - owner = fixed_slicerec_dict['hrn'].split(".")[1].split("_")[0] + owner = fixed_slicerec_dict['hrn'].split( + ".")[1].split("_")[0] else: owner = None for lease in leases_list: @@ -1311,18 +1443,21 @@ class IotlabTestbedAPI(): slicerec_dict['oar_job_id'] = lease['lease_id'] #for reserved_node in lease['reserved_nodes']: - logger.debug("IOTLABDRIVER.PY \tGetSlices lease %s "\ - %(lease )) - - slicerec_dict.update({'node_ids':lease['reserved_nodes']}) - slicerec_dict.update({'list_node_ids':{'hostname':lease['reserved_nodes']}}) + logger.debug("IOTLAB_API.PY \tGetSlices lease %s " + % (lease)) slicerec_dict.update(fixed_slicerec_dict) + slicerec_dict.update({'node_ids': + lease['reserved_nodes']}) + slicerec_dict.update({'list_node_ids': + {'hostname': + lease['reserved_nodes']}}) + #slicerec_dict.update({'hrn':\ #str(fixed_slicerec_dict['slice_hrn'])}) #return_slicerec_dictlist.append(slicerec_dict) fixed_slicerec_dict.update(slicerec_dict) - logger.debug("IOTLABDRIVER.PY \tGetSlices RETURN \ + logger.debug("IOTLAB_API.PY \tGetSlices RETURN \ return_slicerec_dictlist %s \slice_filter %s " \ %(return_slicerec_dictlist, slice_filter)) @@ -1346,10 +1481,10 @@ class IotlabTestbedAPI(): #if not "instantiation" in iotlab_record: #iotlab_record["instantiation"] = "iotlab-instantiated" ##iotlab_record["hrn"] = hrn_to_pl_slicename(hrn) - ##Unused hrn_to_pl_slicename because Slab's hrn already + ##Unused hrn_to_pl_slicename because Iotlab's hrn already ##in the appropriate form SA 23/07/12 #iotlab_record["hrn"] = hrn - #logger.debug("IOTLABDRIVER.PY sfa_fields_to_iotlab_fields \ + #logger.debug("IOTLAB_API.PY sfa_fields_to_iotlab_fields \ #iotlab_record %s " %(iotlab_record['hrn'])) #if "url" in record: #iotlab_record["url"] = record["url"]