X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Fresources%2Fomf%2Fapplication.py;h=37d244cdb88619bb3db0df52287022d0ede78645;hb=450b5dd0a993f63eb2ec34bbc656c558572eb44c;hp=f65b3547b5018283eecbf6956370968cfdca295c;hpb=dc8f5de864464f4a2ccbaa73ac881f50d2c64899;p=nepi.git diff --git a/src/nepi/resources/omf/application.py b/src/nepi/resources/omf/application.py index f65b3547..37d244cd 100644 --- a/src/nepi/resources/omf/application.py +++ b/src/nepi/resources/omf/application.py @@ -1,28 +1,32 @@ -""" - NEPI, a framework to manage network experiments - Copyright (C) 2013 INRIA - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -""" - -from nepi.execution.resource import ResourceManager, clsinit +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2013 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author: Alina Quereilhac +# Julien Tribino + +from nepi.execution.resource import ResourceManager, clsinit_copy, \ + ResourceState, reschedule_delay, failtrap from nepi.execution.attribute import Attribute, Flags +from nepi.resources.omf.omf_resource import ResourceGateway, OMFResource +from nepi.resources.omf.node import OMFNode from nepi.resources.omf.omf_api import OMFAPIFactory -@clsinit -class OMFApplication(ResourceManager): +@clsinit_copy +class OMFApplication(OMFResource): """ .. class:: Class Args : @@ -35,35 +39,28 @@ class OMFApplication(ResourceManager): .. note:: - This class is used only by the Experiment Controller through the Resource Factory + This class is used only by the Experiment Controller through the + Resource Factory """ _rtype = "OMFApplication" _authorized_connections = ["OMFNode"] - _waiters = ["OMFNode", "OMFChannel", "OMFWifiInterface"] @classmethod def _register_attributes(cls): - """Register the attributes of an OMF application - """ + """ Register the attributes of an OMF application + """ appid = Attribute("appid", "Name of the application") path = Attribute("path", "Path of the application") args = Attribute("args", "Argument of the application") env = Attribute("env", "Environnement variable of the application") - xmppSlice = Attribute("xmppSlice","Name of the slice", flags = Flags.Credential) - xmppHost = Attribute("xmppHost", "Xmpp Server",flags = Flags.Credential) - xmppPort = Attribute("xmppPort", "Xmpp Port",flags = Flags.Credential) - xmppPassword = Attribute("xmppPassword", "Xmpp Port",flags = Flags.Credential) + stdin = Attribute("stdin", "Input of the application", default = "") cls._register_attribute(appid) cls._register_attribute(path) cls._register_attribute(args) cls._register_attribute(env) - cls._register_attribute(xmppSlice) - cls._register_attribute(xmppHost) - cls._register_attribute(xmppPort) - cls._register_attribute(xmppPassword) - + cls._register_attribute(stdin) def __init__(self, ec, guid): """ @@ -75,7 +72,6 @@ class OMFApplication(ResourceManager): :type creds: dict """ - super(OMFApplication, self).__init__(ec, guid) self.set('appid', "") @@ -87,75 +83,141 @@ class OMFApplication(ResourceManager): self._omf_api = None - def _validate_connection(self, guid): - """Check if the connection is available. + self.add_set_hook() + + @property + def exp_id(self): + return self.ec.exp_id + + @property + def node(self): + rm_list = self.get_connected(OMFNode.rtype()) + if rm_list: return rm_list[0] + return None + + def stdin_hook(self, old_value, new_value): + self._omf_api.send_stdin(self.node.get('hostname'), new_value, self.get('appid')) + return new_value + + def add_set_hook(self): + attr = self._attrs["stdin"] + attr.set_hook = self.stdin_hook - :param guid: Guid of the current RM + def valid_connection(self, guid): + """ Check if the connection with the guid in parameter is possible. + Only meaningful connections are allowed. + + :param guid: Guid of RM it will be connected :type guid: int :rtype: Boolean """ rm = self.ec.get_resource(guid) if rm.rtype() not in self._authorized_connections: - msg = "Connection between %s %s and %s %s refused : An Application can be connected only to a Node" % (self.rtype(), self._guid, rm.rtype(), guid) - self._logger.debug(msg) + msg = ("Connection between %s %s and %s %s refused: " + "An Application can be connected only to a Node" ) % \ + (self.rtype(), self._guid, rm.rtype(), guid) + self.debug(msg) + return False + elif len(self.connections) != 0 : - msg = "Connection between %s %s and %s %s refused : Already Connected" % (self.rtype(), self._guid, rm.rtype(), guid) - self._logger.debug(msg) + msg = ("Connection between %s %s and %s %s refused: " + "This Application is already connected" ) % \ + (self.rtype(), self._guid, rm.rtype(), guid) + self.debug(msg) + return False + else : - msg = "Connection between %s %s and %s %s accepted" % (self.rtype(), self._guid, rm.rtype(), guid) - self._logger.debug(msg) + msg = "Connection between %s %s and %s %s accepted" % ( + self.rtype(), self._guid, rm.rtype(), guid) + self.debug(msg) + return True - def _get_nodes(self, conn_set): - """Get the RM of the node to which the application is connected + @failtrap + def deploy(self): + """ Deploy the RM. It means nothing special for an application + for now (later it will be upload sources, ...) + It becomes DEPLOYED after getting the xmpp client. - :param conn_set: Connections of the current Guid - :type conn_set: set - :rtype: ResourceManager """ + if not self._omf_api : + self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), + self.get('xmppHost'), self.get('xmppPort'), + self.get('xmppPassword'), exp_id = self.exp_id) - for elt in conn_set: - rm = self.ec.get_resource(elt) - if rm.rtype() == "OMFNode": - return rm - return None - - def deploy(self): - """Deploy the RM + if not self._omf_api : + msg = "Credentials are not initialzed. XMPP Connections impossible" + self.error(msg) + raise RuntimeError, msg - """ - self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), - self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword')) super(OMFApplication, self).deploy() + @failtrap def start(self): - """Send Xmpp Message Using OMF protocol to execute the application + """ Start the RM. It means : Send Xmpp Message Using OMF protocol + to execute the application. + It becomes STARTED before the messages are sent (for coordination) """ - super(OMFApplication, self).start() - msg = " " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + self.get('appid') + " : " + self.get('path') + " : " + self.get('args') + " : " + self.get('env') - self.debug(msg) + if not (self.get('appid') and self.get('path')) : + msg = "Application's information are not initialized" + self.error(msg) + raise RuntimeError, msg + + if not self.get('args'): + self.set('args', " ") + if not self.get('env'): + self.set('env', " ") + + # Some information to check the information in parameter + msg = " " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + \ + self.get('appid') + " : " + self.get('path') + " : " + \ + self.get('args') + " : " + self.get('env') + self.info(msg) + + try: + self._omf_api.execute(self.node.get('hostname'),self.get('appid'), \ + self.get('args'), self.get('path'), self.get('env')) + except AttributeError: + msg = "Credentials are not initialzed. XMPP Connections impossible" + self.error(msg) + raise - if self.get('appid') and self.get('path') and self.get('args') and self.get('env'): - rm_node = self._get_nodes(self._connections) - self._omf_api.execute(rm_node.get('hostname'),self.get('appid'), self.get('args'), self.get('path'), self.get('env')) + super(OMFApplication, self).start() + @failtrap def stop(self): - """Send Xmpp Message Using OMF protocol to kill the application + """ Stop the RM. It means : Send Xmpp Message Using OMF protocol to + kill the application. + State is set to STOPPED after the message is sent. """ + try: + self._omf_api.exit(self.node.get('hostname'),self.get('appid')) + except AttributeError: + msg = "Credentials were not initialzed. XMPP Connections impossible" + self.error(msg) + raise - rm_node = self._get_nodes(self._connections) - self._omf_api.exit(rm_node.get('hostname'),self.get('appid')) super(OMFApplication, self).stop() + self.set_finished() def release(self): - """Clean the RM at the end of the experiment + """ Clean the RM at the end of the experiment and release the API. """ - OMFAPIFactory.release_api(self.get('xmppSlice'), - self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword')) + try: + if self._omf_api : + OMFAPIFactory.release_api(self.get('xmppSlice'), + self.get('xmppHost'), self.get('xmppPort'), + self.get('xmppPassword'), exp_id = self.exp_id) + except: + import traceback + err = traceback.format_exc() + self.error(err) + + super(OMFApplication, self).release()