Added PlanetlabTAP & PlanetlabTUN
[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     def valid_connection(self, guid):
94         """Check if the connection with the guid in parameter is possible. Only meaningful connections are allowed.
95
96         :param guid: Guid of RM it will be connected
97         :type guid: int
98         :rtype:  Boolean
99
100         """
101         rm = self.ec.get_resource(guid)
102         if rm.rtype() not in self._authorized_connections:
103             msg = "Connection between %s %s and %s %s refused : An Application can be connected only to a Node" %\
104                 (self.rtype(), self._guid, rm.rtype(), guid)
105             self.debug(msg)
106             return False
107         elif len(self.connections) != 0 :
108             msg = "Connection between %s %s and %s %s refused : This Application is already connected" % \
109                 (self.rtype(), self._guid, rm.rtype(), guid)
110             self.debug(msg)
111             return False
112         else :
113             msg = "Connection between %s %s and %s %s accepted" % (self.rtype(), self._guid, rm.rtype(), guid)
114             self.debug(msg)
115             return True
116
117     def deploy(self):
118         """Deploy the RM. It means nothing special for an application for now (later it will be upload sources, ...)
119            It becomes DEPLOYED after getting the xmpp client.
120         """
121         if not self._omf_api :
122             self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), 
123                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'))
124         
125         super(OMFApplication, self).deploy()
126
127     def start(self):
128         """Start the RM. It means : Send Xmpp Message Using OMF protocol to execute the application
129            It becomes STARTED before the messages are sent (for coordination)
130
131         """
132         super(OMFApplication, self).start()
133         if self.get('appid') and self.get('path') and self.get('args') and self.get('env') :
134             msg = " " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + \
135                 self.get('appid') + " : " + self.get('path') + " : " + \
136                 self.get('args') + " : " + self.get('env')
137             self.info(msg)
138             rm_list = self.get_connected(OMFNode)
139             try:
140                 for rm_node in rm_list:
141                     if rm_node.get('hostname') :
142                         self._omf_api.execute(rm_node.get('hostname'),self.get('appid'), \
143                             self.get('args'), self.get('path'), self.get('env'))
144             except AttributeError:
145                 self._state = ResourceState.FAILED
146                 msg = "Credentials are not initialzed. XMPP Connections impossible"
147                 self.error(msg)
148                 raise
149         else :
150             self._state = ResourceState.FAILED
151             msg = "Application's information are not initialized"
152             self.error(msg)
153
154     def stop(self):
155         """Stop the RM. It means : Send Xmpp Message Using OMF protocol to kill the application
156            It becomes STOPPED after the message is sent.
157
158         """
159         try:
160             rm_list = self.get_connected("OMFNode")
161             for rm_node in rm_list :
162                 self._omf_api.exit(rm_node.get('hostname'),self.get('appid'))
163         except AttributeError:
164             self._state = ResourceState.FAILED
165             msg = "Credentials were not initialzed. XMPP Connections impossible"
166             self.error(msg)
167             raise
168         super(OMFApplication, self).stop()
169         self._state = ResourceState.FINISHED
170         
171
172     def release(self):
173         """Clean the RM at the end of the experiment and release the API.
174
175         """
176         if self._omf_api :
177             OMFAPIFactory.release_api(self.get('xmppSlice'), 
178                 self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword'))
179