X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Fresources%2Fomf%2Fnode.py;h=c0e10f912621bfcb81ff683d2dc5e63bf7a6cd8f;hb=f025a30a215310a9803067a25e244137b71f56f2;hp=0099ff7c6a173b4e437f9abf089e5d2d6c0c9957;hpb=4896d77f40a611a22f9f1f8f2ae0e63e9008fee1;p=nepi.git diff --git a/src/nepi/resources/omf/node.py b/src/nepi/resources/omf/node.py index 0099ff7c..c0e10f91 100644 --- a/src/nepi/resources/omf/node.py +++ b/src/nepi/resources/omf/node.py @@ -1,33 +1,36 @@ -""" - 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 from nepi.execution.attribute import Attribute, Flags +from nepi.resources.omf.omf_resource import ResourceGateway, OMFResource +from nepi.resources.omf.omf_api_factory import OMFAPIFactory -from nepi.resources.omf.omf_api import OMFAPIFactory - -import nepi -import logging import time -@clsinit -class OMFNode(ResourceManager): +reschedule_check = "0.3s" +confirmation_counter = 300 + +@clsinit_copy +class OMFNode(OMFResource): """ .. class:: Class Args : @@ -38,14 +41,9 @@ class OMFNode(ResourceManager): :param creds: Credentials to communicate with the rm (XmppClient for OMF) :type creds: dict - .. note:: - - This class is used only by the Experiment Controller through the Resource Factory - """ _rtype = "OMFNode" _authorized_connections = ["OMFApplication" , "OMFWifiInterface"] - _waiters = [] @classmethod def _register_attributes(cls): @@ -53,33 +51,8 @@ class OMFNode(ResourceManager): """ hostname = Attribute("hostname", "Hostname of the machine") - cpu = Attribute("cpu", "CPU of the node") - ram = Attribute("ram", "RAM of the node") - 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) - cls._register_attribute(hostname) - cls._register_attribute(ram) - cls._register_attribute(cpu) - cls._register_attribute(xmppSlice) - cls._register_attribute(xmppHost) - cls._register_attribute(xmppPort) - cls._register_attribute(xmppPassword) - - @classmethod - def _register_filters(cls): - """Register the filters of an OMF Node - """ - hostname = Attribute("hostname", "Hostname of the machine") - gateway = Attribute("gateway", "Gateway") - granularity = Attribute("granularity", "Granularity of the reservation time") - hardware_type = Attribute("hardware_type", "Hardware type of the machine") - cls._register_filter(hostname) - cls._register_filter(gateway) - cls._register_filter(granularity) - cls._register_filter(hardware_type) + cls._register_attribute(hostname) # XXX: We don't necessary need to have the credentials at the # moment we create the RM @@ -89,21 +62,19 @@ class OMFNode(ResourceManager): :type ec: ExperimentController :param guid: guid of the RM :type guid: int - :param creds: Credentials to communicate with the rm (XmppClient for OMF) - :type creds: dict """ super(OMFNode, self).__init__(ec, guid) self._omf_api = None - self._logger = logging.getLogger("nepi.omf.omfNode ") + @property + def exp_id(self): + return self.ec.exp_id - # XXX: TO DISCUSS - self._logger.setLevel(nepi.LOGLEVEL) - - def _validate_connection(self, guid): - """Check if the connection is available. + 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 the current RM :type guid: int @@ -111,74 +82,85 @@ class OMFNode(ResourceManager): """ rm = self.ec.get_resource(guid) - if rm.rtype() in self._authorized_connections: - self._logger.debug("Connection between %s %s and %s %s accepted" % - (self.rtype(), self._guid, rm.rtype(), guid)) + if rm.get_rtype() in self._authorized_connections: + msg = "Connection between %s %s and %s %s accepted" % ( + self.get_rtype(), self._guid, rm.get_rtype(), guid) + self.debug(msg) return True - self._logger.debug("Connection between %s %s and %s %s refused" % - (self.rtype(), self._guid, rm.rtype(), guid)) - return False - - def deploy_action(self): - """Deploy the RM - - """ - self._omf_api = OMFAPIFactory.get_api(self.get('xmppSlice'), - self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword')) - self._omf_api.enroll_host(self.get('hostname')) - - super(OMFNode, self).deploy_action() - - def discover(self): - """ Discover the availables nodes - - """ - pass - - def provision(self): - """ Provision some availables nodes - - """ - pass - def start(self): - """Send Xmpp Message Using OMF protocol to enroll the node into the experiment + msg = "Connection between %s %s and %s %s refused" % ( + self.get_rtype(), self._guid, rm.get_rtype(), guid) + self.error(msg) - """ - super(OMFNode, self).start() + return False + def do_deploy(self): + """ Deploy the RM. It means : Send Xmpp Message Using OMF protocol + to enroll the node into the experiment. - def stop(self): - """Send Xmpp Message Using OMF protocol to disconnect the node + """ + if not self.get('xmppServer'): + msg = "XmppServer is not initialzed. XMPP Connections impossible" + self.error(msg) + raise RuntimeError, msg + + if not self.get('version'): + msg = "Version of OMF is not indicated" + self.error(msg) + raise RuntimeError, msg + + if not (self.get('xmppUser') or self.get('xmppPort') + or self.get('xmppPassword')): + msg = "Credentials are not all initialzed. Default values will be used" + self.warn(msg) + + if not self._omf_api : + self._omf_api = OMFAPIFactory.get_api(self.get('version'), + self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'), + self.get('xmppPassword'), exp_id = self.exp_id) + + if not self.get('hostname') : + msg = "Hostname's value is not initialized" + self.error(msg) + raise RuntimeError, msg + + if self.get('version') == "5": + self._omf_api.enroll_host(self.get('hostname')) + else: + self._omf_api.enroll_topic(self.get('hostname')) + + super(OMFNode, self).do_deploy() + + def do_release(self): + """ Clean the RM at the end of the experiment by unenrolling + the node from the topic """ - super(OMFNode, self).stop() + from nepi.resources.omf.application import OMFApplication + rm_list = self.get_connected(OMFApplication.get_rtype()) + if rm_list: + for rm in rm_list: + if rm.state < ResourceState.RELEASED: + self.ec.schedule(reschedule_delay, self.release) + return + + from nepi.resources.omf.interface import OMFWifiInterface + rm_list = self.get_connected(OMFWifiInterface.get_rtype()) + if rm_list: + for rm in rm_list: + if rm.state < ResourceState.RELEASED: + self.ec.schedule(reschedule_delay, self.release) + return + + if self._omf_api: + if self.get('version') == "5": + self._omf_api.release(self.get('hostname')) + else: + self._omf_api.unenroll_topic(self.get('hostname')) + + OMFAPIFactory.release_api(self.get('version'), + self.get('xmppServer'), self.get('xmppUser'), self.get('xmppPort'), + self.get('xmppPassword'), exp_id = self.exp_id) + + super(OMFNode, self).do_release() - def release(self): - """Clean the RM at the end of the experiment - - """ - self._omf_api.release(self.get('hostname')) - OMFAPIFactory.release_api(self.get('xmppSlice'), - self.get('xmppHost'), self.get('xmppPort'), self.get('xmppPassword')) - - - def configure(self): - #routes = self.tc._add_route.get(self.guid, []) - #iface_guids = self.tc.get_connected(self.guid, "devs", "node") - - for route in routes: - (destination, netprefix, nexthop, metric, device) = route - netmask = ipaddr2.ipv4_mask2dot(netprefix) - - # Validate that the interface is associated to the node - for iface_guid in iface_guids: - iface = self.tc.elements.get(iface_guid) - if iface.devname == device: - self._omf_api.execute(self.get('hostname'), - "Id#%s" % str(random.getrandbits(128)), - "add -net %s netmask %s dev %s" % (destination, netmask, iface.devname), - "/sbin/route", # path - None, # env - ) - break