Commit 6cad39d1 authored by Xavier Thompson's avatar Xavier Thompson

slapgrid: Process promises with instance python

parent 5d5769ca
......@@ -62,7 +62,11 @@ from slapos.grid.svcbackend import (launchSupervisord,
createSupervisordConfiguration,
_getSupervisordConfigurationDirectory,
_getSupervisordSocketPath)
from slapos.grid.utils import (md5digest, dropPrivileges, SlapPopen, updateFile)
from slapos.grid.utils import (md5digest,
dropPrivileges,
SlapPopen,
SlapWait,
updateFile)
from slapos.grid.promise import PromiseLauncher, PromiseError
from slapos.grid.promise.generic import PROMISE_LOG_FOLDER_NAME
from slapos.human import human2bytes
......@@ -655,21 +659,21 @@ stderr_logfile_backups=1
return SLAPGRID_SUCCESS
def _checkPromiseList(self, partition, force=True, check_anomaly=False):
instance_path = os.path.join(self.instance_root, partition.partition_id)
partition_id = partition.partition_id
self.logger.info("Checking %s promises...", partition_id)
instance_path = os.path.join(self.instance_root, partition_id)
promise_log_path = os.path.join(instance_path, PROMISE_LOG_FOLDER_NAME)
promise_dir = os.path.join(instance_path, 'etc', 'plugin')
legacy_dir = os.path.join(instance_path, 'etc', 'promise')
self.logger.info("Checking %s promises..." % partition.partition_id)
uid, gid = None, None
stat_info = os.stat(instance_path)
#stat sys call to get statistics informations
uid = stat_info.st_uid
gid = stat_info.st_gid
promise_dir = os.path.join(instance_path, 'etc', 'plugin')
legacy_promise_dir = os.path.join(instance_path, 'etc', 'promise')
promise_config = {
'promise-folder': promise_dir,
'legacy-promise-folder': legacy_promise_dir,
'legacy-promise-folder': legacy_dir,
'promise-timeout': self.promise_timeout,
'uid': uid,
'gid': gid,
......@@ -680,12 +684,53 @@ stderr_logfile_backups=1
'master-url': partition.server_url,
'partition-cert': partition.cert_file,
'partition-key': partition.key_file,
'partition-id': partition.partition_id,
'partition-id': partition_id,
'computer-id': self.computer_id,
}
promise_checker = PromiseLauncher(config=promise_config, logger=self.logger)
return promise_checker.run()
python = partition.instance_python
has_plugins = os.path.isdir(promise_dir) and os.listdir(promise_dir)
if python is not None and has_plugins:
# Run plugin promises using instance python
self.logger.info("Switch to %s's python at %s", partition_id, python)
code_directory = os.path.dirname(__file__)
plugin_launcher = os.path.join(code_directory, 'promise', 'launcher.py')
command = [python, plugin_launcher]
for option, value in promise_config.items():
if option in ('uid', 'gid', 'legacy-promise-folder'):
continue
if isinstance(value, bool):
value = int(value)
command.append('--' + option)
command.append(str(value))
process_handler = SlapWait(
command,
preexec_fn=lambda: dropPrivileges(uid, gid, logger=self.logger),
cwd=instance_path,
logger=self.logger)
returncode = process_handler.wait(60)
if returncode is None:
self.logger.warn('Plugin promise launcher timed out')
elif returncode != 0:
self.logger.warn('Plugin promise launcher failed')
# Run again with current python to retrieve the computed results
promise_config['force'] = False
promise_config['legacy-promise-folder'] = ''
promise_checker = PromiseLauncher(promise_config, self.logger)
promise_checker.run()
# Run legacy promises
if os.path.isdir(legacy_dir) and os.listdir(legacy_dir):
promise_config['legacy-promise-folder'] = legacy_dir
promise_config['promise-folder'] = ''
promise_config['force'] = force
promise_checker = PromiseLauncher(promise_config, self.logger)
promise_checker.run()
else:
promise_checker = PromiseLauncher(config=promise_config, logger=self.logger)
return promise_checker.run()
def _endInstallationTransaction(self, computer_partition):
partition_id = computer_partition.getId()
......
......@@ -159,6 +159,31 @@ class SlapPopen(subprocess.Popen):
self.output = ''.join(output_lines)
class SlapWait(threading.Thread):
"""
Cross-version subprocess with timeout waiting.
"""
def __init__(self, *args, **kwargs):
threading.Thread.__init__(self)
self.logger = kwargs.pop('logger')
self._args = args
self._kwargs = kwargs
self.start()
def run(self):
self._p = subprocess.Popen(*self._args, **self._kwargs)
self._p.wait()
def wait(self, timeout):
self.join(timeout)
if self.is_alive():
killProcessTree(self._p.pid, self.logger)
self._p.terminate()
self.join()
return None
return self._p.returncode
def md5digest(url):
return hashlib.md5(url.encode('utf-8')).hexdigest()
......
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