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
13 class IotLabDriver(Driver):
15 SFA driver for Iot-LAB testbed
18 def __init__(self, api):
19 Driver.__init__(self, api)
22 self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
23 self.shell = IotLABShell()
27 ########################################
28 ########## registry oriented
29 ########################################
32 def register(self, sfa_record, hrn, pub_key):
33 logger.warning("iotlabdriver register : not implemented")
37 def update(self, old_sfa_record, new_sfa_record, hrn, new_key):
38 logger.warning("iotlabdriver update : not implemented")
43 def remove(self, sfa_record):
44 logger.warning("iotlabdriver remove : not implemented")
48 ########################################
49 ########## aggregate oriented
50 ########################################
52 def provision(self, urns, options=None):
53 logger.warning("iotlabdriver provision : not implemented")
54 version_manager = VersionManager()
55 opt = options['geni_rspec_version']
56 rspec_version = version_manager.get_version(opt)
57 return self.describe(urns, rspec_version, options=options)
60 def delete(self, urns, options=None):
61 logger.warning("iotlabdriver delete : not implemented")
66 def aggregate_version(self):
67 logger.warning("iotlabdriver aggregate_version")
68 version_manager = VersionManager()
69 ad_rspec_versions = []
70 request_rspec_versions = []
71 for rspec_version in version_manager.versions:
72 if rspec_version.content_type in ['*', 'ad']:
73 ad_rspec_versions.append(rspec_version.to_dict())
74 if rspec_version.content_type in ['*', 'request']:
75 request_rspec_versions.append(rspec_version.to_dict())
78 'geni_request_rspec_versions': request_rspec_versions,
79 'geni_ad_rspec_versions': ad_rspec_versions}
82 def list_resources(self, version=None, options=None):
83 logger.warning("iotlabdriver list_resources")
86 aggregate = IotLABAggregate(self)
87 rspec = aggregate.list_resources(version=version, options=options)
91 def describe(self, urns, version, options=None):
92 logger.warning("iotlabdriver describe")
95 aggregate = IotLABAggregate(self)
96 return aggregate.describe(urns, version=version, options=options)
99 def status(self, urns, options=None):
100 logger.warning("iotlabdriver status")
101 aggregate = IotLABAggregate(self)
102 desc = aggregate.describe(urns, version='GENI 3')
103 status = {'geni_urn': desc['geni_urn'],
104 'geni_slivers': desc['geni_slivers']}
108 def _get_users(self):
109 """ Get all users """
110 ret = self.shell.get_users()
116 def _get_user_login(self, caller_user):
117 """ Get user login with email """
118 email = caller_user['email']
119 # ensure user exist in LDAP tree
120 users = self._get_users()
121 if users and not email in users:
122 self.shell.add_user(caller_user)
123 users = self._get_users()
124 if users and email in users:
125 return users[email]['login']
131 def _get_experiment(cls, rspec):
133 Find in RSpec leases the experiment start time, duration and nodes list.
138 <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab"
139 start_time="1427792400" duration="30">
141 "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info"/>
143 <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab"
144 start_time="1427792600" duration="50">
146 "urn:publicid:IDN+iotlab+node+m3-15.grenoble.iot-lab.info"/>
151 leases = rspec.version.get_leases()
152 start_time = min([int(lease['start_time'])
153 for lease in leases])
154 end_time = max([int(lease['start_time']) +
155 int(lease['duration'])
156 for lease in leases])
157 nodes_list = [Xrn.unescape(Xrn(lease['component_id'].strip(),
158 type='node').get_leaf())
161 nodes_list = list(set(nodes_list))
162 from math import floor
163 duration = floor((end_time - start_time)/60) # minutes
164 return nodes_list, start_time, duration
167 def _save_db_lease(self, job_id, slice_hrn):
168 """ Save lease table row in SFA database """
169 lease_row = LeaseTable(job_id,
171 logger.warning("iotlabdriver _save_db_lease lease row : %s" %
173 self.api.dbsession().add(lease_row)
174 self.api.dbsession().commit()
177 def allocate(self, urn, rspec_string, expiration, options=None):
179 Allocate method submit an experiment on Iot-LAB testbed with :
180 * user : get the slice user which launch request (caller_hrn)
181 * reservation : get the start time and duration in RSpec leases
182 * nodes : get the nodes list in RSpec leases
183 If we have a request success on Iot-LAB testbed we store in SFA
184 database the assocation OAR scheduler job id and slice hrn
186 :param urn : slice urn
187 :param rspec_string : RSpec received
188 :param options : options with slice users (geni_users)
190 # pylint:disable=R0914
192 logger.warning("iotlabdriver allocate")
194 aggregate = IotLABAggregate(self)
196 rspec = RSpec(rspec_string)
198 caller_hrn = options.get('actual_caller_hrn', [])
199 geni_users = options.get('geni_users', [])
200 caller_user = [user for user in geni_users if
201 urn_to_hrn(user['urn'])[0] == caller_hrn][0]
202 logger.warning("iotlabdriver allocate caller : %s" %
203 caller_user['email'])
205 login = self._get_user_login(caller_user)
206 # only if we have a user
208 nodes_list, start_time, duration = \
209 self._get_experiment(rspec)
210 logger.warning("iotlabdriver allocate submit OAR job :"
212 (xrn.hrn, start_time, duration, nodes_list))
213 # [0-9A-Za-z_] with onelab.inria.test_iotlab
214 exp_name = '_'.join((xrn.hrn).split('.'))
216 ret = self.shell.reserve_nodes(login,
222 # in case of job submission success save slice and lease job
223 # id association in database
225 self._save_db_lease(int(ret['id']),
228 return aggregate.describe([xrn.get_urn()], version=rspec.version)