def list_resources(self, version=None, options=None): logger.warning("iotlabdriver list_resources") if not options: options = {} aggregate = IotLABAggregate(self) rspec = aggregate.list_resources(version=version, options=options) return rspec
def get_users(self): """ Get all LDAP users :returns: users with LDAP attributes :rtype: dict :Example: [{"firstName":"Frederic", "lastName":"Saint-marcel", "email":"*****@*****.**", "structure":"INRIA", "city":"Grenoble", "country":"France", "login":"******", sshPublicKeys":["ssh-rsa AAAAB3..."], "motivations":"test SFA", "validate":true, "admin":true, "createTimeStamp":"20120911115247Z"}, {"firstName":"Julien", ... } ] """ logger.warning("iotlashell get_users") users_dict = {} try: users = self.api.method('admin/users') except HTTPError as err: logger.warning("iotlashell get_users error %s" % err.reason) return {'error' : err.reason} for user in users: users_dict[user['email']] = user return users_dict
def __init__ (self,url,mentioned_in=None,verbose=False): self._url=url self.verbose=verbose cache=VersionCache() key="interface:%s"%url try: (self._url,self.hostname,self.port)=url_hostname_port(url) # look for ip in the cache tuple=cache.get(key) if tuple: (self.hostname, self.ip, self.port) = tuple else: self.ip=socket.gethostbyname(self.hostname) except: msg="can't resolve hostname %s\n\tfound in url %s"%(self.hostname,self._url) if mentioned_in: msg += "\n\t(mentioned at %s)"%mentioned_in logger.warning (msg) self.hostname="unknown" self.ip='0.0.0.0' self.port="???" cache.set(key, (self.hostname, self.ip, self.port,) ) cache.save() self.probed=False # mark unknown interfaces as probed to avoid unnecessary attempts if self.hostname=='unknown': # don't really try it self.probed=True self._version={}
def status(self, urns, options=None): logger.warning("iotlabdriver status") aggregate = IotLABAggregate(self) desc = aggregate.describe(urns, version='GENI 3') status = {'geni_urn': desc['geni_urn'], 'geni_slivers': desc['geni_slivers']} return status
def already_handled(self, call_id): # if not provided in the call... if not call_id: return False has_lock = False for attempt in range(_call_ids_impl.retries): if debug: logger.debug("Waiting for lock (%d)" % attempt) if self._lock.acquire(False): has_lock = True if debug: logger.debug("got lock (%d)" % attempt) break time.sleep(float(_call_ids_impl.wait_ms) / 1000) # in the unlikely event where we can't get the lock if not has_lock: logger.warning( "_call_ids_impl.should_handle_call_id: could not acquire lock") return False # we're good to go if self.has_key(call_id): self._purge() self._lock.release() return True self[call_id] = time.time() self._purge() self._lock.release() if debug: logger.debug("released lock") return False
def call(self): if hasattr(self.api.manager, 'get_key_from_incoming_ip'): return self.api.manager.get_key_from_incoming_ip(api) else: logger.warning( "get_key_from_incoming_ip not supported by registry manager") return 0
def get_nodes(self): """ Get all OAR nodes :returns: nodes with OAR properties :rtype: dict :Example: {"items": [ {"archi": "a8:at86rf231", "mobile": 0, "mobility_type": " ", "network_address": "a8-53.grenoble.iot-lab.info", "site": "paris", "state": "Alive", "uid": "9856", "x": "0.37", "y": "5.44", "z": "2.33" }, {"archi= ...} ] { """ logger.warning("iotlashell get_nodes") nodes_dict = {} try: nodes = experiment.info_experiment(self.api) except HTTPError as err: logger.warning("iotlashell get_nodes error %s" % err.reason) return {'error' : err.reason} for node in nodes['items']: nodes_dict[node['network_address']] = node return nodes_dict
def add_user(self, slice_user): """ Add LDAP user """ # pylint:disable=E1123 logger.warning("iotlashell add_user") user = {"type" : "SA", # single account creation "city" : "To be defined", "country" : "To be defined", "motivations" : "SFA federation"} email = slice_user['email'] user['email'] = email user['sshPublicKey'] = slice_user['keys'][0] # ex : onelab.inria user['structure'] = slice_user['slice_record']['authority'] email = (email.split('@'))[0] user['firstName'] = email.split('.')[0] try: user['lastName'] = email.split('.')[1] except IndexError: user['lastName'] = email.split('.')[0] try: self.api.method('admin/users', 'post', json=user) except HTTPError as err: logger.warning("iotlashell add_user error %s" % err.reason)
def already_handled (self,call_id): # if not provided in the call... if not call_id: return False has_lock=False for attempt in range(_call_ids_impl.retries): if debug: logger.debug("Waiting for lock (%d)"%attempt) if self._lock.acquire(False): has_lock=True if debug: logger.debug("got lock (%d)"%attempt) break time.sleep(float(_call_ids_impl.wait_ms)/1000) # in the unlikely event where we can't get the lock if not has_lock: logger.warning("_call_ids_impl.should_handle_call_id: could not acquire lock") return False # we're good to go if self.has_key(call_id): self._purge() self._lock.release() return True self[call_id]=time.time() self._purge() self._lock.release() if debug: logger.debug("released lock") return False
def _save_db_lease(self, job_id, slice_hrn): """ Save lease table row in SFA database """ lease_row = LeaseTable(job_id, slice_hrn) logger.warning("iotlabdriver _save_db_lease lease row : %s" % lease_row) self.api.dbsession().add(lease_row) self.api.dbsession().commit()
def response(self, from_xmlrpc): if isinstance(from_xmlrpc, dict) and 'code' in from_xmlrpc: if from_xmlrpc['code'] == 0: return from_xmlrpc['value'] else: raise SfaFault(from_xmlrpc['code'], from_xmlrpc['output']) else: logger.warning("unexpected result from federica xmlrpc api") return from_xmlrpc
def response (self, from_xmlrpc): if isinstance (from_xmlrpc, dict) and 'code' in from_xmlrpc: if from_xmlrpc['code']==0: return from_xmlrpc['value'] else: raise SfaFault(from_xmlrpc['code'],from_xmlrpc['output']) else: logger.warning("unexpected result from federica xmlrpc api") return from_xmlrpc
def get_file_list(self): file_list = [] pattern=os.path.join(self.basedir,"*") for cert_file in glob.glob(pattern): if os.path.isfile(cert_file): if self.has_supported_extension(cert_file): file_list.append(cert_file) else: logger.warning("File %s ignored - supported extensions are %r"%\ (cert_file,TrustedRoots.supported_extensions)) return file_list
def _normalize_input (record, reg_key, driver_key): # this looks right, use this for both keys if reg_key in record: # and issue a warning if they were both set and different # as we're overwriting some user data here if driver_key in record: logger.warning ("normalize_input: incoming record has both values, using %s"%reg_key) record[driver_key]=record[reg_key] # we only have one key set, duplicate for the other one elif driver_key in record: logger.warning ("normalize_input: you should use '%s' instead of '%s'"%(reg_key,driver_key)) record[reg_key]=record[driver_key]
def LdapAddUser(self, record) : """Add SFA user to LDAP if it is not in LDAP yet. :param record: dictionnary with the user's data. :returns: a dictionary with the status (Fail= False, Success= True) and the uid of the newly added user if successful, or the error message it is not. Dict has keys bool and message in case of failure, and bool uid in case of success. :rtype: dict .. seealso:: make_ldap_filters_from_record """ logger.debug(" \r\n \t LDAP LdapAddUser \r\n\r\n ================\r\n ") user_ldap_attrs = self.make_ldap_attributes_from_record(record) #Check if user already in LDAP wih email, first name and last name filter_by = self.make_ldap_filters_from_record(user_ldap_attrs) user_exist = self.LdapSearch(filter_by) if user_exist: logger.warning(" \r\n \t LDAP LdapAddUser user %s %s \ already exists" % (user_ldap_attrs['sn'], user_ldap_attrs['mail'])) return {'bool': False} #Bind to the server result = self.conn.connect() if(result['bool']): # A dict to help build the "body" of the object logger.debug(" \r\n \t LDAP LdapAddUser attrs %s " % user_ldap_attrs) # The dn of our new entry/object dn = 'uid=' + user_ldap_attrs['uid'] + "," + self.baseDN try: ldif = modlist.addModlist(user_ldap_attrs) logger.debug("LDAPapi.py add attrs %s \r\n ldif %s" % (user_ldap_attrs, ldif)) self.conn.ldapserv.add_s(dn, ldif) logger.info("Adding user %s login %s in LDAP" % (user_ldap_attrs['cn'], user_ldap_attrs['uid'])) except ldap.LDAPError, error: logger.log_exc("LDAP Add Error %s" % error) return {'bool': False, 'message': error} self.conn.close() return {'bool': True, 'uid': user_ldap_attrs['uid']}
def aggregate_version(self): logger.warning("iotlabdriver aggregate_version") version_manager = VersionManager() ad_rspec_versions = [] request_rspec_versions = [] for rspec_version in version_manager.versions: if rspec_version.content_type in ['*', 'ad']: ad_rspec_versions.append(rspec_version.to_dict()) if rspec_version.content_type in ['*', 'request']: request_rspec_versions.append(rspec_version.to_dict()) return { 'testbed': self.hrn, 'geni_request_rspec_versions': request_rspec_versions, 'geni_ad_rspec_versions': ad_rspec_versions}
def get_slivers(self, urns, leases, nodes): """ Get slivers attributes list """ logger.warning("iotlabaggregate get_slivers") logger.warning("iotlabaggregate get_slivers urns %s" % urns) slivers = [] for lease in leases: for node in lease["resources"]: sliver_node = nodes[node] sliver_hrn = "%s.%s-%s" % (self.driver.hrn, lease["id"], node.split(".")[0]) start_time = datetime.datetime.fromtimestamp(lease["date"]) duration = datetime.timedelta(seconds=int(lease["duration"])) sliver_node["expires"] = start_time + duration sliver_node["sliver_id"] = Xrn(sliver_hrn, type="sliver").urn slivers.append(sliver_node) return slivers
def create_user(self, user_name, password, tenant_id, email=None, enabled=True): if password is None: logger.warning("If you want to make a user, you should include your password!!") raise ValueError('You should include your password!!') users = self.driver.shell.auth_manager.users.findall() for user in users: if user_name == user.name: user_info = user logger.info("The user name[%s] already exists." % user_name) break else: user_info = self.driver.shell.auth_manager.users.create(user_name, password, \ email, tenant_id, enabled) return user_info
def DeletePerson(self, person_record): """Disable an existing account in cortexlab LDAP. Users and techs can only delete themselves. PIs can only delete themselves and other non-PIs at their sites. ins can delete anyone. :param person_record: user's record :type person_record: dict :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("CORTEXLAB_API DeletePerson %s " % (person_record)) return ret['bool']
def DeletePerson(self, person_record): """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. :param person_record: user's record :type person_record: dict :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("IOTLAB_API DeletePerson %s " % (person_record)) return ret['bool']
def get_auth_info(self, xrn): hrn, type = urn_to_hrn(xrn) if not self.auth_exists(hrn): logger.warning("Hierarchy: mising authority - xrn=%s, hrn=%s"%(xrn,hrn)) raise MissingAuthority(hrn) (directory, gid_filename, privkey_filename, dbinfo_filename) = \ self.get_auth_filenames(hrn) auth_info = AuthInfo(hrn, gid_filename, privkey_filename, dbinfo_filename) # check the GID and see if it needs to be refreshed gid = auth_info.get_gid_object() gid_refreshed = self.refresh_gid(gid) if gid != gid_refreshed: auth_info.update_gid_object(gid_refreshed) return auth_info
def get_auth_info(self, xrn): hrn, type = urn_to_hrn(xrn) if not self.auth_exists(hrn): logger.warning("Hierarchy: missing authority - xrn=%s, hrn=%s"%(xrn,hrn)) raise MissingAuthority(hrn) (directory, gid_filename, privkey_filename, ) = \ self.get_auth_filenames(hrn) auth_info = AuthInfo(hrn, gid_filename, privkey_filename) # check the GID and see if it needs to be refreshed gid = auth_info.get_gid_object() gid_refreshed = self.refresh_gid(gid) if gid != gid_refreshed: auth_info.update_gid_object(gid_refreshed) return auth_info
def LdapAddUser(self, record) : """Add SFA user to LDAP if it is not in LDAP yet. """ logger.debug(" \r\n \t LDAP LdapAddUser \r\n\r\n =====================================================\r\n ") user_ldap_attrs = self.make_ldap_attributes_from_record(record) #Check if user already in LDAP wih email, first name and last name filter_by = self.make_ldap_filters_from_record(user_ldap_attrs) user_exist = self.LdapSearch(filter_by) if user_exist: logger.warning(" \r\n \t LDAP LdapAddUser user %s %s \ already exists" %(user_ldap_attrs['sn'], \ user_ldap_attrs['mail'])) return {'bool': False} #Bind to the server result = self.conn.connect() if(result['bool']): # A dict to help build the "body" of the object logger.debug(" \r\n \t LDAP LdapAddUser attrs %s " %user_ldap_attrs) # The dn of our new entry/object dn = 'uid=' + user_ldap_attrs['uid'] + "," + self.baseDN try: ldif = modlist.addModlist(user_ldap_attrs) logger.debug("LDAPapi.py add attrs %s \r\n ldif %s"\ %(user_ldap_attrs,ldif) ) self.conn.ldapserv.add_s(dn,ldif) logger.info("Adding user %s login %s in LDAP" \ %(user_ldap_attrs['cn'] ,user_ldap_attrs['uid'])) except ldap.LDAPError, error: logger.log_exc("LDAP Add Error %s" %error) return {'bool' : False, 'message' : error } self.conn.close() return {'bool': True, 'uid':user_ldap_attrs['uid']}
def reserve_nodes(self, login, exp_name, nodes_list, start_time, duration): """ Submit a physical experiment (nodes list) and reservation date. """ # pylint:disable=W0212,R0913,E1123 logger.warning("iotlashell reserve_nodes") exp_file = helpers.FilesDict() _experiment = experiment._Experiment(exp_name, duration, start_time) _experiment.type = 'physical' _experiment.nodes = nodes_list exp_file['new_exp.json'] = helpers.json_dumps(_experiment) try: return self.api.method('admin/experiments?user=%s' % login, 'post', files=exp_file) except HTTPError as err: logger.warning("iotlashell reserve_nodes error %s" % err.reason) return {'error' : err.reason}
def Remove(self, api, xrn, origin_hrn=None): dbsession = api.dbsession() hrn = xrn.get_hrn() type = xrn.get_type() request = dbsession.query(RegRecord).filter_by(hrn=hrn) if type and type not in ['all', '*']: request = request.filter_by(type=type) record = request.first() if not record: msg = "Could not find hrn %s" % hrn if type: msg += " type=%s" % type raise RecordNotFound(msg) type = record.type if type not in ['slice', 'user', 'node', 'authority']: raise UnknownSfaType(type) credential = api.getCredential() registries = api.registries # Try to remove the object from the PLCDB of federated agg. # This is attempted before removing the object from the local agg's PLCDB and sfa table if hrn.startswith(api.hrn) and type in ['user', 'slice', 'authority']: for registry in registries: if registry not in [api.hrn]: try: result = registries[registry].remove_peer_object( credential, record, origin_hrn) except: pass # call testbed callback first # IIUC this is done on the local testbed TOO because of the refreshpeer link if not api.driver.remove(record.__dict__): logger.warning("driver.remove failed") # delete from sfa db dbsession.delete(record) dbsession.commit() return 1
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. 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 :type person_uid: string :rtype: Boolean :returns: True if the key has been modified, False otherwise. """ ret = self.ldap.LdapModify(person_uid, old_attributes_dict, \ new_key_dict) logger.warning("IOTLAB_API AddPersonKey EMPTY - DO NOTHING \r\n ") return ret['bool']
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. 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 :type person_uid: string :rtype: Boolean :returns: True if the key has been modified, False otherwise. """ ret = self.ldap.LdapModify(person_uid, old_attributes_dict, \ new_key_dict) logger.warning("CORTEXLAB_API AddPersonKey EMPTY - DO NOTHING \r\n ") return ret['bool']
def Remove(self, api, xrn, origin_hrn=None): dbsession=api.dbsession() hrn=xrn.get_hrn() type=xrn.get_type() request=dbsession.query(RegRecord).filter_by(hrn=hrn) if type and type not in ['all', '*']: request=request.filter_by(type=type) record = request.first() if not record: msg="Could not find hrn %s"%hrn if type: msg += " type=%s"%type raise RecordNotFound(msg) type = record.type if type not in ['slice', 'user', 'node', 'authority'] : raise UnknownSfaType(type) credential = api.getCredential() registries = api.registries # Try to remove the object from the PLCDB of federated agg. # This is attempted before removing the object from the local agg's PLCDB and sfa table if hrn.startswith(api.hrn) and type in ['user', 'slice', 'authority']: for registry in registries: if registry not in [api.hrn]: try: result=registries[registry].remove_peer_object(credential, record, origin_hrn) except: pass # call testbed callback first # IIUC this is done on the local testbed TOO because of the refreshpeer link if not api.driver.remove(record.__dict__): logger.warning("driver.remove failed") # delete from sfa db dbsession.delete(record) dbsession.commit() return 1
def __init__(self, url, mentioned_in=None, verbose=False): self._url = url self.verbose = verbose cache = VersionCache() key = "interface:%s" % url try: (self._url, self.hostname, self.port) = url_hostname_port(url) # look for ip in the cache tuple = cache.get(key) if tuple: (self.hostname, self.ip, self.port) = tuple else: self.ip = socket.gethostbyname(self.hostname) except: msg = "can't resolve hostname %s\n\tfound in url %s" % ( self.hostname, self._url) if mentioned_in: msg += "\n\t(mentioned at %s)" % mentioned_in logger.warning(msg) self.hostname = "unknown" self.ip = '0.0.0.0' self.port = "???" cache.set(key, ( self.hostname, self.ip, self.port, )) cache.save() self.probed = False # mark unknown interfaces as probed to avoid unnecessary attempts if self.hostname == 'unknown': # don't really try it self.probed = True self._version = {}
def create_floatingip(self, tenant_name, instances): config = OSConfig() # Information of public network(external network) from configuration file extnet_name = config.get('network', 'external_network_name') tenant = self.driver.shell.auth_manager.tenants.find(name=tenant_name) networks = self.driver.shell.network_manager.list_networks().get('networks') for network in networks: if (network.get('name') == extnet_name) or \ (network.get('name') == 'public') or (network.get('name') == 'ext-net'): pub_net_id = network.get('id') break else: logger.warning("We shoud need the public network ID for floating IPs!") raise ValueError("The public network ID was not found!") ports = self.driver.shell.network_manager.list_ports().get('ports') for port in ports: device_id = port.get('device_id') for instance in instances: if device_id == instance.id: body = { "floatingip": { "floating_network_id": pub_net_id, "tenant_id": tenant.id, "port_id": port.get('id') } } self.driver.shell.network_manager.create_floatingip(body=body)
def get_reserved_nodes(self): """ Get all OAR jobs with state Waiting or Running. :Example: {"total":"1907", "items":[ {"id":9960, "resources": ["m3-16.devgrenoble.iot-lab.info",...], "duration":"36000", "name":"test_sniffer", "state":"Running", "owner":"saintmar", "nb_resources":10, "date":1427966468}, {"id": ...} ] } """ logger.warning("iotlashell get_reserved_nodes") reserved_nodes_dict = {} request = 'admin/experiments?state=Running,Waiting' try: experiments = self.api.method(request) except HTTPError as err: logger.warning("iotlashell get_reserved_nodes error %s" % err.reason) return {'error' : err.reason} for exp in experiments['items']: # BUG IN OAR REST API : job with reservation didn't return # resources attribute list # we use another request for finding job resources exp_nodes = self.api.method('admin/experiments/%d' % exp['id']) exp['resources'] = exp_nodes['nodes'] reserved_nodes_dict[exp['id']] = exp return reserved_nodes_dict
def allocate(self, urn, rspec_string, expiration, options=None): """ Allocate method submit an experiment on Iot-LAB testbed with : * user : get the slice user which launch request (caller_hrn) * reservation : get the start time and duration in RSpec leases * nodes : get the nodes list in RSpec leases If we have a request success on Iot-LAB testbed we store in SFA database the assocation OAR scheduler job id and slice hrn :param urn : slice urn :param rspec_string : RSpec received :param options : options with slice users (geni_users) """ # pylint:disable=R0914 logger.warning("iotlabdriver allocate") xrn = Xrn(urn) aggregate = IotLABAggregate(self) # parse rspec rspec = RSpec(rspec_string) caller_hrn = options.get('actual_caller_hrn', []) geni_users = options.get('geni_users', []) caller_user = [user for user in geni_users if urn_to_hrn(user['urn'])[0] == caller_hrn][0] logger.warning("iotlabdriver allocate caller : %s" % caller_user['email']) login = self._get_user_login(caller_user) # only if we have a user if login: nodes_list, start_time, duration = \ self._get_experiment(rspec) logger.warning("iotlabdriver allocate submit OAR job :" " %s %s %s %s" % (xrn.hrn, start_time, duration, nodes_list)) # [0-9A-Za-z_] with onelab.inria.test_iotlab exp_name = '_'.join((xrn.hrn).split('.')) # submit OAR job ret = self.shell.reserve_nodes(login, exp_name, nodes_list, start_time, duration) # in case of job submission success save slice and lease job # id association in database if 'id' in ret: self._save_db_lease(int(ret['id']), xrn.hrn) return aggregate.describe([xrn.get_urn()], version=rspec.version)
def _delete_db_lease(self, job_id): """ Delete lease table row in SFA database """ logger.warning("iotlabdriver _delete_db_lease lease job_id : %s" % job_id) self.driver.api.dbsession().query(LeaseTable).filter(LeaseTable.job_id == job_id).delete() self.driver.api.dbsession().commit()
def get_slivers(self, urns, options={}): """Get slivers of the given slice urns. Slivers contains slice, node and user information. For Iotlab, returns the leases with sliver ids and their allocation status. :param urns: list of slice urns. :type urns: list of strings :param options: unused :type options: unused .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns """ slice_ids = set() node_ids = [] for urn in urns: xrn = IotlabXrn(xrn=urn) if xrn.type == 'sliver': # id: slice_id-node_id try: sliver_id_parts = xrn.get_sliver_id_parts() slice_id = int(sliver_id_parts[0]) node_id = int(sliver_id_parts[1]) slice_ids.add(slice_id) node_ids.append(node_id) except ValueError: pass else: slice_names = set() slice_names.add(xrn.hrn) logger.debug("CortexlabAggregate \t get_slivers urns %s slice_ids %s \ node_ids %s\r\n" % (urns, slice_ids, node_ids)) logger.debug("CortexlabAggregate \t get_slivers xrn %s slice_names %s \ \r\n" % (xrn, slice_names)) filter_sliver = {} if slice_names: filter_sliver['slice_hrn'] = list(slice_names) slice_hrn = filter_sliver['slice_hrn'][0] slice_filter_type = 'slice_hrn' # if slice_ids: # filter['slice_id'] = list(slice_ids) # # get slices if slice_hrn: slices = self.driver.GetSlices(slice_hrn, slice_filter_type) leases = self.driver.GetLeases({'slice_hrn': slice_hrn}) logger.debug("CortexlabAggregate \t get_slivers \ slices %s leases %s\r\n" % (slices, leases)) if not slices: return [] single_slice = slices[0] # get sliver users user = single_slice['reg_researchers'][0].__dict__ logger.debug("CortexlabAggregate \t get_slivers user %s \ \r\n" % (user)) # construct user key info person = self.driver.testbed_shell.ldap.LdapFindUser(record=user) logger.debug("CortexlabAggregate \t get_slivers person %s \ \r\n" % (person)) # name = person['last_name'] user['login'] = person['uid'] user['user_urn'] = hrn_to_urn(user['hrn'], 'user') user['keys'] = person['pkey'] try: node_ids = single_slice['node_ids'] node_list = self.driver.testbed_shell.GetNodes( {'hostname': single_slice['node_ids']}) node_by_hostname = dict([(node['hostname'], node) for node in node_list]) except KeyError: logger.warning("\t get_slivers No slivers in slice") # slice['node_ids'] = node_ids # nodes_dict = self.get_slice_nodes(slice, options) slivers = [] for current_lease in leases: for hostname in current_lease['reserved_nodes']: node = {} node['slice_id'] = current_lease['slice_id'] node['slice_hrn'] = current_lease['slice_hrn'] slice_name = current_lease['slice_hrn'].split(".")[1] node['slice_name'] = slice_name index = current_lease['reserved_nodes'].index(hostname) node_id = current_lease['resource_ids'][index] # node['slice_name'] = user['login'] # node.update(single_slice) more_info = node_by_hostname[hostname] node.update(more_info) # oar_job_id is the slice_id (lease_id) sliver_hrn = '%s.%s-%s' % (self.driver.hrn, current_lease['lease_id'], node_id) node['node_id'] = node_id node['expires'] = current_lease['t_until'] node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn node['urn'] = node['sliver_id'] node['services_user'] = [user] slivers.append(node) return slivers
def get_slivers(self, urns, options=None): """Get slivers of the given slice urns. Slivers contains slice, node and user information. For Iotlab, returns the leases with sliver ids and their allocation status. :param urns: list of slice urns. :type urns: list of strings :param options: unused :type options: unused .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns """ if options is None: options={} slice_ids = set() node_ids = [] for urn in urns: xrn = IotlabXrn(xrn=urn) if xrn.type == 'sliver': # id: slice_id-node_id try: sliver_id_parts = xrn.get_sliver_id_parts() slice_id = int(sliver_id_parts[0]) node_id = int(sliver_id_parts[1]) slice_ids.add(slice_id) node_ids.append(node_id) except ValueError: pass else: slice_names = set() slice_names.add(xrn.hrn) logger.debug("IotlabAggregate \t get_slivers urns %s slice_ids %s \ node_ids %s\r\n" % (urns, slice_ids, node_ids)) logger.debug("IotlabAggregate \t get_slivers xrn %s slice_names %s \ \r\n" % (xrn, slice_names)) filter_sliver = {} if slice_names: filter_sliver['slice_hrn'] = list(slice_names) slice_hrn = filter_sliver['slice_hrn'][0] slice_filter_type = 'slice_hrn' # if slice_ids: # filter['slice_id'] = list(slice_ids) # # get slices if slice_hrn: slices = self.driver.GetSlices(slice_hrn, slice_filter_type) leases = self.driver.GetLeases({'slice_hrn':slice_hrn}) logger.debug("IotlabAggregate \t get_slivers \ slices %s leases %s\r\n" % (slices, leases )) if not slices: return [] single_slice = slices[0] # get sliver users user = single_slice['reg_researchers'][0].__dict__ logger.debug("IotlabAggregate \t get_slivers user %s \ \r\n" % (user)) # construct user key info person = self.driver.testbed_shell.ldap.LdapFindUser(record=user) logger.debug("IotlabAggregate \t get_slivers person %s \ \r\n" % (person)) # name = person['last_name'] user['login'] = person['uid'] user['user_urn'] = hrn_to_urn(user['hrn'], 'user') user['keys'] = person['pkey'] try: node_ids = single_slice['node_ids'] node_list = self.driver.testbed_shell.GetNodes( {'hostname':single_slice['node_ids']}) node_by_hostname = dict([(node['hostname'], node) for node in node_list]) except KeyError: logger.warning("\t get_slivers No slivers in slice") # slice['node_ids'] = node_ids # nodes_dict = self.get_slice_nodes(slice, options) slivers = [] for current_lease in leases: for hostname in current_lease['reserved_nodes']: node = {} node['slice_id'] = current_lease['slice_id'] node['slice_hrn'] = current_lease['slice_hrn'] slice_name = current_lease['slice_hrn'].split(".")[1] node['slice_name'] = slice_name index = current_lease['reserved_nodes'].index(hostname) node_id = current_lease['resource_ids'][index] # node['slice_name'] = user['login'] # node.update(single_slice) more_info = node_by_hostname[hostname] node.update(more_info) # oar_job_id is the slice_id (lease_id) sliver_hrn = '%s.%s-%s' % (self.driver.hrn, current_lease['lease_id'], node_id) node['node_id'] = node_id node['expires'] = current_lease['t_until'] node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn node['urn'] = node['sliver_id'] node['services_user'] = [user] slivers.append(node) return slivers
def describe(self, urns, version, options=None): logger.warning("iotlabdriver describe") if not options: options = {} aggregate = IotLABAggregate(self) return aggregate.describe(urns, version=version, options=options)
def run_sfatables(_, __, ___, rspec, ____=None): logger.warning( "Cannot import sfatables.runtime, please install package sfa-sfatables" ) return rspec
# up to fedora20 we used os.popen and checked that the output begins with OK # turns out, with fedora21, there is extra input before this 'OK' thing # looks like we're better off just using the exit code - that's what it is made for #cert_args = " ".join(['--trusted-pem %s' % x for x in trusted_certs]) #command = '{} --verify --node-id "{}" {} {} 2>&1'.\ # format(self.xmlsec_path, ref, cert_args, filename) command = [ self.xmlsec_path, '--verify', '--node-id', ref ] for trusted in trusted_certs: command += ["--trusted-pem", trusted ] command += [ filename ] logger.debug("Running " + " ".join(command)) try: verified = subprocess.check_output(command, stderr=subprocess.STDOUT) logger.debug("xmlsec command returned {}".format(verified)) if "OK\n" not in verified: logger.warning("WARNING: xmlsec1 seemed to return fine but without a OK in its output") except subprocess.CalledProcessError as e: verified = e.output # xmlsec errors have a msg= which is the interesting bit. mstart = verified.find("msg=") msg = "" if mstart > -1 and len(verified) > 4: mstart = mstart + 4 mend = verified.find('\\', mstart) msg = verified[mstart:mend] logger.warning("Credential.verify - failed - xmlsec1 returned {}".format(verified.strip())) raise CredentialNotVerifiable("xmlsec1 error verifying cred %s using Signature ID %s: %s" % \ (self.pretty_cred(), ref, msg)) os.remove(filename) # Verify the parents (delegation)
def describe(self, urns, version=None, options=None): """ describe method returns slice slivers (allocated resources) and leases (OAR job submission). We search in lease table of SFA database all OAR jobs id for this slice and match OAR jobs with state Waiting or Running. If OAR job id doesn't exist the experiment is terminated and we delete the database table entry. Otherwise we add slivers and leases in the response :returns: geni_slivers : a list of allocated slivers with information about their allocation and operational state geni_urn : the URN of the slice in which the sliver has been allocated geni_rspec: a RSpec describing the allocated slivers and leases :rtype: dict :Example: <rspec> ... <node component_manager_id="urn:publicid:IDN+iotlab+authority+sa" component_id= "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info" client_id="m3-10.grenoble.iot-lab.info" sliver_id="urn:publicid:IDN+iotlab+sliver+9953-m3-10" exclusive="true" component_name="m3-10.grenoble.iot-lab.info"> <hardware_type name="iotlab-node"/> <location country="France"/> <granularity grain="30"/> <sliver_type name="iotlab-exclusive"/> </node> <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab" start_time="1427792428" duration="29"> <node component_id= "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info"/> </lease> ... </rspec> """ # pylint:disable=R0914,W0212 logger.warning("iotlabaggregate describe") logger.warning("iotlabaggregate describe urns : %s" % urns) if not options: 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) xrn = Xrn(urns[0]) geni_slivers = [] nodes = self.driver.shell.get_nodes() reserved_nodes = self.driver.shell.get_reserved_nodes() if not "error" in nodes and not "error" in reserved_nodes: # find OAR jobs id for one slice in SFA database db_leases = [ (lease.job_id, lease.slice_hrn) for lease in self.driver.api.dbsession().query(LeaseTable).filter(LeaseTable.slice_hrn == xrn.hrn).all() ] leases = [] for job_id, slice_hrn in db_leases: # OAR job terminated, we delete entry in database if not job_id in reserved_nodes: self._delete_db_lease(job_id) else: # onelab slice = job submission from OneLAB lease = reserved_nodes[job_id] lease["slice_id"] = hrn_to_urn(slice_hrn, "slice") leases.append(lease) # get slivers slivers = self.get_slivers(urns, leases, nodes) if slivers: date = utcparse(slivers[0]["expires"]) rspec_expires = datetime_to_string(date) else: rspec_expires = datetime_to_string(utcparse(time.time())) rspec.xml.set("expires", rspec_expires) rspec_nodes = [] for sliver in slivers: rspec_node = self.sliver_to_rspec_node(sliver) rspec_nodes.append(rspec_node) geni_sliver = self.rspec_node_to_geni_sliver(rspec_node) geni_slivers.append(geni_sliver) logger.warning("iotlabaggregate describe geni_slivers %s" % geni_slivers) rspec.version.add_nodes(rspec_nodes) rspec_leases = self.leases_to_rspec_leases(leases) logger.warning("iotlabaggregate describe rspec_leases %s" % rspec_leases) rspec.version.add_leases(rspec_leases) return {"geni_urn": urns[0], "geni_rspec": rspec.toxml(), "geni_slivers": geni_slivers}
def list_resources(self, version=None, options=None): """ list_resources method sends a RSpec with all Iot-LAB testbed nodes and leases (OAR job submission). For leases we get all OAR jobs with state Waiting or Running. If we have an entry in SFA database (lease table) with OAR job id this submission was launched by SFA driver, otherwise it was launched by Iot-LAB Webportal or CLI-tools :Example: <rspec> ... <node component_manager_id="urn:publicid:IDN+iotlab+authority+sa" component_id= "urn:publicid:IDN+iotlab+node+m3-10.devgrenoble.iot-lab.info" exclusive="true" component_name="m3-10.devgrenoble.iot-lab.info"> <hardware_type name="iotlab-node"/> <location country="France"/> <granularity grain="60"/> ... </node> ... <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab" start_time="1427792400" duration="30"> <node component_id= "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info"/> </lease> ... </rspec> """ # pylint:disable=R0914,W0212 logger.warning("iotlabaggregate list_resources") logger.warning("iotlabaggregate list_resources options %s" % options) if not options: 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) nodes = self.driver.shell.get_nodes() reserved_nodes = self.driver.shell.get_reserved_nodes() if not "error" in nodes and not "error" in reserved_nodes: # convert nodes to rspec nodes rspec_nodes = [] for node in nodes: rspec_node = self.node_to_rspec_node(nodes[node]) rspec_nodes.append(rspec_node) rspec.version.add_nodes(rspec_nodes) leases = [] db_leases = {} # find OAR jobs id for all slices in SFA database for lease in self.driver.api.dbsession().query(LeaseTable).all(): db_leases[lease.job_id] = lease.slice_hrn for lease_id in reserved_nodes: # onelab slice = job submission from OneLAB if lease_id in db_leases: reserved_nodes[lease_id]["slice_id"] = hrn_to_urn(db_leases[lease_id], "slice") # iotlab slice = job submission from Iot-LAB else: reserved_nodes[lease_id]["slice_id"] = hrn_to_urn( self.driver.root_auth + "." + reserved_nodes[lease_id]["owner"] + "_slice", "slice" ) leases.append(reserved_nodes[lease_id]) rspec_leases = self.leases_to_rspec_leases(leases) logger.warning("iotlabaggregate list_resources rspec_leases %s" % rspec_leases) rspec.version.add_leases(rspec_leases) return rspec.toxml()