Replacing RM.rtype() for RM.get_type() for consistency
[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, \
22         ResourceState, 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._conf = False
82
83         self._omf_api = None
84         self._alias = self.get('alias')
85
86     def valid_connection(self, guid):
87         """ Check if the connection with the guid in parameter is possible. 
88         Only meaningful connections are allowed.
89
90         :param guid: Guid of the current RM
91         :type guid: int
92         :rtype:  Boolean
93
94         """
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)
99             self.debug(msg)
100
101             return True
102
103         msg = "Connection between %s %s and %s %s refused" % \
104              (self.get_rtype(), self._guid, rm.get_rtype(), guid)
105         self.debug(msg)
106
107         return False
108
109     @property
110     def exp_id(self):
111         return self.ec.exp_id
112
113     @property
114     def node(self):
115         rm_list = self.get_connected(OMFNode.get_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.get_rtype())
122         if rm_list: return rm_list[0]
123         return None
124
125     def configure_iface(self):
126         """ Configure the interface without the ip
127
128         """
129         if self.node.state < ResourceState.READY:
130             self.ec.schedule(reschedule_delay, self.deploy)
131             return False
132
133         for attrname in ["mode", "type", "essid"]:
134             attrval = self.get(attrname)
135             attrname = "net/%s/%s" % (self._alias, attrname)
136             self._omf_api.configure(self.node.get('hostname'), attrname, 
137                         attrval)
138         
139         super(OMFWifiInterface, self).do_provision()
140         return True
141
142     def configure_ip(self):
143         """ Configure the ip of the interface
144
145         """
146         if self.channel.state < ResourceState.READY:
147             self.ec.schedule(reschedule_delay, self.deploy)
148             return False
149
150         attrval = self.get("ip")
151         attrname = "net/%s/%s" % (self._alias, "ip")
152         self._omf_api.configure(self.node.get('hostname'), attrname, 
153                     attrval)
154
155         return True
156
157     def do_deploy(self):
158         """ Deploy the RM. It means : Get the xmpp client and send messages 
159         using OMF 5.4 protocol to configure the interface.
160         It becomes DEPLOYED after sending messages to configure the interface
161         """
162         self.set('xmppSlice',self.node.get('xmppSlice'))
163         self.set('xmppHost',self.node.get('xmppHost'))
164         self.set('xmppPort',self.node.get('xmppPort'))
165         self.set('xmppPassword',self.node.get('xmppPassword'))
166
167         if not (self.get('xmppSlice') and self.get('xmppHost')
168               and self.get('xmppPort') and self.get('xmppPassword')):
169             msg = "Credentials are not initialzed. XMPP Connections impossible"
170             self.error(msg)
171             raise RuntimeError, msg
172
173         if not self._omf_api :
174             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
175                 self.get('xmppHost'), self.get('xmppPort'), 
176                 self.get('xmppPassword'), exp_id = self.exp_id)
177
178         if not (self.get('mode') and self.get('type') and self.get('essid') \
179                 and self.get('ip')):
180             msg = "Interface's variable are not initialized"
181             self.error(msg)
182             raise RuntimeError, msg
183
184         if not self.node.get('hostname') :
185             msg = "The channel is connected with an undefined node"
186             self.error(msg)
187             raise RuntimeError, msg
188
189         # Just for information
190         self.debug(" " + self.get_rtype() + " ( Guid : " + str(self._guid) +") : " + \
191             self.get('mode') + " : " + self.get('type') + " : " + \
192             self.get('essid') + " : " + self.get('ip'))
193     
194         # Check if the node is already deployed
195         if self.state < ResourceState.PROVISIONED:
196             if self._conf == False:
197                 self._conf = self.configure_iface()
198         if self._conf == True:
199             self.configure_ip()
200
201         super(OMFWifiInterface, self).do_deploy()
202
203     def do_release(self):
204         """ Clean the RM at the end of the experiment and release the API
205
206         """
207         if self._omf_api:
208             OMFAPIFactory.release_api(self.get('xmppSlice'), 
209                 self.get('xmppHost'), self.get('xmppPort'), 
210                 self.get('xmppPassword'), exp_id = self.exp_id)
211
212         super(OMFWifiInterface, self).do_release()
213