d064c66814c1e422465d17162e8554c716c48a20
[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, 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_api import OMFAPIFactory
27
28
29 @clsinit
30 class OMFWifiInterface(ResourceManager):
31     """
32     .. class:: Class Args :
33       
34         :param ec: The Experiment controller
35         :type ec: ExperimentController
36         :param guid: guid of the RM
37         :type guid: int
38         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
39         :type creds: dict
40
41     .. note::
42
43        This class is used only by the Experiment Controller through the Resource Factory
44
45     """
46     _rtype = "OMFWifiInterface"
47     _authorized_connections = ["OMFNode" , "OMFChannel"]
48
49     #alias2name = dict({'w0':'wlan0', 'w1':'wlan1'})
50
51     @classmethod
52     def _register_attributes(cls):
53         """Register the attributes of an OMF interface 
54
55         """
56         alias = Attribute("alias","Alias of the interface", default = "w0")
57         mode = Attribute("mode","Mode of the interface")
58         type = Attribute("type","Type of the interface")
59         essid = Attribute("essid","Essid of the interface")
60         ip = Attribute("ip","IP of the interface")
61         xmppSlice = Attribute("xmppSlice","Name of the slice", flags = Flags.Credential)
62         xmppHost = Attribute("xmppHost", "Xmpp Server",flags = Flags.Credential)
63         xmppPort = Attribute("xmppPort", "Xmpp Port",flags = Flags.Credential)
64         xmppPassword = Attribute("xmppPassword", "Xmpp Port",flags = Flags.Credential)
65         cls._register_attribute(alias)
66         cls._register_attribute(xmppSlice)
67         cls._register_attribute(xmppHost)
68         cls._register_attribute(xmppPort)
69         cls._register_attribute(xmppPassword)
70         cls._register_attribute(mode)
71         cls._register_attribute(type)
72         cls._register_attribute(essid)
73         cls._register_attribute(ip)
74
75     def __init__(self, ec, guid):
76         """
77         :param ec: The Experiment controller
78         :type ec: ExperimentController
79         :param guid: guid of the RM
80         :type guid: int
81         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
82         :type creds: dict
83
84         """
85         super(OMFWifiInterface, self).__init__(ec, guid)
86
87         self._omf_api = None
88         self._alias = self.get('alias')
89
90     @property
91     def exp_id(self):
92         if self.ec.exp_id.startswith('exp-'):
93             return None
94         return self.ec.exp_id
95
96     def valid_connection(self, guid):
97         """ Check if the connection with the guid in parameter is possible. Only meaningful connections are allowed.
98
99         :param guid: Guid of the current RM
100         :type guid: int
101         :rtype:  Boolean
102
103         """
104         rm = self.ec.get_resource(guid)
105         if rm.rtype() in self._authorized_connections:
106             msg = "Connection between %s %s and %s %s accepted" % \
107                 (self.rtype(), self._guid, rm.rtype(), guid)
108             self.debug(msg)
109             return True
110         msg = "Connection between %s %s and %s %s refused" % \
111              (self.rtype(), self._guid, rm.rtype(), guid)
112         self.debug(msg)
113         return False
114
115     @property
116     def node(self):
117         rm_list = self.get_connected(OMFNode.rtype())
118         if rm_list: return rm_list[0]
119         return None
120
121     def deploy(self):
122         """Deploy the RM. It means : Get the xmpp client and send messages using OMF 5.4 protocol to configure the interface
123            It becomes DEPLOYED after sending messages to configure the interface
124         """
125         if not self._omf_api :
126             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
127                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'), exp_id = self.exp_id)
128
129         if not self._omf_api :
130             self._state = ResourceState.FAILED
131             msg = "Credentials are not initialzed. XMPP Connections impossible"
132             self.error(msg)
133             return
134
135         if not (self.get('mode') and self.get('type') and self.get('essid') and self.get('ip')):
136             self._state = ResourceState.FAILED
137             msg = "Interface's variable are not initialized"
138             self.error(msg)
139             return False
140
141         if not self.node.get('hostname') :
142             msg = "The channel is connected with an undefined node"
143             self.error(msg)
144             return False
145
146         # Just for information
147         self.debug(" " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + \
148             self.get('mode') + " : " + self.get('type') + " : " + \
149             self.get('essid') + " : " + self.get('ip'))
150     
151         # Check if the node is already deployed
152         if self.node.state < ResourceState.READY:
153             self.ec.schedule(reschedule_delay, self.deploy)
154             return
155
156         try :
157             for attrname in ["mode", "type", "essid", "ip"]:
158                 attrval = self.get(attrname)
159                 attrname = "net/%s/%s" % (self._alias, attrname)
160                 self._omf_api.configure(self.node.get('hostname'), attrname, attrval)
161         except AttributeError:
162             self._state = ResourceState.FAILED
163             msg = "Credentials are not initialzed. XMPP Connections impossible"
164             self.debug(msg)
165             #raise
166
167         super(OMFWifiInterface, self).deploy()
168
169     def start(self):
170         """Start the RM. It means nothing special for an interface for now
171            It becomes STARTED as soon as this method starts.
172
173         """
174
175         super(OMFWifiInterface, self).start()
176
177     def stop(self):
178         """Stop the RM. It means nothing special for an interface for now
179            It becomes STOPPED as soon as this method stops
180
181         """
182         super(OMFWifiInterface, self).stop()
183
184     def release(self):
185         """Clean the RM at the end of the experiment and release the API
186
187         """
188         if self._omf_api :
189             OMFAPIFactory.release_api(self.get('xmppSlice'), 
190                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'), exp_id = self.exp_id)
191
192         super(OMFWifiInterface, self).release()
193