Modify the OMT test and add the exp_id in the xmpp Api
[nepi.git] / src / nepi / resources / omf / application.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 from nepi.resources.omf.node import OMFNode
25 from nepi.resources.omf.omf_api import OMFAPIFactory
26
27
28 @clsinit
29 class OMFApplication(ResourceManager):
30     """
31     .. class:: Class Args :
32       
33         :param ec: The Experiment controller
34         :type ec: ExperimentController
35         :param guid: guid of the RM
36         :type guid: int
37         :param creds: Credentials to communicate with the rm (XmppClient)
38         :type creds: dict
39
40     .. note::
41
42        This class is used only by the Experiment Controller through the Resource Factory
43
44     """
45     _rtype = "OMFApplication"
46     _authorized_connections = ["OMFNode"]
47
48     @classmethod
49     def _register_attributes(cls):
50         """Register the attributes of an OMF application
51         """
52
53         appid = Attribute("appid", "Name of the application")
54         path = Attribute("path", "Path of the application")
55         args = Attribute("args", "Argument of the application")
56         env = Attribute("env", "Environnement variable of the application")
57         xmppSlice = Attribute("xmppSlice","Name of the slice", flags = Flags.Credential)
58         xmppHost = Attribute("xmppHost", "Xmpp Server",flags = Flags.Credential)
59         xmppPort = Attribute("xmppPort", "Xmpp Port",flags = Flags.Credential)
60         xmppPassword = Attribute("xmppPassword", "Xmpp Port",flags = Flags.Credential)
61         cls._register_attribute(appid)
62         cls._register_attribute(path)
63         cls._register_attribute(args)
64         cls._register_attribute(env)
65         cls._register_attribute(xmppSlice)
66         cls._register_attribute(xmppHost)
67         cls._register_attribute(xmppPort)
68         cls._register_attribute(xmppPassword)
69
70
71     def __init__(self, ec, guid):
72         """
73         :param ec: The Experiment controller
74         :type ec: ExperimentController
75         :param guid: guid of the RM
76         :type guid: int
77         :param creds: Credentials to communicate with the rm (XmppClient for OMF)
78         :type creds: dict
79
80         """
81         
82         super(OMFApplication, self).__init__(ec, guid)
83
84         self.set('appid', "")
85         self.set('path', "")
86         self.set('args', "")
87         self.set('env', "")
88
89         self._node = None
90
91         self._omf_api = None
92
93     @property
94     def exp_id(self):
95         if self.ec.exp_id.startswith('exp-'):
96             return None
97         return self.ec.exp_id
98
99     @property
100     def node(self):
101         rm_list = self.get_connected(OMFNode.rtype())
102         if rm_list: return rm_list[0]
103         return None
104
105     def valid_connection(self, guid):
106         """Check if the connection with the guid in parameter is possible. Only meaningful connections are allowed.
107
108         :param guid: Guid of RM it will be connected
109         :type guid: int
110         :rtype:  Boolean
111
112         """
113         rm = self.ec.get_resource(guid)
114         if rm.rtype() not in self._authorized_connections:
115             msg = "Connection between %s %s and %s %s refused : An Application can be connected only to a Node" %\
116                 (self.rtype(), self._guid, rm.rtype(), guid)
117             self.debug(msg)
118             return False
119         elif len(self.connections) != 0 :
120             msg = "Connection between %s %s and %s %s refused : This Application is already connected" % \
121                 (self.rtype(), self._guid, rm.rtype(), guid)
122             self.debug(msg)
123             return False
124         else :
125             msg = "Connection between %s %s and %s %s accepted" % (self.rtype(), self._guid, rm.rtype(), guid)
126             self.debug(msg)
127             return True
128
129
130
131     def deploy(self):
132         """Deploy the RM. It means nothing special for an application for now (later it will be upload sources, ...)
133            It becomes DEPLOYED after getting the xmpp client.
134         """
135         if not self._omf_api :
136             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
137                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'), exp_id = self.exp_id)
138
139         if not self._omf_api :
140             self._state = ResourceState.FAILED
141             msg = "Credentials are not initialzed. XMPP Connections impossible"
142             self.error(msg)
143             return
144
145         super(OMFApplication, self).deploy()
146
147     def start(self):
148         """Start the RM. It means : Send Xmpp Message Using OMF protocol to execute the application
149            It becomes STARTED before the messages are sent (for coordination)
150
151         """
152         if not (self.get('appid') and self.get('path')) :
153             self._state = ResourceState.FAILED
154             msg = "Application's information are not initialized"
155             self.error(msg)
156             return
157
158         if not self.get('args'):
159             self.set('args', " ")
160         if not self.get('env'):
161             self.set('env', " ")
162
163         # Some information to check the information in parameter
164         msg = " " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + \
165             self.get('appid') + " : " + self.get('path') + " : " + \
166             self.get('args') + " : " + self.get('env')
167         self.info(msg)
168
169         try:
170             self._omf_api.execute(self.node.get('hostname'),self.get('appid'), \
171                 self.get('args'), self.get('path'), self.get('env'))
172         except AttributeError:
173             self._state = ResourceState.FAILED
174             msg = "Credentials are not initialzed. XMPP Connections impossible"
175             self.error(msg)
176             raise
177
178
179         super(OMFApplication, self).start()
180
181
182     def stop(self):
183         """Stop the RM. It means : Send Xmpp Message Using OMF protocol to kill the application
184            It becomes STOPPED after the message is sent.
185
186         """
187         try:
188             self._omf_api.exit(self.node.get('hostname'),self.get('appid'))
189         except AttributeError:
190             self._state = ResourceState.FAILED
191             msg = "Credentials were not initialzed. XMPP Connections impossible"
192             self.error(msg)
193             #raise
194
195         super(OMFApplication, self).stop()
196         self._state = ResourceState.FINISHED
197         
198
199     def release(self):
200         """Clean the RM at the end of the experiment and release the API.
201
202         """
203         if self._omf_api :
204             OMFAPIFactory.release_api(self.get('xmppSlice'), 
205                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'), exp_id = self.exp_id)
206
207         super(OMFApplication, self).release()
208