"""
from sfa.util.faults import SliverDoesNotExist, UnknownSfaType
from sfa.util.sfalogging import logger
-from sfa.storage.alchemy import dbsession
from sfa.storage.model import RegRecord
+from sfa.util.sfatime import utcparse, datetime_to_string
from sfa.managers.driver import Driver
from sfa.rspecs.version_manager import VersionManager
from sfa.rspecs.rspec import RSpec
-from sfa.util.xrn import Xrn, hrn_to_urn, get_authority
+from sfa.iotlab.iotlabxrn import xrn_object
+from sfa.util.xrn import Xrn, hrn_to_urn, get_authority, urn_to_hrn
-from sfa.iotlab.iotlabaggregate import IotlabAggregate, iotlab_xrn_to_hostname
+from sfa.iotlab.iotlabaggregate import IotlabAggregate
+from sfa.iotlab.iotlabxrn import xrn_to_hostname
from sfa.iotlab.iotlabslices import IotlabSlices
-
-from sfa.iotlab.iotlabapi import IotlabTestbedAPI
+from sfa.storage.model import SliverAllocation
+from sfa.iotlab.iotlabshell import IotlabShell
class IotlabDriver(Driver):
.. seealso::: Driver class
"""
- def __init__(self, config):
+ def __init__(self, api):
"""
Sets the iotlab SFA config parameters,
:type config: Config object
"""
- Driver.__init__(self, config)
- self.config = config
- self.iotlab_api = IotlabTestbedAPI(config)
+ Driver.__init__(self, api)
+ self.api = api
+ config = api.config
+ self.testbed_shell = IotlabShell(api)
self.cache = None
def augment_records_with_testbed_info(self, record_list):
# look for node info using GetNodes
# the record is about one node only
filter_dict = {'hrn': [record['hrn']]}
- node_info = self.iotlab_api.GetNodes(filter_dict)
+ node_info = self.testbed_shell.GetNodes(filter_dict)
# the node_info is about one node only, but it is formatted
# as a list
record.update(node_info[0])
'key_ids': ''})
#Get iotlab slice record and oar job id if any.
- recslice_list = self.iotlab_api.GetSlices(
+ recslice_list = self.testbed_shell.GetSlices(
slice_filter=str(record['hrn']),
slice_filter_type='slice_hrn')
fill_record_info oar_job_id %s "
% (rec['oar_job_id']))
- record['node_ids'] = [self.iotlab_api.root_auth +
+ record['node_ids'] = [self.testbed_shell.root_auth +
'.' + hostname for hostname
in rec['node_ids']]
except KeyError:
#The record is a SFA user record.
#Get the information about his slice from Iotlab's DB
#and add it to the user record.
- recslice_list = self.iotlab_api.GetSlices(
+ recslice_list = self.testbed_shell.GetSlices(
slice_filter=record['record_id'],
slice_filter_type='record_id_user')
'hrn': recslice_list[0]['hrn']})
#GetPersons takes [] as filters
- user_iotlab = self.iotlab_api.GetPersons([record])
+ user_iotlab = self.testbed_shell.GetPersons([record])
record.update(user_iotlab[0])
#For client_helper.py compatibility
"""
#First get the slice with the slice hrn
- slice_list = self.iotlab_api.GetSlices(slice_filter=slice_hrn,
+ slice_list = self.testbed_shell.GetSlices(slice_filter=slice_hrn,
slice_filter_type='slice_hrn')
if len(slice_list) == 0:
slice_nodes_list = []
slice_nodes_list = one_slice['node_ids']
#Get all the corresponding nodes details
- nodes_all = self.iotlab_api.GetNodes(
+ nodes_all = self.testbed_shell.GetNodes(
{'hostname': slice_nodes_list},
['node_id', 'hostname', 'site', 'boot_state'])
nodeall_byhostname = dict([(one_node['hostname'], one_node)
% (resources, res))
return result
- @staticmethod
- def get_user_record(hrn):
+ def get_user_record(self, hrn):
"""
Returns the user record based on the hrn from the SFA DB .
:rtype: RegUser
"""
- return dbsession.query(RegRecord).filter_by(hrn=hrn).first()
+ return self.api.dbsession().query(RegRecord).filter_by(hrn=hrn).first()
def testbed_name(self):
"""
if not lease.get('lease_id'):
if get_authority(lease['component_id']) == \
- self.iotlab_api.root_auth:
+ self.testbed_shell.root_auth:
single_requested_lease['hostname'] = \
- iotlab_xrn_to_hostname(\
+ xrn_to_hostname(\
lease.get('component_id').strip())
single_requested_lease['start_time'] = \
lease.get('start_time')
#the lease to the requested leases list
duration_in_seconds = \
int(single_requested_lease['duration'])
- if duration_in_seconds >= self.iotlab_api.GetMinExperimentDurationInGranularity():
+ if duration_in_seconds >= self.testbed_shell.GetMinExperimentDurationInGranularity():
requested_lease_list.append(single_requested_lease)
return requested_lease_list
"""
- requested_job_dict = {}
+ requested_xp_dict = {}
for lease in requested_lease_list:
#In case it is an asap experiment start_time is empty
if lease['start_time'] == '':
lease['start_time'] = '0'
- if lease['start_time'] not in requested_job_dict:
+ if lease['start_time'] not in requested_xp_dict:
if isinstance(lease['hostname'], str):
lease['hostname'] = [lease['hostname']]
- requested_job_dict[lease['start_time']] = lease
+ requested_xp_dict[lease['start_time']] = lease
else:
- job_lease = requested_job_dict[lease['start_time']]
+ job_lease = requested_xp_dict[lease['start_time']]
if lease['duration'] == job_lease['duration']:
job_lease['hostname'].append(lease['hostname'])
- return requested_job_dict
+ return requested_xp_dict
- def _process_requested_jobs(self, rspec):
+ def _process_requested_xp_dict(self, rspec):
"""
Turns the requested leases and information into a dictionary
of requested jobs, grouped by starting time.
"""
requested_lease_list = self._get_requested_leases_list(rspec)
- logger.debug("IOTLABDRIVER _process_requested_jobs \
+ logger.debug("IOTLABDRIVER _process_requested_xp_dict \
requested_lease_list %s" % (requested_lease_list))
- job_dict = self._group_leases_by_start_time(requested_lease_list)
- logger.debug("IOTLABDRIVER _process_requested_jobs job_dict\
- %s" % (job_dict))
+ xp_dict = self._group_leases_by_start_time(requested_lease_list)
+ logger.debug("IOTLABDRIVER _process_requested_xp_dict xp_dict\
+ %s" % (xp_dict))
+
+ return xp_dict
- return job_dict
def create_sliver(self, slice_urn, slice_hrn, creds, rspec_string,
users, options):
#requested_slivers = [node.get('component_id') \
#for node in rspec.version.get_nodes_with_slivers()\
- #if node.get('authority_id') is self.iotlab_api.root_auth]
+ #if node.get('authority_id') is self.testbed_shell.root_auth]
#l = [ node for node in rspec.version.get_nodes_with_slivers() ]
#logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
#requested_slivers %s listnodes %s" \
#verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
#slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
- requested_job_dict = self._process_requested_jobs(rspec)
+ requested_xp_dict = self._process_requested_xp_dict(rspec)
- logger.debug("IOTLABDRIVER.PY \tcreate_sliver requested_job_dict %s "
- % (requested_job_dict))
+ logger.debug("IOTLABDRIVER.PY \tcreate_sliver requested_xp_dict %s "
+ % (requested_xp_dict))
#verify_slice_leases returns the leases , but the return value is unused
#here. Removed SA 13/08/12
slices.verify_slice_leases(sfa_slice,
- requested_job_dict, peer)
+ requested_xp_dict, peer)
return aggregate.get_rspec(slice_xrn=slice_urn,
login=sfa_slice['login'],
version=rspec.version)
- def delete_sliver(self, slice_urn, slice_hrn, creds, options):
+ def delete(self, slice_urns, options):
"""
Deletes the lease associated with the slice hrn and the credentials
if the slice belongs to iotlab. Answer to DeleteSliver.
:param slice_urn: urn of the slice
- :param slice_hrn: name of the slice
- :param creds: slice credenials
:type slice_urn: string
- :type slice_hrn: string
- :type creds: ? unused
+
:returns: 1 if the slice to delete was not found on iotlab,
True if the deletion was successful, False otherwise otherwise.
.. note:: creds are unused, and are not used either in the dummy driver
delete_sliver .
"""
-
- sfa_slice_list = self.iotlab_api.GetSlices(
+ # collect sliver ids so we can update sliver allocation states after
+ # we remove the slivers.
+ aggregate = IotlabAggregate(self)
+ slivers = aggregate.get_slivers(slice_urns)
+ if slivers:
+ slice_id = slivers[0]['slice_id']
+ node_ids = []
+ sliver_ids = []
+ for sliver in slivers:
+ node_ids.append(sliver['node_id'])
+ sliver_ids.append(sliver['sliver_id'])
+ logger.debug("IOTLABDRIVER.PY delete_sliver slivers %s slice_urns %s"
+ % (slivers, slice_urns))
+ slice_hrn = urn_to_hrn(slice_urns[0])[0]
+
+ sfa_slice_list = self.testbed_shell.GetSlices(
slice_filter=slice_hrn,
slice_filter_type='slice_hrn')
logger.debug("IOTLABDRIVER.PY delete_sliver peer %s \
\r\n \t sfa_slice %s " % (peer, sfa_slice))
try:
- self.iotlab_api.DeleteSliceFromNodes(sfa_slice)
- return True
+ self.testbed_shell.DeleteSliceFromNodes(sfa_slice)
+ dbsession = self.api.dbsession()
+ SliverAllocation.delete_allocations(sliver_ids,dbsession)
except:
- return False
+ logger.log_exc("IOTLABDRIVER.PY delete error ")
+
+ # prepare return struct
+ geni_slivers = []
+ for sliver in slivers:
+ geni_slivers.append(
+ {'geni_sliver_urn': sliver['sliver_id'],
+ 'geni_allocation_status': 'geni_unallocated',
+ 'geni_expires': datetime_to_string(utcparse(sliver['expires']))})
+ return geni_slivers
def list_resources (self, slice_urn, slice_hrn, creds, options):
"""
# get data from db
- slices = self.iotlab_api.GetSlices()
+ slices = self.testbed_shell.GetSlices()
logger.debug("IOTLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n"
% (slices))
slice_hrns = [iotlab_slice['hrn'] for iotlab_slice in slices]
if new_key:
# must check this key against the previous one if it exists
- persons = self.iotlab_api.GetPersons([old_sfa_record])
+ persons = self.testbed_shell.GetPersons([old_sfa_record])
person = persons[0]
keys = [person['pkey']]
#Get all the person's keys
- keys_dict = self.iotlab_api.GetKeys(keys)
+ keys_dict = self.testbed_shell.GetKeys(keys)
# Delete all stale keys, meaning the user has only one key
#at a time
else:
#remove all the other keys
for key in keys_dict:
- self.iotlab_api.DeleteKey(person, key)
- self.iotlab_api.AddPersonKey(
+ self.testbed_shell.DeleteKey(person, key)
+ self.testbed_shell.AddPersonKey(
person, {'sshPublicKey': person['pkey']},
{'sshPublicKey': new_key})
return True
if sfa_record_type == 'user':
#get user from iotlab ldap
- person = self.iotlab_api.GetPersons(sfa_record)
+ person = self.testbed_shell.GetPersons(sfa_record)
#No registering at a given site in Iotlab.
#Once registered to the LDAP, all iotlab sites are
#accesible.
if person:
#Mark account as disabled in ldap
- return self.iotlab_api.DeletePerson(sfa_record)
+ return self.testbed_shell.DeletePerson(sfa_record)
elif sfa_record_type == 'slice':
- if self.iotlab_api.GetSlices(slice_filter=hrn,
+ if self.testbed_shell.GetSlices(slice_filter=hrn,
slice_filter_type='slice_hrn'):
- ret = self.iotlab_api.DeleteSlice(sfa_record)
+ ret = self.testbed_shell.DeleteSlice(sfa_record)
return True
+
+ def check_sliver_credentials(self, creds, urns):
+ # build list of cred object hrns
+ slice_cred_names = []
+ for cred in creds:
+ slice_cred_hrn = Credential(cred=cred).get_gid_object().get_hrn()
+ slicename = Xrn(xrn=slice_cred_hrn).iotlab_slicename()
+ logger.debug("IOTLABDRIVER.PY \t check_sliver_credentials slicename %s \r\n \r\n"
+ % (slicename))
+ slice_cred_names.append(slicename)
+
+ # look up slice name of slivers listed in urns arg
+
+ slice_ids = []
+ for urn in urns:
+ sliver_id_parts = Xrn(xrn=urn).get_sliver_id_parts()
+ try:
+ slice_ids.append(int(sliver_id_parts[0]))
+ except ValueError:
+ pass
+
+ if not slice_ids:
+ raise Forbidden("sliver urn not provided")
+
+ slices = self.testbed_shell.GetSlices(slice_ids)
+ sliver_names = [single_slice['name'] for single_slice in slices]
+
+ # make sure we have a credential for every specified sliver ierd
+ for sliver_name in sliver_names:
+ if sliver_name not in slice_cred_names:
+ msg = "Valid credential not found for target: %s" % sliver_name
+ raise Forbidden(msg)
+
+ ########################################
+ ########## aggregate oriented
+ ########################################
+
+
+ def testbed_name (self): return "iotlab"
+
+ def aggregate_version (self):
+ return {}
+
+ # first 2 args are None in case of resource discovery
+ def list_resources (self, version=None, options={}):
+ aggregate = IotlabAggregate(self)
+ rspec = aggregate.list_resources(version=version, options=options)
+ return rspec
+
+ def describe(self, urns, version, options={}):
+ aggregate = IotlabAggregate(self)
+ return aggregate.describe(urns, version=version, options=options)
+
+ def status (self, urns, options={}):
+ aggregate = IotlabAggregate(self)
+ desc = aggregate.describe(urns, version='GENI 3')
+ status = {'geni_urn': desc['geni_urn'],
+ 'geni_slivers': desc['geni_slivers']}
+ return status
+
+
+ def allocate (self, urn, rspec_string, expiration, options={}):
+ xrn = Xrn(urn)
+ aggregate = IotlabAggregate(self)
+
+ slices = IotlabSlices(self)
+ peer = slices.get_peer(xrn.get_hrn())
+ sfa_peer = slices.get_sfa_peer(xrn.get_hrn())
+
+
+ slice_record = None
+ users = options.get('geni_users', [])
+
+ sfa_users = options.get('sfa_users', [])
+ if sfa_users:
+ slice_record = sfa_users[0].get('slice_record', [])
+ logger.debug("IOTLABDRIVER.PY \t ===============allocate \t\
+ \r\n \r\n options %s slice_record %s" % (options,slice_record))
+ # parse rspec
+ rspec = RSpec(rspec_string)
+ # requested_attributes = rspec.version.get_slice_attributes()
+
+ # ensure site record exists
+ # site = slices.verify_site(xrn.hrn, slice_record, peer, sfa_peer, options=options)
+ # ensure slice record exists
+
+ current_slice = slices.verify_slice(xrn.hrn, slice_record, sfa_peer)
+ logger.debug("IOTLABDRIVER.PY \t ===============allocate \t\
+ \r\n \r\n current_slice %s" % (current_slice))
+ # ensure person records exists
+
+ # oui c'est degueulasse, le slice_record se retrouve modifie
+ # dans la methode avec les infos du user, els infos sont propagees
+ # dans verify_slice_leases
+ persons = slices.verify_persons(xrn.hrn, slice_record, users, options=options)
+ # ensure slice attributes exists
+ # slices.verify_slice_attributes(slice, requested_attributes, options=options)
+
+ # add/remove slice from nodes
+ requested_xp_dict = self._process_requested_xp_dict(rspec)
+
+ logger.debug("IOTLABDRIVER.PY \tallocate requested_xp_dict %s "
+ % (requested_xp_dict))
+ request_nodes = rspec.version.get_nodes_with_slivers()
+ nodes_list = []
+ for start_time in requested_xp_dict:
+ lease = requested_xp_dict[start_time]
+ for hostname in lease['hostname']:
+ nodes_list.append(hostname)
+
+ # nodes = slices.verify_slice_nodes(slice_record,request_nodes, peer)
+ logger.debug("IOTLABDRIVER.PY \tallocate nodes_list %s slice_record %s"
+ % (nodes_list, slice_record))
+
+ # add/remove leases
+ rspec_requested_leases = rspec.version.get_leases()
+ leases = slices.verify_slice_leases(slice_record, requested_xp_dict, peer)
+ logger.debug("IOTLABDRIVER.PY \tallocate leases %s rspec_requested_leases %s"
+ % (leases,rspec_requested_leases))
+ # update sliver allocations
+ for hostname in nodes_list:
+ client_id = hostname
+ node_urn = xrn_object(self.testbed_shell.root_auth, hostname).urn
+ component_id = node_urn
+ slice_urn = current_slice['reg-urn']
+ for lease in leases:
+ if hostname in lease['reserved_nodes']:
+ index = lease['reserved_nodes'].index(hostname)
+ sliver_hrn = '%s.%s-%s' % (self.hrn, lease['lease_id'],
+ lease['resource_ids'][index] )
+ sliver_id = Xrn(sliver_hrn, type='sliver').urn
+ record = SliverAllocation(sliver_id=sliver_id, client_id=client_id,
+ component_id=component_id,
+ slice_urn = slice_urn,
+ allocation_state='geni_allocated')
+
+ logger.debug("\r\n \
+ ===============================IOTLABDRIVER.PY \tallocate sliver_id %s slice_urn %s \r\n"
+ % (sliver_id,slice_urn))
+ record.sync(self.api.dbsession())
+ # add/remove links links
+ # slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
+
+
+
+ return aggregate.describe([xrn.get_urn()], version=rspec.version)
+
+ def provision(self, urns, options={}):
+ # update users
+ slices = IotlabSlices(self)
+ aggregate = IotlabAggregate(self)
+ slivers = aggregate.get_slivers(urns)
+ current_slice = slivers[0]
+ peer = slices.get_peer(current_slice['hrn'])
+ sfa_peer = slices.get_sfa_peer(current_slice['hrn'])
+ users = options.get('geni_users', [])
+ # persons = slices.verify_persons(current_slice['hrn'],
+ # current_slice, users, peer, sfa_peer, options=options)
+ # slices.handle_peer(None, None, persons, peer)
+ # update sliver allocation states and set them to geni_provisioned
+ sliver_ids = [sliver['sliver_id'] for sliver in slivers]
+ dbsession =self.api.dbsession()
+ SliverAllocation.set_allocations(sliver_ids, 'geni_provisioned',dbsession)
+ version_manager = VersionManager()
+ rspec_version = version_manager.get_version(options['geni_rspec_version'])
+ return self.describe(urns, rspec_version, options=options)