+#
+# 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
FAILED = 7
RELEASED = 8
+ResourceState2str = dict({
+ 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):
+ """ Initializes template information (i.e. attributes and traces)
+ for the ResourceManager class
+ """
cls._clsinit()
return cls
+def clsinit_copy(cls):
+ """ Initializes template information (i.e. attributes and traces)
+ for the ResourceManager class, inheriting attributes and traces
+ from the parent class
+ """
+ cls._clsinit_copy()
+ return cls
+
# Decorator to invoke class initialization method
@clsinit
-class ResourceManager(object):
+class ResourceManager(Logger):
_rtype = "Resource"
- _filters = None
_attributes = None
_traces = None
@classmethod
- def _register_filter(cls, attr):
+ def _register_attribute(cls, attr):
""" Resource subclasses will invoke this method to add a
- filter attribute
+ resource attribute
"""
- cls._filters[attr.name] = attr
+ cls._attributes[attr.name] = attr
@classmethod
- def _register_attribute(cls, attr):
- """ Resource subclasses will invoke this method to add a
+ def _remove_attribute(cls, name):
+ """ Resource subclasses will invoke this method to remove a
resource attribute
"""
- cls._attributes[attr.name] = attr
+ del cls._attributes[name]
@classmethod
def _register_trace(cls, trace):
"""
cls._traces[trace.name] = trace
-
@classmethod
- def _register_filters(cls):
- """ Resource subclasses will invoke this method to register
- resource filters
+ def _remove_trace(cls, name):
+ """ Resource subclasses will invoke this method to remove a
+ resource trace
"""
- pass
+ del cls._traces[name]
@classmethod
def _register_attributes(cls):
@classmethod
def _clsinit(cls):
- """ Create a new dictionnary instance of the dictionnary
- with the same template.
-
- Each ressource should have the same registration dictionary
- template with different instances.
+ """ ResourceManager child classes have different attributes and traces.
+ Since the templates that hold the information of attributes and traces
+ are 'class attribute' dictionaries, initially they all point to the
+ parent class ResourceManager instances of those dictionaries.
+ In order to make these templates independent from the parent's one,
+ it is necessary re-initialize the corresponding dictionaries.
+ This is the objective of the _clsinit method
"""
- # static template for resource filters
- cls._filters = dict()
- cls._register_filters()
-
# static template for resource attributes
cls._attributes = dict()
cls._register_attributes()
cls._register_traces()
@classmethod
- def rtype(cls):
- return cls._rtype
+ def _clsinit_copy(cls):
+ """ Same as _clsinit, except that it also inherits all attributes and traces
+ from the parent class.
+ """
+ # static template for resource attributes
+ cls._attributes = copy.deepcopy(cls._attributes)
+ cls._register_attributes()
- @classmethod
- def get_filters(cls):
- """ Returns a copy of the filters
+ # static template for resource traces
+ cls._traces = copy.deepcopy(cls._traces)
+ cls._register_traces()
- """
- return copy.deepcopy(cls._filters.values())
+ @classmethod
+ def rtype(cls):
+ return cls._rtype
@classmethod
def get_attributes(cls):
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):
return self._guid
def state(self):
return self._state
+ def log_message(self, msg):
+ return " %s guid: %d - %s " % (self._rtype, self.guid, msg)
+
def connect(self, guid):
if self.valid_connection(guid):
self._connections.add(guid)
- def discover(self, filters = None):
+ def discover(self):
self._discover_time = strfnow()
self._state = ResourceState.DISCOVERED
- def provision(self, filters = None):
+ def provision(self):
self._provision_time = strfnow()
self._state = ResourceState.PROVISIONED
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
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)