-"""
- 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 <http://www.gnu.org/licenses/>.
-
-"""
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
from nepi.util.timefuncs import strfnow, strfdiff, strfvalid
+from nepi.util.logger import Logger
from nepi.execution.trace import TraceAttr
import copy
import functools
-import inspect
import logging
import os
import pkgutil
reschedule_delay = "0.5s"
class ResourceAction:
+ """ Action that a user can order to a Resource Manager
+
+ """
DEPLOY = 0
START = 1
STOP = 2
class ResourceState:
+ """ State of a Resource Manager
+
+ """
NEW = 0
DISCOVERED = 1
PROVISIONED = 2
RELEASED = 8
ResourceState2str = dict({
- NEW = "NEW",
- DISCOVERED = "DISCOVERED",
- PROVISIONED = "PROVISIONED",
- READY = "READY",
- STARTED = "STARTED",
- STOPPED = "STOPPED",
- FINISHED = "FINISHED",
- FAILED = "FAILED",
- RELEASED = "RELEASED",
+ ResourceState.NEW : "NEW",
+ ResourceState.DISCOVERED : "DISCOVERED",
+ ResourceState.PROVISIONED : "PROVISIONED",
+ ResourceState.READY : "READY",
+ ResourceState.STARTED : "STARTED",
+ ResourceState.STOPPED : "STOPPED",
+ ResourceState.FINISHED : "FINISHED",
+ ResourceState.FAILED : "FAILED",
+ ResourceState.RELEASED : "RELEASED",
})
def clsinit(cls):
# Decorator to invoke class initialization method
@clsinit
-class ResourceManager(object):
+class ResourceManager(Logger):
_rtype = "Resource"
_attributes = None
_traces = None
@classmethod
def rtype(cls):
+ """ Returns the type of the Resource Manager
+
+ """
return cls._rtype
@classmethod
return copy.deepcopy(cls._traces.values())
def __init__(self, ec, guid):
+ super(ResourceManager, self).__init__(self.rtype())
+
self._guid = guid
self._ec = weakref.ref(ec)
self._connections = set()
self._ready_time = None
self._release_time = None
- # Logging
- self._logger = logging.getLogger("Resource")
-
- def debug(self, msg, out = None, err = None):
- self.log(msg, logging.DEBUG, out, err)
-
- def error(self, msg, out = None, err = None):
- self.log(msg, logging.ERROR, out, err)
-
- def warn(self, msg, out = None, err = None):
- self.log(msg, logging.WARNING, out, err)
-
- def info(self, msg, out = None, err = None):
- self.log(msg, logging.INFO, out, err)
-
- def log(self, msg, level, out = None, err = None):
- if out:
- msg += " - OUT: %s " % out
-
- if err:
- msg += " - ERROR: %s " % err
-
- msg = self.log_message(msg)
-
- self.logger.log(level, msg)
-
- def log_message(self, msg):
- return " %s guid: %d - %s " % (self._rtype, self.guid, msg)
-
- @property
- def logger(self):
- return self._logger
-
@property
def guid(self):
+ """ Returns the guid of the current RM """
return self._guid
@property
def ec(self):
+ """ Returns the Experiment Controller """
return self._ec()
@property
def connections(self):
+ """ Returns the set of connection for this RM"""
return self._connections
@property
def conditions(self):
+ """ Returns the list of conditions for this RM
+ The list is a dictionary with for each action, a list of tuple
+ describing the conditions. """
return self._conditions
@property
@property
def state(self):
+ """ Get the state of the current RM """
return self._state
+ def log_message(self, msg):
+ """ Improve debugging message by adding more information
+ as the guid and the type of the RM
+
+ :param msg: Message to log
+ :type msg: str
+ :rtype: str
+ """
+ return " %s guid: %d - %s " % (self._rtype, self.guid, msg)
+
def connect(self, guid):
+ """ Connect the current RM with the RM 'guid'
+
+ :param guid: Guid of the RM the current RM will be connected
+ :type guid: int
+ """
if self.valid_connection(guid):
self._connections.add(guid)
def discover(self):
+ """ Discover the Resource. As it is specific for each RM,
+ this method take the time when the RM become DISCOVERED and
+ change the status """
self._discover_time = strfnow()
self._state = ResourceState.DISCOVERED
def provision(self):
+ """ Provision the Resource. As it is specific for each RM,
+ this method take the time when the RM become PROVISIONNED and
+ change the status """
self._provision_time = strfnow()
self._state = ResourceState.PROVISIONED
def start(self):
- """ Start the Resource Manager
+ """ Start the Resource Manager. As it is specific to each RM, this methods
+ just change, after some verifications, the status to STARTED and save the time.
"""
if not self._state in [ResourceState.READY, ResourceState.STOPPED]:
self._state = ResourceState.STARTED
def stop(self):
- """ Start the Resource Manager
+ """ Stop the Resource Manager. As it is specific to each RM, this methods
+ just change, after some verifications, the status to STOPPED and save the time.
"""
if not self._state in [ResourceState.STARTED]:
conditions.append((group, state, time))
def get_connected(self, rtype):
+ """ Return the list of RM with the type 'rtype'
+
+ :param rtype: Type of the RM we look for
+ :type rtype: str
+ :return : list of guid
+ """
connected = []
for guid in self.connections:
rm = self.ec.get_resource(guid)
callback = functools.partial(self.stop_with_conditions)
self.ec.schedule(delay, callback)
else:
- self.logger.debug(" ----- STOPPING ---- ")
+ self.debug(" ----- STOPPING ---- ")
self.stop()
def deploy(self):
self.error("Wrong state %s for deploy" % self.state)
return
- self.debug("----- DEPLOYING ---- ")
+ self.debug("----- READY ---- ")
self._ready_time = strfnow()
self._state = ResourceState.READY
self._state = ResourceState.RELEASED
def valid_connection(self, guid):
- """Check if the connection is available.
+ """Check if the connection is available. This method need to be
+ redefined by each new Resource Manager.
:param guid: Guid of the current Resource Manager
:type guid: int
@classmethod
def resource_types(cls):
+ """Return the type of the Class"""
return cls._resource_types
@classmethod
def register_type(cls, rclass):
+ """Register a new Ressource Manager"""
cls._resource_types[rclass.rtype()] = rclass
@classmethod
def create(cls, rtype, ec, guid):
+ """Create a new instance of a Ressource Manager"""
rclass = cls._resource_types[rtype]
return rclass(ec, guid)
def populate_factory():
+ """Register all the possible RM that exists in the current version of Nepi.
+ """
for rclass in find_types():
ResourceFactory.register_type(rclass)
def find_types():
+ """Look into the different folders to find all the
+ availables Resources Managers
+
+ """
search_path = os.environ.get("NEPI_SEARCH_PATH", "")
search_path = set(search_path.split(" "))
+ import inspect
import nepi.resources
path = os.path.dirname(nepi.resources.__file__)
search_path.add(path)
types.append(attr)
except:
import traceback
+ import logging
err = traceback.format_exc()
logger = logging.getLogger("Resource.find_types()")
logger.error("Error while lading Resource Managers %s" % err)