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
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"]
45 #alias2name = dict({'w0':'wlan0', 'w1':'wlan1'})
48 def _register_attributes(cls):
49 """Register the attributes of an OMF interface
52 alias = Attribute("alias","Alias of the interface", default = "w0")
53 type = Attribute("type","Choose between : a, b, g, n")
54 name = Attribute("name","Alias of the interface", default = "wlan0")
55 mode = Attribute("mode","Mode of the interface")
56 hw_mode = Attribute("hw_mode","Choose between : a, b, g, n")
57 essid = Attribute("essid","Essid of the interface")
58 ip = Attribute("ip","IP of the interface")
59 cls._register_attribute(alias)
60 cls._register_attribute(type)
61 cls._register_attribute(name)
62 cls._register_attribute(mode)
63 cls._register_attribute(hw_mode)
64 cls._register_attribute(essid)
65 cls._register_attribute(ip)
67 def __init__(self, ec, guid):
69 :param ec: The Experiment controller
70 :type ec: ExperimentController
71 :param guid: guid of the RM
73 :param creds: Credentials to communicate with the rm (XmppClient for OMF)
77 super(OMFWifiInterface, self).__init__(ec, guid)
81 self._alias = self.get('alias')
85 self.release_id = None
87 self._topic_iface = None
92 def valid_connection(self, guid):
93 """ Check if the connection with the guid in parameter is possible.
94 Only meaningful connections are allowed.
96 :param guid: Guid of the current RM
101 rm = self.ec.get_resource(guid)
102 if rm.get_rtype() in self._authorized_connections:
103 msg = "Connection between %s %s and %s %s accepted" % \
104 (self.get_rtype(), self._guid, rm.get_rtype(), guid)
108 msg = "Connection between %s %s and %s %s refused" % \
109 (self.get_rtype(), self._guid, rm.get_rtype(), guid)
115 return self.ec.exp_id
119 rm_list = self.get_connected(OMFNode.get_rtype())
120 if rm_list: return rm_list[0]
125 rm_list = self.get_connected(OMFChannel.get_rtype())
126 if rm_list: return rm_list[0]
129 def configure_iface(self):
130 """ Configure the interface without the ip
133 if self.node.state < ResourceState.READY:
134 self.ec.schedule(reschedule_delay, self.deploy)
137 for attrname in ["mode", "type", "essid"]:
138 attrval = self.get(attrname)
139 attrname = "net/%s/%s" % (self._alias, attrname)
140 self._omf_api.configure(self.node.get('hostname'), attrname,
143 super(OMFWifiInterface, self).do_provision()
146 def configure_ip(self):
147 """ Configure the ip of the interface
150 if self.channel.state < ResourceState.READY:
151 self.ec.schedule(reschedule_delay, self.deploy)
154 attrval = self.get("ip")
155 attrname = "net/%s/%s" % (self._alias, "ip")
156 self._omf_api.configure(self.node.get('hostname'), attrname,
161 def configure_on_omf5(self):
162 # Just for information
163 # self.debug(" " + self.get_rtype() + " ( Guid : " + str(self._guid) +") : " + \
164 # self.get('mode') + " : " + self.get('type') + " : " + \
165 # self.get('essid') + " : " + self.get('ip'))
166 if self.state < ResourceState.PROVISIONED:
167 if self._conf == False:
168 self._conf = self.configure_iface()
170 if self._conf == True:
171 res = self.configure_ip()
174 def check_deploy(self, cid):
175 uid = self._omf_api.check_mailbox("create", cid)
181 """ Deploy the RM. It means : Get the xmpp client and send messages
182 using OMF 5.4 protocol to configure the interface.
183 It becomes DEPLOYED after sending messages to configure the interface
185 if not self.node or self.node.state < ResourceState.READY:
186 self.debug("---- RESCHEDULING DEPLOY ---- node state %s "
188 self.ec.schedule(reschedule_delay, self.deploy)
191 if not self.channel or self.channel.state < ResourceState.READY:
192 self.debug("---- RESCHEDULING DEPLOY ---- channel state %s "
193 % self.channel.state )
194 self.ec.schedule(reschedule_delay, self.deploy)
197 self.set('xmppUser',self.node.get('xmppUser'))
198 self.set('xmppServer',self.node.get('xmppServer'))
199 self.set('xmppPort',self.node.get('xmppPort'))
200 self.set('xmppPassword',self.node.get('xmppPassword'))
201 self.set('version',self.node.get('version'))
203 if not self.get('xmppServer'):
204 msg = "XmppServer is not initialzed. XMPP Connections impossible"
206 raise RuntimeError, msg
208 if not (self.get('xmppUser') or self.get('xmppPort')
209 or self.get('xmppPassword')):
210 msg = "Credentials are not all initialzed. Default values will be used"
213 if not self._omf_api :
214 self._omf_api = OMFAPIFactory.get_api(self.get('version'),
215 self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'),
216 self.get('xmppPassword'), exp_id = self.exp_id)
218 if not (self.get('name') and self.get('mode') and self.get('essid') \
219 and self.get('hw_mode') and self.get('ip')):
220 msg = "Interface's variable are not initialized"
222 raise RuntimeError, msg
224 self.set('type',self.get('hw_mode'))
226 if self.get('version') == "5":
227 res = self.configure_on_omf5()
229 res = self.configure_on_omf6()
232 super(OMFWifiInterface, self).do_deploy()
234 def configure_on_omf6(self):
235 if not self.create_id :
237 props['wlan:if_name'] = self.get('name')
238 props['wlan:mode'] = {
239 "mode": self.get('mode'),
240 "hw_mode" : self.get('hw_mode'),
241 "channel" : self.channel.get('channel'),
242 "essid" : self.get('essid'),
243 "ip_addr" : self.get('ip'),
244 "frequency" : self.channel.frequency,
247 props['wlan:hrn'] = self.get('name')
248 props['wlan:type'] = "wlan"
250 self.create_id = os.urandom(16).encode('hex')
251 self._omf_api.frcp_create( self.create_id, self.node.get('hostname'), "wlan", props = props)
253 if self._create_cnt > confirmation_counter:
254 msg = "Couldn't retrieve the confirmation of the creation"
256 raise RuntimeError, msg
258 uid = self.check_deploy(self.create_id)
261 self.ec.schedule(reschedule_delay, self.deploy)
264 self._topic_iface = uid
265 self._omf_api.enroll_topic(self._topic_iface)
268 def check_release(self, cid):
269 res = self._omf_api.check_mailbox("release", cid)
274 def do_release(self):
275 """ Clean the RM at the end of the experiment and release the API
278 if self.get('version') == "6":
279 if not self.release_id:
280 self.release_id = os.urandom(16).encode('hex')
281 self._omf_api.frcp_release( self.release_id, self.node.get('hostname'),self._topic_iface, res_id=self._topic_iface)
283 if self._release_cnt < confirmation_counter:
284 cid = self.check_release(self.release_id)
286 self._release_cnt +=1
287 self.ec.schedule(reschedule_delay, self.release)
290 msg = "Couldn't retrieve the confirmation of the release"
294 OMFAPIFactory.release_api(self.get('version'),
295 self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'),
296 self.get('xmppPassword'), exp_id = self.exp_id)
298 super(OMFWifiInterface, self).do_release()