fd083a703c076cabb9b117ef11ee83e1e1d63647
[nepi.git] / src / nepi / resources / omf / channel.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.omf_resource import ResourceGateway, OMFResource
26 from nepi.resources.omf.omf_api_factory import OMFAPIFactory
27
28
29 @clsinit_copy
30 class OMFChannel(OMFResource):
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     """
42     _rtype = "OMFChannel"
43     _authorized_connections = ["OMFWifiInterface", "OMFNode"]
44
45     ChannelToFreq = dict({
46              "1" : "2412",
47              "2" : "2417",
48              "3" : "2422",
49              "4" : "2427",
50              "5" : "2432",
51              "6" : "2437",
52              "7" : "2442",
53              "8" : "2447",
54              "9" : "2452",
55              "10" : "2457",
56              "11" : "2462",
57              "12" : "2467",
58              "13" : "2472",
59     })
60
61     @classmethod
62     def _register_attributes(cls):
63         """Register the attributes of an OMF channel
64         
65         """
66         channel = Attribute("channel", "Name of the application")
67         cls._register_attribute(channel)
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
76         """
77         super(OMFChannel, self).__init__(ec, guid)
78
79         self._nodes_guid = list()
80         self.frequency = None
81
82         self._omf_api = None
83
84     @property
85     def exp_id(self):
86         return self.ec.exp_id
87
88     def valid_connection(self, guid):
89         """ Check if the connection with the guid in parameter is possible.
90         Only meaningful connections are allowed.
91
92         :param guid: Guid of the current RM
93         :type guid: int
94         :rtype:  Boolean
95
96         """
97         rm = self.ec.get_resource(guid)
98         if rm.get_rtype() in self._authorized_connections:
99             msg = "Connection between %s %s and %s %s accepted" % (
100                     self.get_rtype(), self._guid, rm.get_rtype(), guid)
101             self.debug(msg)
102             return True
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         return False
107
108     def _get_target(self, conn_set):
109         """
110         Get the couples (host, interface) that uses this channel
111
112         :param conn_set: Connections of the current Guid
113         :type conn_set: set
114         :rtype: list
115         :return: self._nodes_guid
116
117         """
118         res = []
119         for elt in conn_set:
120             rm_iface = self.ec.get_resource(elt)
121             for conn in rm_iface.connections:
122                 rm_node = self.ec.get_resource(conn)
123                 if rm_node.get_rtype() == "OMFNode" and rm_node.get('hostname'):
124                     if rm_iface.state < ResourceState.PROVISIONED or \
125                             rm_node.state < ResourceState.READY:
126                         return "reschedule"
127                     couple = [rm_node.get('hostname'), rm_iface.get('alias')]
128                     #print couple
129                     res.append(couple)
130         return res
131
132     def get_frequency(self, channel):
133         return OMFChannel.ChannelToFreq[channel]
134
135     def do_deploy(self):
136         """ Deploy the RM. It means : Get the xmpp client and send messages 
137         using OMF 5.4 protocol to configure the channel.
138         It becomes DEPLOYED after sending messages to configure the channel
139
140         """   
141         if self.get('version') == "6":
142             self.frequency = self.get_frequency(self.get('channel'))
143             super(OMFChannel, self).do_deploy()
144             return
145
146
147         if not self.get('xmppServer'):
148             msg = "XmppServer is not initialzed. XMPP Connections impossible"
149             self.error(msg)
150             raise RuntimeError, msg
151
152         if not (self.get('xmppUser') or self.get('xmppPort') 
153                    or self.get('xmppPassword')):
154             msg = "Credentials are not all initialzed. Default values will be used"
155             self.warn(msg)
156
157         if not self._omf_api :
158             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
159                 self.get('xmppHost'), self.get('xmppPort'), 
160                 self.get('xmppPassword'), exp_id = self.exp_id)
161
162         if not self.get('channel'):
163             msg = "Channel's value is not initialized"
164             self.error(msg)
165             raise RuntimeError, msg
166
167         self._nodes_guid = self._get_target(self._connections)
168
169
170
171         if self._nodes_guid == "reschedule" :
172             self.ec.schedule("2s", self.deploy)
173         else:
174             for couple in self._nodes_guid:
175                 attrval = self.get('channel')
176                 attrname = "net/%s/%s" % (couple[1], 'channel')
177                 self._omf_api.configure(couple[0], attrname, attrval)
178
179         super(OMFChannel, self).do_deploy()
180
181     def do_release(self):
182         """ Clean the RM at the end of the experiment and release the API
183
184         """
185         if self._omf_api :
186             OMFAPIFactory.release_api(self.get('version'), 
187               self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'),
188                self.get('xmppPassword'), exp_id = self.exp_id)
189
190         super(OMFChannel, self).do_release()
191