Commit 7dbd8742 authored by Alain Takoudjou's avatar Alain Takoudjou

make promise runner work on monitor

parent ed597075
...@@ -33,7 +33,6 @@ import sys ...@@ -33,7 +33,6 @@ import sys
import logging import logging
import time import time
import importlib import importlib
import ConfigParser
import re import re
import traceback import traceback
import psutil import psutil
...@@ -43,7 +42,6 @@ from abc import ABCMeta, abstractmethod ...@@ -43,7 +42,6 @@ from abc import ABCMeta, abstractmethod
from multiprocessing import Process, Queue as MQueue from multiprocessing import Process, Queue as MQueue
import Queue import Queue
from datetime import datetime, timedelta from datetime import datetime, timedelta
from threading import Thread
from slapos.grid.promise import interface from slapos.grid.promise import interface
from slapos.grid.utils import dropPrivileges from slapos.grid.utils import dropPrivileges
from zope import interface as zope_interface from zope import interface as zope_interface
...@@ -57,7 +55,7 @@ class BaseResult(object): ...@@ -57,7 +55,7 @@ class BaseResult(object):
self.__message = message self.__message = message
self.__date = date self.__date = date
if self.__date is None: if self.__date is None:
self.__date = datetime.now() self.__date = datetime.utcnow()
def hasFailed(self): def hasFailed(self):
return self.__problem return self.__problem
...@@ -91,7 +89,8 @@ class PromiseQueueResult(object): ...@@ -91,7 +89,8 @@ class PromiseQueueResult(object):
def __init__(self, path, name, title, result, execution_time=0): def __init__(self, path, name, title, result, execution_time=0):
self.path = path self.path = path
self.name = name self.name = name
self.result = result self.item = result
self.title = title
self.execution_time = execution_time self.execution_time = execution_time
class GenericPromise(object): class GenericPromise(object):
...@@ -448,8 +447,7 @@ class PromiseRunner(Process): ...@@ -448,8 +447,7 @@ class PromiseRunner(Process):
class PromiseLauncher(object): class PromiseLauncher(object):
def __init__(self, config=None, logger=None, config_file=None, def __init__(self, config=None, logger=None, save_method=None):
save_method=None):
""" """
Promise launcher will run promises Promise launcher will run promises
...@@ -464,9 +462,9 @@ class PromiseLauncher(object): ...@@ -464,9 +462,9 @@ class PromiseLauncher(object):
Maximum promise execution time before timeout. Default: 20 Maximum promise execution time before timeout. Default: 20
partition-folder partition-folder
Base path of the partition Base path of the partition
promise-dir promise-folder
Promises folder, all promises scripts will be imported from that folder Promises folder, all promises scripts will be imported from that folder
old-promise-dir old-promise-folder
Old promises folder, where to find bash, shell and standard promises Old promises folder, where to find bash, shell and standard promises
log-folder log-folder
Folder where promises will write logs. Can be None Folder where promises will write logs. Can be None
...@@ -490,14 +488,17 @@ class PromiseLauncher(object): ...@@ -490,14 +488,17 @@ class PromiseLauncher(object):
User GID User GID
profile profile
If True, show Promise consumption and execution time information If True, show Promise consumption and execution time information
run-only-promise-list:
A list of promise from plugins directory that will be executed
""" """
self.save_method = save_method self.save_method = save_method
self.__config = { self.__config = {
'promise-timeout': 20, 'promise-timeout': 20,
'promise-dir': None, 'promise-folder': None,
'old-promise-dir': None, 'old-promise-folder': None,
'log-folder': None, 'log-folder': None,
'partition-folder': None,
'profile': False, 'profile': False,
'uid': None, 'uid': None,
'gid': None, 'gid': None,
...@@ -507,17 +508,16 @@ class PromiseLauncher(object): ...@@ -507,17 +508,16 @@ class PromiseLauncher(object):
'partition-id': None, 'partition-id': None,
'computer-id': None, 'computer-id': None,
'debug': True, 'debug': True,
'check-anomaly': False 'check-anomaly': False,
'run-only-promise-list': None
} }
if config_file is not None:
self.loadConfigFromFile(config_file)
if config is not None: if config is not None:
self.__config.update(config) self.__config.update(config)
for key, value in self.__config.items(): for key, value in self.__config.items():
setattr(self, key.replace('-', '_'), value or None) setattr(self, key.replace('-', '_'), value or None)
if self.promise_dir is None: if self.promise_folder is None:
raise ValueError("Promise folder is missing in configuration!") raise ValueError("Promise folder is missing in configuration!")
if logger is None: if logger is None:
...@@ -534,13 +534,6 @@ class PromiseLauncher(object): ...@@ -534,13 +534,6 @@ class PromiseLauncher(object):
self.queue_result = MQueue() self.queue_result = MQueue()
self.bang_called = False self.bang_called = False
def _loadConfigFromFile(self, config_file):
config = ConfigParser.ConfigParser()
config.read([config_file])
if config.has_section('promises'):
for key, value in config.items('promises'):
self.__config[key] = value
def _loadPromiseModule(self, promise_name): def _loadPromiseModule(self, promise_name):
"""Load a promise from promises directory.""" """Load a promise from promises directory."""
...@@ -568,8 +561,8 @@ class PromiseLauncher(object): ...@@ -568,8 +561,8 @@ class PromiseLauncher(object):
else: else:
result = TestResult(problem=True, message=message) result = TestResult(problem=True, message=message)
return PromiseQueueResult( return PromiseQueueResult(
result=result, item=result,
path=os.path.join(self.promise_dir, promise_name), path=os.path.join(self.promise_folder, promise_name),
name=promise_name, name=promise_name,
title=promise_instance.getTitle(), title=promise_instance.getTitle(),
execution_time=execution_time execution_time=execution_time
...@@ -580,8 +573,7 @@ class PromiseLauncher(object): ...@@ -580,8 +573,7 @@ class PromiseLauncher(object):
Launch the promise and save the result if `self.save_method` is not None Launch the promise and save the result if `self.save_method` is not None
If no save method is set, raise PromiseError in case of failure If no save method is set, raise PromiseError in case of failure
""" """
if self.profile: self.logger.info("Checking promise %s..." % promise_name)
self.logger.info("Checking promise %s..." % promise_name)
try: try:
if promise_module is None: if promise_module is None:
promise_instance = PromiseWrapper(argument_dict) promise_instance = PromiseWrapper(argument_dict)
...@@ -629,19 +621,19 @@ class PromiseLauncher(object): ...@@ -629,19 +621,19 @@ class PromiseLauncher(object):
messsage="No output returned by the promise", messsage="No output returned by the promise",
execution_time=execution_time execution_time=execution_time
) )
self.save_method(queue_item) self.save_method(result=queue_item)
break break
if queue_item.result.hasFailed(): if queue_item.item.hasFailed():
if self.save_method is None: if self.save_method is None:
raise PromiseError(queue_item.result.message) raise PromiseError(queue_item.item.message)
elif isinstance(queue_item.result, AnomalyResult): elif isinstance(queue_item.item, AnomalyResult):
# stop to bang as it was called # stop to bang as it was called
self.bang_called = True self.bang_called = True
if self.save_method is not None: if self.save_method is not None:
queue_item.execution_time = execution_time queue_item.execution_time = execution_time
self.save_method(queue_item) self.save_method(result=queue_item)
break break
if ps_profile: if ps_profile:
...@@ -667,7 +659,7 @@ class PromiseLauncher(object): ...@@ -667,7 +659,7 @@ class PromiseLauncher(object):
if self.save_method is None: if self.save_method is None:
raise PromiseError(message) raise PromiseError(message)
else: else:
self.save_method(self._getErrorPromiseResult( self.save_method(result=self._getErrorPromiseResult(
promise_instance, promise_instance,
promise_name=promise_name, promise_name=promise_name,
message=message, message=message,
...@@ -694,37 +686,41 @@ class PromiseLauncher(object): ...@@ -694,37 +686,41 @@ class PromiseLauncher(object):
'queue': self.queue_result, 'queue': self.queue_result,
} }
if os.path.exists(self.promise_dir) and os.path.isdir(self.promise_dir): if os.path.exists(self.promise_folder) and os.path.isdir(self.promise_folder):
# if there is no __init file, add it # if there is no __init file, add it
init_file = os.path.join(self.promise_dir, '__init__.py') init_file = os.path.join(self.promise_folder, '__init__.py')
if not os.path.exists(init_file): if not os.path.exists(init_file):
with open(init_file, 'w') as f: with open(init_file, 'w') as f:
f.write("") f.write("")
os.chmod(init_file, 0644) os.chmod(init_file, 0644)
if sys.path[0] != self.promise_dir: if sys.path[0] != self.promise_folder:
sys.path[0:0] = [self.promise_dir] sys.path[0:0] = [self.promise_folder]
promise_list = [] promise_list = []
# load all promises so we can catch import errors before launch them # load all promises so we can catch import errors before launch them
for promise_name in os.listdir(self.promise_dir): for promise_name in os.listdir(self.promise_folder):
if promise_name.startswith('__init__') or \ if promise_name.startswith('__init__') or \
not promise_name.endswith('.py'): not promise_name.endswith('.py'):
continue continue
if self.run_only_promise_list is not None and not \
promise_name in self.run_only_promise_list:
continue
promise_list.append((promise_name, promise_list.append((promise_name,
self._loadPromiseModule(promise_name))) self._loadPromiseModule(promise_name)))
for promise in promise_list: for promise in promise_list:
config = { config = {
'path': os.path.join(self.promise_dir, promise[0]), 'path': os.path.join(self.promise_folder, promise[0]),
'name': promise[0] 'name': promise[0]
} }
config.update(base_config) config.update(base_config)
self._launchPromise(promise_name, config, promise[1]) self._launchPromise(promise_name, config, promise[1])
if os.path.exists(self.old_promise_dir) and os.path.isdir(self.old_promise_dir): if not self.run_only_promise_list and os.path.exists(self.old_promise_folder) \
and os.path.isdir(self.old_promise_folder):
# run old promise styles # run old promise styles
for promise_name in os.listdir(self.old_promise_dir): for promise_name in os.listdir(self.old_promise_folder):
promise_path = os.path.join(self.old_promise_dir, promise_name) promise_path = os.path.join(self.old_promise_folder, promise_name)
if not os.path.isfile(promise_path) or \ if not os.path.isfile(promise_path) or \
not os.access(promise_path, os.X_OK): not os.access(promise_path, os.X_OK):
self.logger.warning("Bad promise file at %r." % promise_path) self.logger.warning("Bad promise file at %r." % promise_path)
......
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