0aea5bb148c06eeb5835a9153409183274523919
[nepi.git] / src / nepi / resources / omf / interface.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
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.
9 #
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.
14 #
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/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 #         Julien Tribino <julien.tribino@inria.fr>
20
21 from nepi.execution.resource import ResourceManager, clsinit_copy, ResourceState, \
22         reschedule_delay
23 from nepi.execution.attribute import Attribute, Flags 
24
25 from nepi.resources.omf.node import OMFNode
26 from nepi.resources.omf.omf_resource import ResourceGateway, OMFResource
27 from nepi.resources.omf.channel import OMFChannel
28 from nepi.resources.omf.omf_api import OMFAPIFactory
29
30 @clsinit_copy
31 class OMFWifiInterface(OMFResource):
32     """
33     .. class:: Class Args :
34       
35         :param ec: The Experiment controller
36         :type ec: ExperimentController
37         :param guid: guid of the RM
38         :type guid: int
39         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
40         :type creds: dict
41
42     .. note::
43
44        This class is used only by the Experiment Controller through the Resource 
45        Factory
46
47     """
48     _rtype = "OMFWifiInterface"
49     _authorized_connections = ["OMFNode" , "OMFChannel"]
50
51     #alias2name = dict({'w0':'wlan0', 'w1':'wlan1'})
52
53     @classmethod
54     def _register_attributes(cls):
55         """Register the attributes of an OMF interface 
56
57         """
58         alias = Attribute("alias","Alias of the interface", default = "w0")
59         mode = Attribute("mode","Mode of the interface")
60         type = Attribute("type","Type of the interface")
61         essid = Attribute("essid","Essid of the interface")
62         ip = Attribute("ip","IP of the interface")
63         cls._register_attribute(alias)
64         cls._register_attribute(mode)
65         cls._register_attribute(type)
66         cls._register_attribute(essid)
67         cls._register_attribute(ip)
68
69     def __init__(self, ec, guid):
70         """
71         :param ec: The Experiment controller
72         :type ec: ExperimentController
73         :param guid: guid of the RM
74         :type guid: int
75         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
76         :type creds: dict
77
78         """
79         super(OMFWifiInterface, self).__init__(ec, guid)
80
81         self._omf_api = None
82         self._alias = self.get('alias')
83
84     def valid_connection(self, guid):
85         """ Check if the connection with the guid in parameter is possible. 
86         Only meaningful connections are allowed.
87
88         :param guid: Guid of the current RM
89         :type guid: int
90         :rtype:  Boolean
91
92         """
93         rm = self.ec.get_resource(guid)
94         if rm.rtype() in self._authorized_connections:
95             msg = "Connection between %s %s and %s %s accepted" % \
96                 (self.rtype(), self._guid, rm.rtype(), guid)
97             self.debug(msg)
98
99             return True
100
101         msg = "Connection between %s %s and %s %s refused" % \
102              (self.rtype(), self._guid, rm.rtype(), guid)
103         self.debug(msg)
104
105         return False
106
107     @property
108     def exp_id(self):
109         if self.ec.exp_id.startswith('exp-'):
110             return None
111         return self.ec.exp_id
112
113     @property
114     def node(self):
115         rm_list = self.get_connected(OMFNode.rtype())
116         if rm_list: return rm_list[0]
117         return None
118
119     @property
120     def channel(self):
121         rm_list = self.get_connected(OMFChannel.rtype())
122         if rm_list: return rm_list[0]
123         return None
124
125
126     def configure_iface(self):
127         """ Configure the interface without the ip
128
129         """
130         if self.node.state < ResourceState.READY:
131             self.ec.schedule(reschedule_delay, self.deploy)
132             return False
133
134         try :
135             for attrname in ["mode", "type", "essid"]:
136                 attrval = self.get(attrname)
137                 attrname = "net/%s/%s" % (self._alias, attrname)
138                 self._omf_api.configure(self.node.get('hostname'), attrname, 
139                         attrval)
140         except AttributeError:
141             self._state = ResourceState.FAILED
142             msg = "Credentials are not initialzed. XMPP Connections impossible"
143             self.debug(msg)
144             #raise
145         
146         super(OMFWifiInterface, self).provision()
147         return True
148
149     def configure_ip(self):
150         """ Configure the ip of the interface
151
152         """
153         if self.channel.state < ResourceState.READY:
154             self.ec.schedule(reschedule_delay, self.deploy)
155             return False
156
157         try :
158             attrval = self.get("ip")
159             attrname = "net/%s/%s" % (self._alias, "ip")
160             self._omf_api.configure(self.node.get('hostname'), attrname, 
161                     attrval)
162         except AttributeError:
163             msg = "Credentials are not initialzed. XMPP Connections impossible"
164             self.debug(msg)
165             self.fail()
166             #raise
167
168         return True
169
170     def deploy(self):
171         """ Deploy the RM. It means : Get the xmpp client and send messages 
172         using OMF 5.4 protocol to configure the interface.
173         It becomes DEPLOYED after sending messages to configure the interface
174         """
175         if not self._omf_api :
176             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
177                 self.get('xmppHost'), self.get('xmppPort'), 
178                 self.get('xmppPassword'), exp_id = self.exp_id)
179
180         if not self._omf_api :
181             msg = "Credentials are not initialzed. XMPP Connections impossible"
182             self.error(msg)
183             self.fail()
184             return
185
186         if not (self.get('mode') and self.get('type') and self.get('essid') \
187                 and self.get('ip')):
188             msg = "Interface's variable are not initialized"
189             self.error(msg)
190             self.fail()
191             return False
192
193         if not self.node.get('hostname') :
194             msg = "The channel is connected with an undefined node"
195             self.error(msg)
196             self.fail()
197             return False
198
199         # Just for information
200         self.debug(" " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + \
201             self.get('mode') + " : " + self.get('type') + " : " + \
202             self.get('essid') + " : " + self.get('ip'))
203     
204         # Check if the node is already deployed
205         chk1 = True
206         if self.state < ResourceState.PROVISIONED:
207             chk1 = self.configure_iface()
208         if chk1:
209             chk2 = self.configure_ip()
210
211         if not (chk1 and chk2) :
212             return False
213             
214         super(OMFWifiInterface, self).deploy()
215         return True
216
217     def release(self):
218         """ Clean the RM at the end of the experiment and release the API
219
220         """
221         if self._omf_api :
222             OMFAPIFactory.release_api(self.get('xmppSlice'), 
223                 self.get('xmppHost'), self.get('xmppPort'), 
224                 self.get('xmppPassword'), exp_id = self.exp_id)
225
226         super(OMFWifiInterface, self).release()
227