Commit 62627b23 authored by Alain Takoudjou's avatar Alain Takoudjou

slapgrid: remove old promise checker implementation

parent f7eadb26
...@@ -37,9 +37,6 @@ import stat ...@@ -37,9 +37,6 @@ import stat
import subprocess import subprocess
import sys import sys
import logging import logging
import time
import psutil
from datetime import datetime
from slapos.grid.exception import BuildoutFailedError, WrongPermissionError from slapos.grid.exception import BuildoutFailedError, WrongPermissionError
...@@ -90,10 +87,6 @@ LOCALE_ENVIRONMENT_REMOVE_LIST = [ ...@@ -90,10 +87,6 @@ LOCALE_ENVIRONMENT_REMOVE_LIST = [
'LC_TIME', 'LC_TIME',
] ]
class PromiseError(Exception):
pass
class SlapPopen(subprocess.Popen): class SlapPopen(subprocess.Popen):
""" """
Almost normal subprocess with greedish features and logging. Almost normal subprocess with greedish features and logging.
...@@ -365,117 +358,3 @@ def createPrivateDirectory(path): ...@@ -365,117 +358,3 @@ def createPrivateDirectory(path):
raise WrongPermissionError('Wrong permissions in %s: ' raise WrongPermissionError('Wrong permissions in %s: '
'is 0%o, should be 0700' 'is 0%o, should be 0700'
% (path, permission)) % (path, permission))
def checkPromiseList(promise_dir, promise_timeout, uid=None, gid=None, cwd=None,
logger=None, profile=False, raise_on_failure=True):
"""
Check a promise list and return the result or raise in case of failure
if `raise_on_failure` is set to True
When `profile` is set to True, log each promise resource usage.
"""
if logger is None:
logging.basicConfig(format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
promise_result_list = []
if os.path.exists(promise_dir) and os.path.isdir(promise_dir):
kw = {}
if uid is not None and gid is not None:
kw["preexec_fn"] = lambda: dropPrivileges(uid, gid, logger=logger)
if cwd is not None:
kw["cwd"] = cwd
for promise in os.listdir(promise_dir):
command = [os.path.join(promise_dir, promise)]
promise = os.path.basename(command[0])
logger.info("Checking promise '%s'.", promise)
if not os.path.isfile(command[0]) or not os.access(command[0], os.X_OK):
# Not executable file
logger.warning("Promise script '%s' is not executable.", promise)
continue
result_dict = {
"returncode": -1,
"title": promise,
"start-date" : datetime.utcnow(),
"execution-time": 0,
"message": ""
}
process_handler = subprocess.Popen(command,
env=None if sys.platform == 'cygwin' else {},
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
**kw)
process_handler.stdin.flush()
process_handler.stdin.close()
process_handler.stdin = None
# Check if the promise finished every tenth of second,
# but timeout after promise_timeout.
sleep_time = 0.1
check_profile = False
if profile:
try:
psutil_process = psutil.Process(process_handler.pid)
check_profile = True
except psutil.NoSuchProcess:
# process is gone
pass
increment_limit = int(promise_timeout / sleep_time)
for current_increment in range(0, increment_limit):
if process_handler.poll() is None:
if check_profile:
try:
io_counter = psutil_process.io_counters()
logger.debug(
"[t=%ss] CPU: %s%%, MEM: %s MB (%s%%), DISK: %s Read - %s Write" % (
current_increment * sleep_time,
psutil_process.cpu_percent(),
psutil_process.memory_info().rss / float(2 ** 20),
round(psutil_process.memory_percent(), 4),
io_counter.read_count,
io_counter.write_count
)
)
except (psutil.AccessDenied, psutil.NoSuchProcess):
# defunct process will raise AccessDenied
pass
time.sleep(sleep_time)
continue
result_dict["execution-time"] = current_increment * sleep_time
result_dict["returncode"] = process_handler.poll()
if result_dict["returncode"] == 0:
# Success!
result_dict["message"] = process_handler.communicate()[0]
else:
stdout, stderr = process_handler.communicate()
if raise_on_failure:
if stderr is None:
stderr = "No error output from '%s'." % promise
else:
stderr = "Promise '%s':" % promise + stderr
raise PromiseError(stderr)
if not stderr:
result_dict["message"] = stdout or ""
else:
result_dict["message"] = stderr
break
else:
process_handler.terminate()
if raise_on_failure:
raise PromiseError("The promise '%s' timed out" % promise)
message = process_handler.stderr.read()
if message is None:
message = process_handler.stdout.read() or ""
message += '\nPROMISE TIMED OUT AFTER %s SECONDS' % promise_timeout
result_dict["message"] = message
result_dict["execution-time"] = current_increment * sleep_time
promise_result_list.append(result_dict)
logger.info("Finished promise %r in %s second(s)." % (
promise, result_dict["execution-time"]))
return promise_result_list
##############################################################################
#
# Copyright (c) 2013 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import os
import slapos.grid.utils
import tempfile
import unittest
class TestGridUtils(unittest.TestCase):
def test_check_promise_success(self):
"""
check that checkPromiseList works well
"""
script = """#!/bin/sh
echo "%(name)s"
sleep 0.1
exit %(code)s
"""
root_directory = tempfile.mkdtemp()
promise_1 = "first_promise"
promise_2 = "second_promise"
promise_timeout = 10
with open(os.path.join(root_directory, promise_1), 'w') as f:
f.write(script % {'name': promise_1, 'code': 0})
with open(os.path.join(root_directory, promise_2), 'w') as f:
f.write(script % {'name': promise_2, 'code': 0})
for file in os.listdir(root_directory):
if 'promise' in file:
os.chmod(os.path.join(root_directory, file), 0755)
result_list = []
try:
result_list = slapos.grid.utils.checkPromiseList(
root_directory,
promise_timeout,
profile=True,
raise_on_failure=True,
logger=None)
except slapos.grid.utils.PromiseError:
self.fail("Unexpected raise of PromiseError in 'checkPromiseList()'")
for result in result_list:
self.assertEquals(result['returncode'], 0)
self.assertTrue(result['message'].strip() in [promise_1, promise_2])
def test_check_promise_failure(self):
"""
check that checkPromiseList works well
"""
script = """#!/bin/sh
echo "%(name)s"
sleep 0.1
exit %(code)s
"""
root_directory = tempfile.mkdtemp()
promise_1 = "first_promise"
promise_2 = "second_promise_fail"
promise_timeout = 10
with open(os.path.join(root_directory, promise_1), 'w') as f:
f.write(script % {'name': promise_1, 'code': 0})
with open(os.path.join(root_directory, promise_2), 'w') as f:
f.write(script % {'name': promise_2, 'code': 1})
for file in os.listdir(root_directory):
if 'promise' in file:
os.chmod(os.path.join(root_directory, file), 0755)
with self.assertRaises(slapos.grid.utils.PromiseError):
slapos.grid.utils.checkPromiseList(
root_directory,
promise_timeout,
profile=True,
raise_on_failure=True,
logger=None)
def test_check_promise_no_raise(self):
"""
check that checkPromiseList works well
"""
script = """#!/bin/sh
echo "%(name)s"
sleep 0.1
exit %(code)s
"""
root_directory = tempfile.mkdtemp()
promise_1 = "first_promise"
promise_2 = "second_promise"
promise_3 = "third_promise"
promise_4 = "fourth_promise_fail"
promise_timeout = 10
with open(os.path.join(root_directory, promise_1), 'w') as f:
f.write(script % {'name': promise_1, 'code': 0})
with open(os.path.join(root_directory, promise_2), 'w') as f:
f.write(script % {'name': promise_2, 'code': 0})
with open(os.path.join(root_directory, promise_3), 'w') as f:
f.write(script % {'name': promise_3, 'code': 0})
with open(os.path.join(root_directory, promise_4), 'w') as f:
f.write(script % {'name': promise_4, 'code': 1})
for file in os.listdir(root_directory):
if 'promise' in file:
os.chmod(os.path.join(root_directory, file), 0755)
result_list = []
try:
result_list = slapos.grid.utils.checkPromiseList(
root_directory,
promise_timeout,
profile=True,
raise_on_failure=False,
logger=None)
except slapos.grid.utils.PromiseError:
self.fail("Unexpected raise of PromiseError in 'checkPromiseList()'")
for result in result_list:
self.assertTrue(result['message'].strip() in [promise_1, promise_2, promise_3, promise_4])
if result['title'] == promise_4:
self.assertEquals(result['returncode'], 1)
else:
self.assertEquals(result['returncode'], 0)
if __name__ == '__main__':
unittest.main()
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