2 """ driver class management """
4 from sfa.util.sfalogging import logger
5 from sfa.util.xrn import Xrn, urn_to_hrn
6 from sfa.rspecs.version_manager import VersionManager
7 from sfa.rspecs.rspec import RSpec
8 from sfa.managers.driver import Driver
9 from sfa.iotlab.iotlabshell import IotLABShell
10 from sfa.iotlab.iotlabaggregate import IotLABAggregate
11 from sfa.iotlab.iotlablease import LeaseTable
14 class IotLabDriver(Driver):
16 SFA driver for Iot-LAB testbed
19 def __init__(self, api):
20 Driver.__init__(self, api)
23 self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
24 self.shell = IotLABShell()
28 def check_sliver_credentials(self, creds, urns):
29 """ Not used and need by SFA """
32 # #######################################
33 # ######### registry oriented
34 # #######################################
37 def register(self, sfa_record, hrn, pub_key):
38 logger.warning("iotlabdriver register : not implemented")
41 def update(self, old_sfa_record, new_sfa_record, hrn, new_key):
42 logger.warning("iotlabdriver update : not implemented")
45 def remove(self, sfa_record):
46 logger.warning("iotlabdriver remove : not implemented")
49 # #######################################
50 # ######### aggregate oriented
51 # #######################################
53 def provision(self, urns, options=None):
54 logger.warning("iotlabdriver provision : not implemented")
55 version_manager = VersionManager()
56 opt = options['geni_rspec_version']
57 rspec_version = version_manager.get_version(opt)
58 return self.describe(urns, rspec_version, options=options)
60 def delete(self, urns, options=None):
61 logger.warning("iotlabdriver delete : not implemented")
65 def aggregate_version(self):
66 logger.warning("iotlabdriver aggregate_version")
67 version_manager = VersionManager()
68 ad_rspec_versions = []
69 request_rspec_versions = []
70 for rspec_version in version_manager.versions:
71 if rspec_version.content_type in ['*', 'ad']:
72 ad_rspec_versions.append(rspec_version.to_dict())
73 if rspec_version.content_type in ['*', 'request']:
74 request_rspec_versions.append(rspec_version.to_dict())
77 'geni_request_rspec_versions': request_rspec_versions,
78 'geni_ad_rspec_versions': ad_rspec_versions}
80 def list_resources(self, version=None, options=None):
81 logger.warning("iotlabdriver list_resources")
84 aggregate = IotLABAggregate(self)
85 rspec = aggregate.list_resources(version=version, options=options)
88 def describe(self, urns, version, options=None):
89 logger.warning("iotlabdriver describe")
92 aggregate = IotLABAggregate(self)
93 return aggregate.describe(urns, version=version, options=options)
95 def status(self, urns, options=None):
96 logger.warning("iotlabdriver status")
97 aggregate = IotLABAggregate(self)
98 desc = aggregate.describe(urns, version='GENI 3')
99 status = {'geni_urn': desc['geni_urn'],
100 'geni_slivers': desc['geni_slivers']}
103 def _get_users(self):
104 """ Get all users """
105 ret = self.shell.get_users()
110 def _get_user_login(self, caller_user):
111 """ Get user login with email """
112 email = caller_user['email']
113 # ensure user exist in LDAP tree
114 users = self._get_users()
115 if users and email not in users:
116 self.shell.add_user(caller_user)
117 users = self._get_users()
118 if users and email in users:
119 return users[email]['login']
124 def _get_experiment(cls, rspec):
126 Find in RSpec leases the experiment start time, duration and nodes
132 <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab"
133 start_time="1427792400" duration="30">
135 "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info"/>
137 <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab"
138 start_time="1427792600" duration="50">
140 "urn:publicid:IDN+iotlab+node+m3-15.grenoble.iot-lab.info"/>
145 leases = rspec.version.get_leases()
146 start_time = min([int(lease['start_time'])
147 for lease in leases])
148 end_time = max([int(lease['start_time']) +
149 int(lease['duration'])*60
150 for lease in leases])
151 nodes_list = [Xrn.unescape(Xrn(lease['component_id'].strip(),
152 type='node').get_leaf())
155 nodes_list = list(set(nodes_list))
156 from math import floor
158 duration = floor((end_time - start_time)/60)
159 return nodes_list, start_time, duration
161 def _save_db_lease(self, job_id, slice_hrn):
162 """ Save lease table row in SFA database """
163 lease_row = LeaseTable(job_id,
165 logger.warning("iotlabdriver _save_db_lease lease row : %s" %
167 self.api.dbsession().add(lease_row)
168 self.api.dbsession().commit()
170 def allocate(self, urn, rspec_string, expiration, options=None):
172 Allocate method submit an experiment on Iot-LAB testbed with :
173 * user : get the slice user which launch request (caller_hrn)
174 * reservation : get the start time and duration in RSpec leases
175 * nodes : get the nodes list in RSpec leases
176 If we have a request success on Iot-LAB testbed we store in SFA
177 database the assocation OAR scheduler job id and slice hrn
179 :param urn : slice urn
180 :param rspec_string : RSpec received
181 :param options : options with slice users (geni_users)
183 # pylint:disable=R0914
185 logger.warning("iotlabdriver allocate")
187 aggregate = IotLABAggregate(self)
189 rspec = RSpec(rspec_string)
191 caller_hrn = options.get('actual_caller_hrn', [])
192 geni_users = options.get('geni_users', [])
193 caller_user = [user for user in geni_users if
194 urn_to_hrn(user['urn'])[0] == caller_hrn][0]
195 logger.warning("iotlabdriver allocate caller : %s" %
196 caller_user['email'])
198 login = self._get_user_login(caller_user)
199 # only if we have a user
201 nodes_list, start_time, duration = \
202 self._get_experiment(rspec)
203 logger.warning("iotlabdriver allocate submit OAR job :"
205 (xrn.hrn, start_time, duration, nodes_list))
206 # [0-9A-Za-z_] with onelab.inria.test_iotlab
207 exp_name = '_'.join((xrn.hrn).split('.'))
209 ret = self.shell.reserve_nodes(login,
215 # in case of job submission success save slice and lease job
216 # id association in database
218 self._save_db_lease(int(ret['id']),
221 return aggregate.describe([xrn.get_urn()], version=rspec.version)