2 # NEPI, a framework to manage network experiments
3 # Copyright (C) 2013 INRIA
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 # Julien Tribino <julien.tribino@inria.fr>
22 from nepi.execution.resource import ResourceManager, clsinit_copy, \
23 ResourceState, reschedule_delay
24 from nepi.execution.attribute import Attribute, Flags
26 from nepi.resources.omf.node import OMFNode, confirmation_counter, reschedule_check
27 from nepi.resources.omf.omf_resource import ResourceGateway, OMFResource
28 from nepi.resources.omf.channel import OMFChannel
29 from nepi.resources.omf.omf_api_factory import OMFAPIFactory
32 class OMFWifiInterface(OMFResource):
34 .. class:: Class Args :
36 :param ec: The Experiment controller
37 :type ec: ExperimentController
38 :param guid: guid of the RM
42 _rtype = "OMFWifiInterface"
43 _authorized_connections = ["OMFNode" , "OMFChannel", "WilabtSfaNode"]
46 def _register_attributes(cls):
47 """Register the attributes of an OMF interface
50 name = Attribute("name","Alias of the interface : wlan0, wlan1, ..", default = "wlan0")
51 mode = Attribute("mode","Mode of the interface")
52 hw_mode = Attribute("hw_mode","Choose between : a, b, g, n")
53 essid = Attribute("essid","Essid of the interface")
54 ip = Attribute("ip","IP of the interface")
55 cls._register_attribute(name)
56 cls._register_attribute(mode)
57 cls._register_attribute(hw_mode)
58 cls._register_attribute(essid)
59 cls._register_attribute(ip)
61 def __init__(self, ec, guid):
63 :param ec: The Experiment controller
64 :type ec: ExperimentController
65 :param guid: guid of the RM
67 :param creds: Credentials to communicate with the rm (XmppClient for OMF)
71 super(OMFWifiInterface, self).__init__(ec, guid)
79 self.release_id = None
81 self._topic_iface = None
86 def valid_connection(self, guid):
87 """ Check if the connection with the guid in parameter is possible.
88 Only meaningful connections are allowed.
90 :param guid: Guid of the current RM
95 rm = self.ec.get_resource(guid)
96 if rm.get_rtype() in self._authorized_connections:
97 msg = "Connection between %s %s and %s %s accepted" % \
98 (self.get_rtype(), self._guid, rm.get_rtype(), guid)
102 msg = "Connection between %s %s and %s %s refused" % \
103 (self.get_rtype(), self._guid, rm.get_rtype(), guid)
109 return self.ec.exp_id
113 rm_list = self.get_connected(OMFNode.get_rtype())
114 if rm_list: return rm_list[0]
119 rm_list = self.get_connected(OMFChannel.get_rtype())
120 if rm_list: return rm_list[0]
123 def configure_iface(self):
124 """ Configure the interface without the ip
127 if self.node.state < ResourceState.READY:
128 self.ec.schedule(reschedule_delay, self.deploy)
131 for attrname in ["mode", "type", "essid"]:
132 if attrname == "type" :
135 attrval = self.get(attrname)
136 attrname = "net/%s/%s" % (self.alias, attrname)
137 self._omf_api.configure(self.node.get('hostname'), attrname,
140 super(OMFWifiInterface, self).do_provision()
143 def configure_ip(self):
144 """ Configure the ip of the interface
146 .. note : The ip is separated from the others parameters to avoid
147 CELL ID shraing problem. By putting th ip at the end of the configuration,
148 each node use the same channel and can then share the same CELL ID.
149 In the second case, the channel is defined at the end and the node don't
150 share a common CELL ID and can not communicate.
153 if self.channel.state < ResourceState.READY:
154 self.ec.schedule(reschedule_delay, self.deploy)
157 attrval = self.get("ip")
159 attrval,mask = attrval.split('/')
160 attrname = "net/%s/%s" % (self.alias, "ip")
161 self._omf_api.configure(self.node.get('hostname'), attrname,
166 def configure_on_omf5(self):
167 """ Method to configure the wifi interface when OMF 5.4 is used.
171 self._type = self.get('hw_mode')
172 if self.get('name') == "wlan0" or "eth0":
177 if self.state < ResourceState.PROVISIONED:
178 if self._conf == False:
179 self._conf = self.configure_iface()
180 if self._conf == True:
181 res = self.configure_ip()
184 def check_deploy(self, cid):
185 """ Check, through the mail box in the parser,
186 if the confirmation of the creation has been received
188 :param cid: the id of the original message
192 uid = self._omf_api.check_mailbox("create", cid)
198 """ Deploy the RM. It means : Get the xmpp client and send messages
199 using OMF 5.4 or 6 protocol to configure the interface.
202 if not self.node or self.node.state < ResourceState.READY:
203 self.debug("---- RESCHEDULING DEPLOY ---- node state %s "
205 self.ec.schedule(reschedule_delay, self.deploy)
208 if not self.channel or self.channel.state < ResourceState.READY:
209 self.debug("---- RESCHEDULING DEPLOY ---- channel state %s "
210 % self.channel.state )
211 self.ec.schedule(reschedule_delay, self.deploy)
214 self.set('xmppUser',self.node.get('xmppUser'))
215 self.set('xmppServer',self.node.get('xmppServer'))
216 self.set('xmppPort',self.node.get('xmppPort'))
217 self.set('xmppPassword',self.node.get('xmppPassword'))
218 self.set('version',self.node.get('version'))
220 if not self.get('xmppServer'):
221 msg = "XmppServer is not initialzed. XMPP Connections impossible"
223 raise RuntimeError, msg
225 if not (self.get('xmppUser') or self.get('xmppPort')
226 or self.get('xmppPassword')):
227 msg = "Credentials are not all initialzed. Default values will be used"
230 if not self._omf_api :
231 self._omf_api = OMFAPIFactory.get_api(self.get('version'),
232 self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'),
233 self.get('xmppPassword'), exp_id = self.exp_id)
235 if not (self.get('name')):
236 msg = "Interface's name is not initialized"
238 raise RuntimeError, msg
240 if not (self.get('mode') and self.get('essid') \
241 and self.get('hw_mode') and self.get('ip')):
242 msg = "Interface's variable are not initialized"
244 raise RuntimeError, msg
246 if self.get('version') == "5":
247 res = self.configure_on_omf5()
250 res = self.configure_on_omf6()
253 super(OMFWifiInterface, self).do_deploy()
255 def configure_on_omf6(self):
256 """ Method to configure the wifi interface when OMF 6 is used.
259 if not self.create_id :
261 props['wlan:if_name'] = self.get('name')
262 props['wlan:mode'] = {
263 "mode": self.get('mode'),
264 "hw_mode" : self.get('hw_mode'),
265 "channel" : self.channel.get('channel'),
266 "essid" : self.get('essid'),
267 "ip_addr" : self.get('ip'),
268 "frequency" : self.channel.frequency,
271 props['wlan:hrn'] = self.get('name')
272 props['wlan:type'] = "wlan"
274 self.create_id = os.urandom(16).encode('hex')
275 self._omf_api.frcp_create( self.create_id, self.node.get('hostname'), "wlan", props = props)
277 if self._create_cnt > confirmation_counter:
278 msg = "Couldn't retrieve the confirmation of the creation"
280 raise RuntimeError, msg
282 uid = self.check_deploy(self.create_id)
285 self.ec.schedule(reschedule_check, self.deploy)
288 self._topic_iface = uid
289 self._omf_api.enroll_topic(self._topic_iface)
292 def check_release(self, cid):
293 """ Check, through the mail box in the parser,
294 if the confirmation of the release has been received
296 :param cid: the id of the original message
300 res = self._omf_api.check_mailbox("release", cid)
305 def do_release(self):
306 """ Clean the RM at the end of the experiment and release the API
310 if self.get('version') == "6":
311 if not self.release_id:
312 self.release_id = os.urandom(16).encode('hex')
313 self._omf_api.frcp_release( self.release_id, self.node.get('hostname'),self._topic_iface, res_id=self._topic_iface)
315 if self._release_cnt < confirmation_counter:
316 cid = self.check_release(self.release_id)
318 self._release_cnt +=1
319 self.ec.schedule(reschedule_check, self.release)
322 msg = "Couldn't retrieve the confirmation of the release"
326 OMFAPIFactory.release_api(self.get('version'),
327 self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'),
328 self.get('xmppPassword'), exp_id = self.exp_id)
330 super(OMFWifiInterface, self).do_release()