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 version_manager = VersionManager()
67 ad_rspec_versions = []
68 request_rspec_versions = []
69 for rspec_version in version_manager.versions:
70 if rspec_version.content_type in ['*', 'ad']:
71 ad_rspec_versions.append(rspec_version.to_dict())
72 if rspec_version.content_type in ['*', 'request']:
73 request_rspec_versions.append(rspec_version.to_dict())
76 'geni_request_rspec_versions': request_rspec_versions,
77 'geni_ad_rspec_versions': ad_rspec_versions}
79 def list_resources(self, version=None, options=None):
80 logger.warning("iotlabdriver list_resources")
83 aggregate = IotLABAggregate(self)
84 rspec = aggregate.list_resources(version=version, options=options)
87 def describe(self, urns, version, options=None):
88 logger.warning("iotlabdriver describe")
91 aggregate = IotLABAggregate(self)
92 return aggregate.describe(urns, version=version, options=options)
94 def status(self, urns, options=None):
95 logger.warning("iotlabdriver status")
96 aggregate = IotLABAggregate(self)
97 desc = aggregate.describe(urns, version='GENI 3')
98 status = {'geni_urn': desc['geni_urn'],
99 'geni_slivers': desc['geni_slivers']}
102 def _get_users(self):
103 """ Get all users """
104 ret = self.shell.get_users()
109 def _get_user_login(self, caller_user):
110 """ Get user login with email """
111 email = caller_user['email']
112 # ensure user exist in LDAP tree
113 users = self._get_users()
114 if users and email not in users:
115 self.shell.add_user(caller_user)
116 users = self._get_users()
117 if users and email in users:
118 return users[email]['login']
123 def _get_experiment(cls, rspec):
125 Find in RSpec leases the experiment start time, duration and nodes
131 <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab"
132 start_time="1427792400" duration="30">
134 "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info"/>
136 <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab"
137 start_time="1427792600" duration="50">
139 "urn:publicid:IDN+iotlab+node+m3-15.grenoble.iot-lab.info"/>
144 leases = rspec.version.get_leases()
145 start_time = min([int(lease['start_time'])
146 for lease in leases])
150 duration = max([int(lease['duration'])
151 for lease in leases])
154 end_time = max([int(lease['start_time']) +
155 int(lease['duration']) * 60
156 for lease in leases])
157 from math import floor
159 duration = floor((end_time - start_time) / 60)
160 nodes_list = [Xrn.unescape(Xrn(lease['component_id'].strip(),
161 type='node').get_leaf())
164 nodes_list = list(set(nodes_list))
165 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()
176 def allocate(self, urn, rspec_string, expiration, options=None):
178 Allocate method submit an experiment on Iot-LAB testbed with :
179 * user : get the slice user which launch request (caller_hrn)
180 * reservation : get the start time and duration in RSpec leases
181 * nodes : get the nodes list in RSpec leases
182 If we have a request success on Iot-LAB testbed we store in SFA
183 database the assocation OAR scheduler job id and slice hrn
185 :param urn : slice urn
186 :param rspec_string : RSpec received
187 :param options : options with slice users (geni_users)
189 # pylint:disable=R0914
191 logger.warning("iotlabdriver allocate")
193 aggregate = IotLABAggregate(self)
195 rspec = RSpec(rspec_string)
197 caller_hrn = options.get('actual_caller_hrn', [])
198 geni_users = options.get('geni_users', [])
199 caller_user = [user for user in geni_users if
200 urn_to_hrn(user['urn'])[0] == caller_hrn][0]
201 logger.warning("iotlabdriver allocate caller : %s" %
202 caller_user['email'])
204 login = self._get_user_login(caller_user)
205 # only if we have a user
207 nodes_list, start_time, duration = \
208 self._get_experiment(rspec)
209 logger.warning("iotlabdriver allocate submit OAR job :"
211 (xrn.hrn, start_time, duration, nodes_list))
212 # [0-9A-Za-z_] with onelab.inria.test_iotlab
213 exp_name = '_'.join((xrn.hrn).split('.'))
215 ret = self.shell.reserve_nodes(login,
221 # in case of job submission success save slice and lease job
222 # id association in database
224 self._save_db_lease(int(ret['id']),
227 return aggregate.describe([xrn.get_urn()], version=rspec.version)