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