2 # NEPI, a framework to manage network experiments
3 # Copyright (C) 2013 INRIA
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.
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.
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/>.
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 # Julien Tribino <julien.tribino@inria.fr>
21 from nepi.execution.resource import ResourceManager, clsinit_copy, \
22 ResourceState, reschedule_delay
23 from nepi.execution.attribute import Attribute, Flags
24 from nepi.resources.omf.omf6_resource import OMF6Resource
25 from nepi.resources.omf.node6 import OMF6Node
26 from nepi.resources.omf.omf6_api import OMF6APIFactory
29 from nepi.util import sshfuncs
32 class OMF6Application(OMF6Resource):
34 .. class:: Class Args :
36 :param ec: The Experiment controller
37 :type ec: ExperimentController
38 :param guid: guid of the RM
42 _rtype = "OMF6Application"
43 _authorized_connections = ["OMF6Node"]
46 def _register_attributes(cls):
47 """ Register the attributes of an OMF application
50 command = Attribute("command", "Command to execute")
51 env = Attribute("env", "Environnement variable of the application")
52 # sources = Attribute("sources", "Sources of the application",
53 # flags = Flags.ExecReadOnly)
54 # sshuser = Attribute("sshUser", "user to connect with ssh",
55 # flags = Flags.ExecReadOnly)
56 # sshkey = Attribute("sshKey", "key to use for ssh",
57 # flags = Flags.ExecReadOnly)
58 cls._register_attribute(command)
59 cls._register_attribute(env)
60 # cls._register_attribute(sources)
61 # cls._register_attribute(sshuser)
62 # cls._register_attribute(sshkey)
64 def __init__(self, ec, guid):
66 :param ec: The Experiment controller
67 :type ec: ExperimentController
68 :param guid: guid of the RM
70 :param creds: Credentials to communicate with the rm (XmppClient for OMF)
74 super(OMF6Application, self).__init__(ec, guid)
76 self.set('command', "")
80 self._topic_app = None
90 rm_list = self.get_connected(OMF6Node.get_rtype())
91 if rm_list: return rm_list[0]
94 def valid_connection(self, guid):
95 """ Check if the connection with the guid in parameter is possible.
96 Only meaningful connections are allowed.
98 :param guid: Guid of RM it will be connected
103 rm = self.ec.get_resource(guid)
104 if rm.get_rtype() not in self._authorized_connections:
105 msg = ("Connection between %s %s and %s %s refused: "
106 "An Application can be connected only to a Node" ) % \
107 (self.get_rtype(), self._guid, rm.get_rtype(), guid)
112 elif len(self.connections) != 0 :
113 msg = ("Connection between %s %s and %s %s refused: "
114 "This Application is already connected" ) % \
115 (self.get_rtype(), self._guid, rm.get_rtype(), guid)
121 msg = "Connection between %s %s and %s %s accepted" % (
122 self.get_rtype(), self._guid, rm.get_rtype(), guid)
128 """ Deploy the RM. It means nothing special for an application
129 for now (later it will be upload sources, ...)
130 It becomes DEPLOYED after getting the xmpp client.
134 self.set('xmppUser',self.node.get('xmppUser'))
135 self.set('xmppHost',self.node.get('xmppHost'))
136 self.set('xmppPort',self.node.get('xmppPort'))
137 self.set('xmppPassword',self.node.get('xmppPassword'))
139 if not (self.get('xmppUser') and self.get('xmppHost')
140 and self.get('xmppPort') and self.get('xmppPassword')):
141 msg = "Credentials are not initialzed. XMPP Connections impossible"
143 raise RuntimeError, msg
145 if not self._omf_api :
146 self._omf_api = OMF6APIFactory.get_api(self.get('xmppHost'),
147 self.get('xmppUser'), self.get('xmppPort'),
148 self.get('xmppPassword'), exp_id = self.exp_id)
150 # if self.get('sources'):
151 # gateway = ResourceGateway.AMtoGateway[self.get('xmppHost')]
152 # user = self.get('sshUser') or self.get('xmppSlice')
153 # dst = user + "@"+ gateway + ":"
154 # (out, err), proc = sshfuncs.rcopy(self.get('sources'), dst)
156 self._topic_app = self.node.get('hostname') +'_'+ str(self.guid) +'_app'
158 self._omf_api.enroll_topic(self._topic_app)
161 if self.get('command'):
162 props['application:binary_path'] = self.get('command')
163 props['application:hrn'] = self.get('command')
164 props['application:membership'] = self._topic_app
165 props['application:type'] = "application"
166 self._omf_api.frcp_create( self.node.get('hostname'), "application", props = props)
170 super(OMF6Application, self).do_deploy()
173 """ Start the RM. It means : Send Xmpp Message Using OMF protocol
174 to execute the application.
175 It becomes STARTED before the messages are sent (for coordination)
178 if not self.get('command') :
179 msg = "Application's Command is not initialized"
181 raise RuntimeError, msg
183 if not self.get('env'):
187 props['state'] = "running"
190 guards['type'] = "application"
191 guards['name'] = self.get('command')
193 self._omf_api.frcp_configure(self._topic_app, props = props, guards = guards )
196 super(OMF6Application, self).do_start()
199 """ Stop the RM. It means : Send Xmpp Message Using OMF protocol to
200 kill the application.
201 State is set to STOPPED after the message is sent.
205 super(OMF6Application, self).do_stop()
207 def do_release(self):
208 """ Clean the RM at the end of the experiment and release the API.
212 props['frcp:type'] = "application"
214 self._omf_api.frcp_release(self.node.get('hostname'),self._topic_app, props = props )
217 OMF6APIFactory.release_api(self.get('xmppHost'),
218 self.get('xmppUser'), self.get('xmppPort'),
219 self.get('xmppPassword'), exp_id = self.exp_id)
221 super(OMF6Application, self).do_release()