README moves to markdown
[nepi.git] / nepi / resources / omf / node.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 version 2 as
7 #    published by the Free Software Foundation;
8 #
9 #    This program is distributed in the hope that it will be useful,
10 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #    GNU General Public License for more details.
13 #
14 #    You should have received a copy of the GNU General Public License
15 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 #
17 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
18 #         Julien Tribino <julien.tribino@inria.fr>
19
20 from nepi.util.timefuncs import tnow
21 from nepi.execution.resource import ResourceManager, clsinit_copy, \
22         ResourceState
23 from nepi.execution.attribute import Attribute, Flags 
24 from nepi.resources.omf.omf_resource import ResourceGateway, OMFResource
25 from nepi.resources.omf.omf_api_factory import OMFAPIFactory
26
27 import time
28
29 reschedule_check = "1s"
30 confirmation_counter = 3600
31
32 @clsinit_copy
33 class OMFNode(OMFResource):
34     """
35     .. class:: Class Args :
36       
37         :param ec: The Experiment controller
38         :type ec: ExperimentController
39         :param guid: guid of the RM
40         :type guid: int
41         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
42         :type creds: dict
43
44     """
45     _rtype = "omf::Node"
46     _authorized_connections = ["omf::Application" , "omf::WifiInterface"]
47
48     @classmethod
49     def _register_attributes(cls):
50         """Register the attributes of an OMF Node
51
52         """
53         hostname = Attribute("hostname", "Hostname of the machine")
54
55         cls._register_attribute(hostname)
56
57     # XXX: We don't necessary need to have the credentials at the 
58     # moment we create the RM
59     def __init__(self, ec, guid):
60         """
61         :param ec: The Experiment controller
62         :type ec: ExperimentController
63         :param guid: guid of the RM
64         :type guid: int
65
66         """
67         super(OMFNode, self).__init__(ec, guid)
68
69         self._omf_api = None 
70
71         # For performance tests
72         self.perf = True
73         self.begin_deploy_time = None
74
75
76     @property
77     def exp_id(self):
78         return self.ec.exp_id
79
80     def valid_connection(self, guid):
81         """ Check if the connection with the guid in parameter is possible. 
82         Only meaningful connections are allowed.
83
84         :param guid: Guid of the current RM
85         :type guid: int
86         :rtype:  Boolean
87
88         """
89         rm = self.ec.get_resource(guid)
90         if rm.get_rtype() in self._authorized_connections:
91             msg = "Connection between %s %s and %s %s accepted" % (
92                     self.get_rtype(), self._guid, rm.get_rtype(), guid)
93             self.debug(msg)
94             return True
95
96         msg = "Connection between %s %s and %s %s refused" % (
97                 self.get_rtype(), self._guid, rm.get_rtype(), guid)
98         self.error(msg)
99
100         return False
101
102     def do_deploy(self):
103         """ Deploy the RM. It means : Send Xmpp Message Using OMF protocol 
104             to enroll the node into the experiment.
105
106         """ 
107       ## For performance test
108         if self.perf:
109             self.begin_deploy_time = tnow()
110             self.perf = False
111
112         if not self.get('xmppServer'):
113             msg = "XmppServer is not initialzed. XMPP Connections impossible"
114             self.error(msg)
115             raise RuntimeError(msg)
116
117         if not self.get('version'):
118             msg = "Version of OMF is not indicated"
119             self.error(msg)
120             raise RuntimeError(msg)
121
122         if not (self.get('xmppUser') or self.get('xmppPort') 
123                    or self.get('xmppPassword')):
124             msg = "Credentials are not all initialzed. Default values will be used"
125             self.warn(msg)
126
127         if not self._omf_api :
128             self._omf_api = OMFAPIFactory.get_api(self.get('version'), 
129               self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'),
130                self.get('xmppPassword'), exp_id = self.exp_id)
131
132         if not self.get('hostname') :
133             msg = "Hostname's value is not initialized"
134             self.error(msg)
135             raise RuntimeError(msg)
136
137         if self.get('version') == "5":
138             self._omf_api.enroll_host(self.get('hostname'))
139         else:
140             self._omf_api.enroll_topic(self.get('hostname'))
141
142         super(OMFNode, self).do_deploy()
143
144     def do_release(self):
145         """ Clean the RM at the end of the experiment by unenrolling
146         the node from the topic
147
148         """
149         from nepi.resources.omf.application import OMFApplication
150         rm_list = self.get_connected(OMFApplication.get_rtype())
151         if rm_list:
152             for rm in rm_list:
153                 if rm.state < ResourceState.RELEASED:
154                     self.ec.schedule(self.reschedule_delay, self.release)
155                     return 
156
157         from nepi.resources.omf.interface import OMFWifiInterface
158         rm_list = self.get_connected(OMFWifiInterface.get_rtype())
159         if rm_list:
160             for rm in rm_list:
161                 if rm.state < ResourceState.RELEASED:
162                     self.ec.schedule(self.reschedule_delay, self.release)
163                     return 
164
165         if self._omf_api:
166             if self.get('version') == "5":
167                 self._omf_api.release(self.get('hostname'))
168             else:
169                 self._omf_api.unenroll_topic(self.get('hostname'))
170
171             OMFAPIFactory.release_api(self.get('version'), 
172               self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'),
173                self.get('xmppPassword'), exp_id = self.exp_id)
174
175         super(OMFNode, self).do_release()
176