Commit 99c1d7ea authored by Alain Takoudjou's avatar Alain Takoudjou

slapgid.promise: add tests, fixup

parent 6e07cd0b
...@@ -107,12 +107,11 @@ class GenericPromise(object): ...@@ -107,12 +107,11 @@ class GenericPromise(object):
self.__log_folder = self.__config.pop('log-folder', None) self.__log_folder = self.__config.pop('log-folder', None)
self.__partition_folder = self.__config.pop('partition-folder', None) self.__partition_folder = self.__config.pop('partition-folder', None)
self.__check_anomaly = self.__config.pop('check-anomaly', False)
self.__periodicity = self.__config.pop('periodicity', 2) self.__periodicity = self.__config.pop('periodicity', 2)
self.__debug = self.__config.pop('debug', True) self.__debug = self.__config.pop('debug', True)
self.__name = self.__config.pop('name', None) self.__name = self.__config.pop('name', None)
self.__promise_path = self.__config.pop('path', None) self.__promise_path = self.__config.pop('path', None)
self.queue = self.__config.pop('queue', None) self.__queue = self.__config.pop('queue', None)
self.__logger_buffer = None self.__logger_buffer = None
self._validateConf() self._validateConf()
...@@ -122,6 +121,8 @@ class GenericPromise(object): ...@@ -122,6 +121,8 @@ class GenericPromise(object):
def _configureLogger(self): def _configureLogger(self):
self.logger = logging.getLogger(self.__name) self.logger = logging.getLogger(self.__name)
for handler in self.logger.handlers:
self.logger.removeHandler(handler)
if self.__log_folder is None: if self.__log_folder is None:
# configure logger with StringIO # configure logger with StringIO
import cStringIO import cStringIO
...@@ -143,7 +144,7 @@ class GenericPromise(object): ...@@ -143,7 +144,7 @@ class GenericPromise(object):
self.logger.addHandler(logger_handler) self.logger.addHandler(logger_handler)
def _validateConf(self): def _validateConf(self):
if self.queue is None: if self.__queue is None:
raise ValueError("Queue object is not set in configuration") raise ValueError("Queue object is not set in configuration")
if self.__name is None: if self.__name is None:
raise ValueError("Monitor name is not set in configuration") raise ValueError("Monitor name is not set in configuration")
...@@ -153,8 +154,11 @@ class GenericPromise(object): ...@@ -153,8 +154,11 @@ class GenericPromise(object):
if self.__partition_folder is None: if self.__partition_folder is None:
raise ValueError("Monitor partition folder is not set in configuration") raise ValueError("Monitor partition folder is not set in configuration")
def getConfig(self): def getConfig(self, key, default=None):
return self.__config return self.__config.get(key, default)
def setConfig(self, key, value):
self.__config[key] = value
def getTitle(self): def getTitle(self):
return self.__title return self.__title
...@@ -271,7 +275,7 @@ class GenericPromise(object): ...@@ -271,7 +275,7 @@ class GenericPromise(object):
if line != "": if line != "":
result = regex.match(line) result = regex.match(line)
if result is not None: if result is not None:
if result.groups()[0] < date_string: if result.groups()[0] <= date_string:
break break
if not only_failure or \ if not only_failure or \
(only_failure and result.groups()[1] == 'ERROR'): (only_failure and result.groups()[1] == 'ERROR'):
...@@ -288,21 +292,13 @@ class GenericPromise(object): ...@@ -288,21 +292,13 @@ class GenericPromise(object):
line_list.reverse() line_list.reverse()
return line_list return line_list
def defaultTest(self, latest_minute=2, failure_amount=1, exact_match=True, def defaultTest(self, latest_minute=2, failure_amount=1, is_anomaly=False):
is_anomaly=False):
""" """
Test if the latest messages contain `failure_amount` failures. Test if the latest messages contain `failure_amount` failures.
@param latest_minute: test the result from now to the latest X minutes in @param latest_minute: test the result from now to the latest X minutes in
the past. the past.
@param failure_amount: fail is this amount of failure is found in result @param failure_amount: fail is this amount of failure is found in result
@param exact_match: bool (True|False).
True:
only fail if the number of failure found is equal to
`failure_amount`, exactly `failure_amount` promise result are tested
starting from the most recent .
False:
fail if at least one failure is found.
@param is_anomaly: Say if the result is an AnomalyResult of TestResult @param is_anomaly: Say if the result is an AnomalyResult of TestResult
""" """
...@@ -315,19 +311,19 @@ class GenericPromise(object): ...@@ -315,19 +311,19 @@ class GenericPromise(object):
) )
result_size = len(latest_result_list) result_size = len(latest_result_list)
if result_size == 0: if result_size == 0:
return module(problem=False, message="No result!") return module(problem=False, message="No result found!")
i = 0 i = 0
failure_found = 0 failure_found = 0
latest_result_list.reverse() latest_result_list.reverse()
# we test at most the `failure_amount` latest results # we test at most the `failure_amount` latest results
while i < result_size and i < failure_amount: while i < result_size and failure_found < failure_amount:
if latest_result_list[i][1] == 'ERROR': if latest_result_list[i][1] == 'ERROR':
failure_found += 1 failure_found += 1
problem = True problem = True
i += 1 i += 1
if exact_match and failure_found != failure_amount: if failure_found != failure_amount:
return module(problem=False, message=latest_result_list[0][2]) return module(problem=False, message=latest_result_list[0][2])
return module(problem=problem, message=latest_result_list[0][2]) return module(problem=problem, message=latest_result_list[0][2])
...@@ -354,7 +350,7 @@ class GenericPromise(object): ...@@ -354,7 +350,7 @@ class GenericPromise(object):
except Exception, e: except Exception, e:
# log the result # log the result
self.logger.error(str(e)) self.logger.error(str(e))
if self.__check_anomaly: if self.getConfig('check-anomaly', False):
# run sense, anomaly # run sense, anomaly
try: try:
result = self.anomaly() result = self.anomaly()
...@@ -362,8 +358,9 @@ class GenericPromise(object): ...@@ -362,8 +358,9 @@ class GenericPromise(object):
raise ValueError("Promise anomaly method returned 'None'") raise ValueError("Promise anomaly method returned 'None'")
except Exception, e: except Exception, e:
result = AnomalyResult(problem=True, message=str(e)) result = AnomalyResult(problem=True, message=str(e))
if result.hasFailed() and can_bang: else:
self.__bang("Promise %s is failing" % self.__title) if result.hasFailed() and can_bang:
self.__bang("Promise %s is failing" % self.__title)
else: else:
# run sense, test # run sense, test
try: try:
...@@ -377,8 +374,7 @@ class GenericPromise(object): ...@@ -377,8 +374,7 @@ class GenericPromise(object):
self.__logger_buffer.close() self.__logger_buffer.close()
# send the result of this promise # send the result of this promise
# should not raise Queue.Full exception as limit is not set to constructor self.__queue.put(PromiseQueueResult(
self.queue.put(PromiseQueueResult(
path=self.__promise_path, path=self.__promise_path,
name=self.__name, name=self.__name,
title=self.__title, title=self.__title,
...@@ -395,6 +391,7 @@ class PromiseWrapper(GenericPromise): ...@@ -395,6 +391,7 @@ class PromiseWrapper(GenericPromise):
def __init__(self, config): def __init__(self, config):
GenericPromise.__init__(self, config) GenericPromise.__init__(self, config)
self.setConfig("check-anomaly", False)
self.setPeriodicity(minute=2) self.setPeriodicity(minute=2)
@staticmethod @staticmethod
...@@ -550,11 +547,13 @@ class PromiseLauncher(object): ...@@ -550,11 +547,13 @@ class PromiseLauncher(object):
if logger is None: if logger is None:
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
self.logger.setLevel(logging.DEBUG if self.debug else logging.INFO) self.logger.setLevel(logging.DEBUG if self.debug else logging.INFO)
handler = logging.StreamHandler() if len(self.logger.handlers) == 0 or \
handler.setFormatter( not isinstance(self.logger.handlers[0], logging.StreamHandler):
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") handler = logging.StreamHandler()
) handler.setFormatter(
self.logger.addHandler(handler) logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
)
self.logger.addHandler(handler)
else: else:
self.logger = logger self.logger = logger
...@@ -580,8 +579,7 @@ class PromiseLauncher(object): ...@@ -580,8 +579,7 @@ class PromiseLauncher(object):
try: try:
latest_timestamp = float(f.read()) latest_timestamp = float(f.read())
current_timediff = (time.time() - latest_timestamp) / 60.0 current_timediff = (time.time() - latest_timestamp) / 60.0
margin_error = 0.15 # 0.15 seconds less is accepted if current_timediff >= periodicity:
if current_timediff + margin_error >= periodicity:
return True return True
self.logger.debug("Skip Promise %r. periodicity=%s, time_diff=%s" % ( self.logger.debug("Skip Promise %r. periodicity=%s, time_diff=%s" % (
promise_name, periodicity, current_timediff)) promise_name, periodicity, current_timediff))
...@@ -679,10 +677,10 @@ class PromiseLauncher(object): ...@@ -679,10 +677,10 @@ class PromiseLauncher(object):
# process is gone # process is gone
pass pass
for current_increment in range(0, increment_limit): for current_increment in range(0, increment_limit):
execution_time = current_increment * sleep_time execution_time = (current_increment + 1) * sleep_time
if not promise_process.is_alive(): if not promise_process.is_alive():
try: try:
queue_item = self.queue_result.get(False, 2) queue_item = self.queue_result.get(True, 1)
except Queue.Empty: except Queue.Empty:
# no result found in process result Queue # no result found in process result Queue
if self.save_method is None: if self.save_method is None:
...@@ -751,6 +749,7 @@ class PromiseLauncher(object): ...@@ -751,6 +749,7 @@ class PromiseLauncher(object):
'partition-folder': self.partition_folder, 'partition-folder': self.partition_folder,
'debug': self.debug, 'debug': self.debug,
'slapgrid-mode': self.slapgrid_mode, 'slapgrid-mode': self.slapgrid_mode,
'check-anomaly': self.check_anomaly,
'master-url': self.master_url, 'master-url': self.master_url,
'partition-cert': self.partition_cert, 'partition-cert': self.partition_cert,
'partition-key': self.partition_key, 'partition-key': self.partition_key,
...@@ -781,13 +780,20 @@ class PromiseLauncher(object): ...@@ -781,13 +780,20 @@ class PromiseLauncher(object):
promise_list.append((promise_name, promise_list.append((promise_name,
self._loadPromiseModule(promise_name))) self._loadPromiseModule(promise_name)))
for promise in promise_list: for name, module in promise_list:
promise_path = os.path.join(self.promise_folder, name)
config = { config = {
'path': os.path.join(self.promise_folder, promise[0]), 'path': promise_path,
'name': promise[0] 'name': name
} }
if module.__file__ != promise_path:
# cached module need to be updated
module = reload(module)
#if os.path.getmtime(promise_path) > os.path.getmtime('%sc' % promise_path):
# module = reload(module)
config.update(base_config) config.update(base_config)
self._launchPromise(promise_name, config, promise[1]) self._launchPromise(name, config, module)
if not self.run_only_promise_list and os.path.exists(self.old_promise_folder) \ if not self.run_only_promise_list and os.path.exists(self.old_promise_folder) \
and os.path.isdir(self.old_promise_folder): and os.path.isdir(self.old_promise_folder):
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment