Commit 451846f4 authored by Rafael Monnerat's avatar Rafael Monnerat

slapos: Add new command slapos node promise

  Introduce a new command for run promises only, from all partitions. This helps to perform quick
  checks.
parent fd2a6906
Pipeline #6269 canceled with stage
in 0 seconds
...@@ -102,6 +102,7 @@ setup(name=name, ...@@ -102,6 +102,7 @@ setup(name=name,
'node report = slapos.cli.slapgrid:ReportCommand', 'node report = slapos.cli.slapgrid:ReportCommand',
'node software = slapos.cli.slapgrid:SoftwareCommand', 'node software = slapos.cli.slapgrid:SoftwareCommand',
'node instance = slapos.cli.slapgrid:InstanceCommand', 'node instance = slapos.cli.slapgrid:InstanceCommand',
'node promise = slapos.cli.slapgrid:PromiseCommand',
'node boot = slapos.cli.boot:BootCommand', 'node boot = slapos.cli.boot:BootCommand',
'node collect = slapos.cli.collect:CollectCommand', 'node collect = slapos.cli.collect:CollectCommand',
# SlapOS client commands # SlapOS client commands
......
...@@ -173,3 +173,11 @@ class ReportCommand(SlapgridCommand): ...@@ -173,3 +173,11 @@ class ReportCommand(SlapgridCommand):
method_name = 'agregateAndSendUsage' method_name = 'agregateAndSendUsage'
default_pidfile = '/opt/slapos/slapgrid-ur.pid' default_pidfile = '/opt/slapos/slapgrid-ur.pid'
pidfile_option_name = 'pidfile_report' pidfile_option_name = 'pidfile_report'
class PromiseCommand(SlapgridCommand):
"""run only promises to test the parition state"""
method_name = 'processPromiseList'
default_pidfile = '/opt/slapos/slapgrid-cp.pid'
pidfile_option_name = 'pidfile_instance'
...@@ -936,6 +936,73 @@ stderr_logfile_backups=1 ...@@ -936,6 +936,73 @@ stderr_logfile_backups=1
if partition_access_status is None or status_error: if partition_access_status is None or status_error:
computer_partition.started() computer_partition.started()
def processPromise(self, computer_partition):
"""
Process the promises from a given Computer Partition, depending on its state
"""
computer_partition_id = computer_partition.getId()
# Sanity checks before processing
# Those values should not be None or empty string or any falsy value
if not computer_partition_id:
raise ValueError('Computer Partition id is empty.')
# Check if we defined explicit list of partitions to process.
# If so, if current partition not in this list, skip.
if len(self.computer_partition_filter_list) > 0 and \
(computer_partition_id not in self.computer_partition_filter_list):
return
instance_path = os.path.join(self.instance_root, computer_partition_id)
os.environ['SLAPGRID_INSTANCE_ROOT'] = self.instance_root
try:
software_url = computer_partition.getSoftwareRelease().getURI()
except NotFoundError:
# Problem with instance: SR URI not set.
# Try to process it anyway, it may need to be deleted.
software_url = None
try:
software_path = os.path.join(self.software_root, md5digest(software_url))
except TypeError:
# Problem with instance: SR URI not set.
# Try to process it anyway, it may need to be deleted.
software_path = None
computer_partition_state = computer_partition.getState()
local_partition = Partition(
software_path=software_path,
instance_path=instance_path,
supervisord_partition_configuration_path=os.path.join(
_getSupervisordConfigurationDirectory(self.instance_root), '%s.conf' %
computer_partition_id),
supervisord_socket=self.supervisord_socket,
computer_partition=computer_partition,
computer_id=self.computer_id,
partition_id=computer_partition_id,
server_url=self.master_url,
software_release_url=software_url,
certificate_repository_path=self.certificate_repository_path,
buildout=self.buildout,
buildout_debug=self.buildout_debug,
logger=self.logger,
retention_delay=getattr(computer_partition, '_filter_dict', {}).get('retention_delay', '0'),
instance_min_free_space=self.instance_min_free_space,
instance_storage_home=self.instance_storage_home,
ipv4_global_network=self.ipv4_global_network,
)
if (computer_partition_id not in self.computer_partition_filter_list):
self.logger.info('Processing Promises for Computer Partition %s.' % computer_partition_id)
self.logger.info(' Software URL: %s' % software_url)
self.logger.info(' Software path: %s' % software_path)
self.logger.info(' Instance path: %s' % instance_path)
if computer_partition_state == COMPUTER_PARTITION_STARTED_STATE:
self._checkPromiseList(local_partition)
#self._checkPromiseAnomaly(local_partition, computer_partition)
def processComputerPartition(self, computer_partition): def processComputerPartition(self, computer_partition):
""" """
Process a Computer Partition, depending on its state Process a Computer Partition, depending on its state
...@@ -1324,6 +1391,64 @@ stderr_logfile_backups=1 ...@@ -1324,6 +1391,64 @@ stderr_logfile_backups=1
return SLAPGRID_PROMISE_FAIL return SLAPGRID_PROMISE_FAIL
return SLAPGRID_SUCCESS return SLAPGRID_SUCCESS
def processPromiseList(self):
"""
Will check and process promises for each Computer Partition.
"""
self.logger.info('Processing promises...')
# Return success value
clean_run_promise = True
check_required_only_partitions([cp.getId() for cp in self.getComputerPartitionList()],
self.computer_partition_filter_list)
# Filter all dummy / empty partitions
computer_partition_list = self.FilterComputerPartitionList(
self.getComputerPartitionList())
promise_error_partition_list = []
for computer_partition in computer_partition_list:
try:
# Process the partition itself
self.processPromise(computer_partition)
# Send log before exiting
except (SystemExit, KeyboardInterrupt):
raise
except PromiseError as exc:
clean_run_promise = False
try:
self.logger.error(exc)
promise_error_partition_list.append((computer_partition, exc))
except (SystemExit, KeyboardInterrupt):
raise
except Exception:
self.logger.exception('Problem while reporting error, continuing:')
except Exception as exc:
clean_run_promise = False
self.logger.exception('Problem while reporting error, continuing:')
promise_error_partition_list.append((computer_partition, exc))
def getPartitionType(part):
"""returns the partition type, if known at that point.
"""
try:
return part.getType()
except slapos.slap.ResourceNotReady:
return '(not ready)'
if promise_error_partition_list:
self.logger.info('Finished computer partitions.')
for partition, exc in promise_error_partition_list:
self.logger.info(' %s[%s]: %s', partition.getId(), getPartitionType(partition), exc)
# Return success value
if not clean_run_promise:
return SLAPGRID_PROMISE_FAIL
return SLAPGRID_SUCCESS
def _checkWaitProcessList(self, partition, state_list): def _checkWaitProcessList(self, partition, state_list):
wait_file = os.path.join(partition.instance_path, wait_file = os.path.join(partition.instance_path,
COMPUTER_PARTITION_WAIT_LIST_FILENAME) COMPUTER_PARTITION_WAIT_LIST_FILENAME)
......
...@@ -55,6 +55,7 @@ from slapos.grid import SlapObject ...@@ -55,6 +55,7 @@ from slapos.grid import SlapObject
from slapos.grid.SlapObject import WATCHDOG_MARK from slapos.grid.SlapObject import WATCHDOG_MARK
from slapos.manager.interface import IManager from slapos.manager.interface import IManager
from slapos.slap.slap import COMPUTER_PARTITION_REQUEST_LIST_TEMPLATE_FILENAME from slapos.slap.slap import COMPUTER_PARTITION_REQUEST_LIST_TEMPLATE_FILENAME
from slapos.slap.exception import ConnectionError
import slapos.grid.SlapObject import slapos.grid.SlapObject
from slapos import manager as slapmanager from slapos import manager as slapmanager
from slapos.util import dumps from slapos.util import dumps
...@@ -106,7 +107,32 @@ chmod 755 etc/service/daemon && ...@@ -106,7 +107,32 @@ chmod 755 etc/service/daemon &&
touch worked touch worked
""" """
PROMISE_CONTENT_TEMPLATE = """
from zope.interface import implementer
from slapos.grid.promise import interface
from slapos.grid.promise import GenericPromise
@implementer(interface.IPromise)
class RunPromise(GenericPromise):
def __init__(self, config):
super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=%(periodicity)s)
def sense(self):
%(content)s
if not %(success)s:
self.logger.error("failed")
else:
self.logger.info("success")
def anomaly(self):
return self._anomaly(result_count=2, failure_amount=%(failure_amount)s)
def test(self):
return self._test(result_count=1, failure_amount=%(failure_amount)s)
"""
class BasicMixin(object): class BasicMixin(object):
def setUp(self): def setUp(self):
...@@ -248,11 +274,10 @@ class TestBasicSlapgridCP(BasicMixin, unittest.TestCase): ...@@ -248,11 +274,10 @@ class TestBasicSlapgridCP(BasicMixin, unittest.TestCase):
os.mkdir(self.software_root) os.mkdir(self.software_root)
self.assertRaises(OSError, self.grid.processComputerPartitionList) self.assertRaises(OSError, self.grid.processComputerPartitionList)
@unittest.skip('which request handler here?')
def test_no_master(self): def test_no_master(self):
os.mkdir(self.software_root) os.mkdir(self.software_root)
os.mkdir(self.instance_root) os.mkdir(self.instance_root)
self.assertRaises(socket.error, self.grid.processComputerPartitionList) self.assertRaises(ConnectionError, self.grid.processComputerPartitionList)
class MasterMixin(BasicMixin): class MasterMixin(BasicMixin):
...@@ -385,9 +410,6 @@ class ComputerForTest(object): ...@@ -385,9 +410,6 @@ class ComputerForTest(object):
else: else:
return {'status_code': 500} return {'status_code': 500}
def setSoftwares(self): def setSoftwares(self):
""" """
Will set requested amount of software Will set requested amount of software
...@@ -491,6 +513,24 @@ class InstanceForTest(object): ...@@ -491,6 +513,24 @@ class InstanceForTest(object):
f.write(promise_content) f.write(promise_content)
os.chmod(promise, 0o777) os.chmod(promise, 0o777)
def setPluginPromise(self, promise_name, success=True, failure_count=1,
promise_content="", periodicity=0.03):
"""
This function will set plugin promise and return its path
"""
promise_dir = os.path.join(self.partition_path, 'etc', 'plugin')
if not os.path.isdir(promise_dir):
os.makedirs(promise_dir)
_promise_content = PROMISE_CONTENT_TEMPLATE % \
{'success': success,
'content': promise_content,
'failure_amount': failure_count,
'periodicity': periodicity}
with open(os.path.join(promise_dir, promise_name), 'w') as f:
f.write(_promise_content)
return os.path.join(promise_dir, promise_name)
def setCertificate(self, certificate_repository_path): def setCertificate(self, certificate_repository_path):
if not os.path.exists(certificate_repository_path): if not os.path.exists(certificate_repository_path):
os.mkdir(certificate_repository_path) os.mkdir(certificate_repository_path)
...@@ -505,7 +545,6 @@ class InstanceForTest(object): ...@@ -505,7 +545,6 @@ class InstanceForTest(object):
with open(self.key_file, 'w') as f: with open(self.key_file, 'w') as f:
f.write(self.key) f.write(self.key)
class SoftwareForTest(object): class SoftwareForTest(object):
""" """
Class to prepare and simulate software. Class to prepare and simulate software.
...@@ -1848,6 +1887,8 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase): ...@@ -1848,6 +1887,8 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase):
class TestSlapgridSoftwareRelease(MasterMixin, unittest.TestCase): class TestSlapgridSoftwareRelease(MasterMixin, unittest.TestCase):
fake_waiting_time = 0.05
def test_one_software_buildout_fail_is_correctly_logged(self): def test_one_software_buildout_fail_is_correctly_logged(self):
""" """
1. We set up a software using a corrupted buildout 1. We set up a software using a corrupted buildout
...@@ -1945,7 +1986,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase): ...@@ -1945,7 +1986,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase):
with httmock.HTTMock(computer.request_handler): with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0] instance = computer.instance_list[0]
instance.requested_state = 'started' instance.requested_state = 'started'
self.fake_waiting_time = 0.05
worked_file = os.path.join(instance.partition_path, 'succeed_worked') worked_file = os.path.join(instance.partition_path, 'succeed_worked')
succeed = textwrap.dedent("""\ succeed = textwrap.dedent("""\
#!/usr/bin/env sh #!/usr/bin/env sh
...@@ -1964,7 +2004,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase): ...@@ -1964,7 +2004,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase):
instance = computer.instance_list[0] instance = computer.instance_list[0]
instance.requested_state = 'started' instance.requested_state = 'started'
self.fake_waiting_time = 0.05
promise_path = os.path.join(instance.partition_path, 'etc', 'promise') promise_path = os.path.join(instance.partition_path, 'etc', 'promise')
os.makedirs(promise_path) os.makedirs(promise_path)
...@@ -1991,9 +2030,7 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase): ...@@ -1991,9 +2030,7 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase):
computer = ComputerForTest(self.software_root, self.instance_root) computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler): with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0] instance = computer.instance_list[0]
instance.requested_state = 'started' instance.requested_state = 'started'
self.fake_waiting_time = 0.05
promise_path = os.path.join(instance.partition_path, 'etc', 'promise') promise_path = os.path.join(instance.partition_path, 'etc', 'promise')
os.makedirs(promise_path) os.makedirs(promise_path)
...@@ -2019,8 +2056,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase): ...@@ -2019,8 +2056,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase):
instance = computer.instance_list[0] instance = computer.instance_list[0]
instance.requested_state = 'started' instance.requested_state = 'started'
self.fake_waiting_time = 0.05
for i in range(2): for i in range(2):
worked_file = os.path.join(instance.partition_path, 'succeed_%s_worked' % i) worked_file = os.path.join(instance.partition_path, 'succeed_%s_worked' % i)
succeed = textwrap.dedent("""\ succeed = textwrap.dedent("""\
...@@ -2041,7 +2076,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase): ...@@ -2041,7 +2076,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase):
with httmock.HTTMock(computer.request_handler): with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0] instance = computer.instance_list[0]
instance.requested_state = 'started' instance.requested_state = 'started'
self.fake_waiting_time = 0.05
for i in range(2): for i in range(2):
worked_file = os.path.join(instance.partition_path, 'promise_worked_%d' % i) worked_file = os.path.join(instance.partition_path, 'promise_worked_%d' % i)
...@@ -2070,7 +2104,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase): ...@@ -2070,7 +2104,6 @@ class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase):
with httmock.HTTMock(computer.request_handler): with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0] instance = computer.instance_list[0]
instance.requested_state = 'started' instance.requested_state = 'started'
self.fake_waiting_time = 0.05
for i in range(2): for i in range(2):
worked_file = os.path.join(instance.partition_path, 'promise_worked_%d' % i) worked_file = os.path.join(instance.partition_path, 'promise_worked_%d' % i)
lockfile = os.path.join(instance.partition_path, 'lock') lockfile = os.path.join(instance.partition_path, 'lock')
...@@ -3089,3 +3122,380 @@ exit 1 ...@@ -3089,3 +3122,380 @@ exit 1
self.assertEqual(self.manager.sequence, self.assertEqual(self.manager.sequence,
['software']) ['software'])
class TestBasicSlapgridPromise(BasicMixin, unittest.TestCase):
def test_no_software_root(self):
self.assertRaises(ConnectionError, self.grid.processPromiseList)
def test_no_instance_root(self):
os.mkdir(self.software_root)
self.assertRaises(ConnectionError, self.grid.processPromiseList)
def test_no_master(self):
os.mkdir(self.software_root)
os.mkdir(self.instance_root)
self.assertRaises(ConnectionError, self.grid.processPromiseList)
class TestSlapgridPromiseWithMaster(MasterMixin, unittest.TestCase):
fake_waiting_time = 0.05
def test_one_failing_promise(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'fail_worked')
fail = textwrap.dedent("""\
#!/usr/bin/env sh
touch "%s"
exit 127""" % worked_file)
instance.setPromise('fail', fail)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_PROMISE_FAIL)
self.assertTrue(os.path.isfile(worked_file))
def test_one_failing_plugin_promise(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'fail_worked_plugin')
fail = """import os
with open("%s", 'a'):
os.utime("%s", None)""" % (worked_file, worked_file)
instance.setPluginPromise(promise_name='fail.py', success=False, promise_content=fail)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_PROMISE_FAIL)
self.assertTrue(os.path.isfile(worked_file))
with open(os.path.join(instance.partition_path,
".slapgrid/promise/result/fail.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('failed', result["result"]["message"])
def test_one_succeeding_promise(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'succeed_worked')
succeed = textwrap.dedent("""\
#!/usr/bin/env sh
touch "%s"
exit 0""" % worked_file)
instance.setPromise('succeed', succeed)
self.assertEqual(self.grid.processPromiseList(), slapgrid.SLAPGRID_SUCCESS)
self.assertTrue(os.path.isfile(worked_file))
def test_one_succeeding_plugin_promise(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'succeed_worked_plugin')
succeed = """import os
with open("%s", 'a'):
os.utime("%s", None)""" % (worked_file, worked_file)
instance.setPluginPromise(promise_name='succeeding.py',
success=True, promise_content=succeed)
self.assertEqual(self.grid.processPromiseList(),
slapgrid.SLAPGRID_SUCCESS)
self.assertTrue(os.path.isfile(worked_file))
with open(os.path.join(instance.partition_path, ".slapgrid/promise/result/succeeding.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('success',
result["result"]["message"])
def test_stderr_has_been_sent(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
promise_path = os.path.join(instance.partition_path, 'etc', 'promise')
os.makedirs(promise_path)
succeed = os.path.join(promise_path, 'stderr_writer')
worked_file = os.path.join(instance.partition_path, 'stderr_worked')
with open(succeed, 'w') as f:
f.write(textwrap.dedent("""\
#!/usr/bin/env sh
touch "%s"
echo 'Error Promise 254554802' 1>&2
exit 127""" % worked_file))
os.chmod(succeed, 0o777)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_PROMISE_FAIL)
self.assertTrue(os.path.isfile(worked_file))
def test_stderr_has_been_sent_plugin(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'stderr_worked_plugin')
fail = """import os
with open("%s", 'a'):
os.utime("%s", None)
raise ValueError("FAILED 254554802")""" % (worked_file, worked_file)
instance.setPluginPromise(promise_name='stderr_fail.py', success=False, promise_content=fail)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_PROMISE_FAIL)
self.assertTrue(os.path.isfile(worked_file))
with open(os.path.join(instance.partition_path, ".slapgrid/promise/result/stderr_fail.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('FAILED 254554802', result["result"]["message"])
def test_timeout_works(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
promise_path = os.path.join(instance.partition_path, 'etc', 'promise')
os.makedirs(promise_path)
succeed = os.path.join(promise_path, 'timed_out_promise')
worked_file = os.path.join(instance.partition_path, 'timed_out_worked')
with open(succeed, 'w') as f:
f.write(textwrap.dedent("""\
#!/usr/bin/env sh
touch "%s"
sleep 5
exit 0""" % worked_file))
os.chmod(succeed, 0o777)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_PROMISE_FAIL)
self.assertTrue(os.path.isfile(worked_file))
def test_timeout_works_plugin(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'timed_out_worked_plugin')
fail = """import os
with open("%s", 'a'):
os.utime("%s", None)
import time
time.sleep(7)""" % (worked_file, worked_file)
instance.setPluginPromise(promise_name='timeout_fail.py', success=True, promise_content=fail)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_PROMISE_FAIL)
self.assertTrue(os.path.isfile(worked_file))
with open(os.path.join(instance.partition_path, ".slapgrid/promise/result/timeout_fail.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('Error: Promise timed out after 3 seconds',
result["result"]["message"])
def test_two_succeeding_promises(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
for i in range(2):
worked_file = os.path.join(instance.partition_path, 'succeed_%s_worked' % i)
succeed = textwrap.dedent("""\
#!/usr/bin/env sh
touch "%s"
exit 0""" % worked_file)
instance.setPromise('succeed_%s' % i, succeed)
self.assertEqual(self.grid.processPromiseList(), slapgrid.SLAPGRID_SUCCESS)
for i in range(2):
worked_file = os.path.join(instance.partition_path, 'succeed_%s_worked' % i)
self.assertTrue(os.path.isfile(worked_file))
def test_two_succeeding_plugin_promise(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'succeed_worked_plugin')
succeed = """import os
with open("%s", 'a'):
os.utime("%s", None)""" % (worked_file, worked_file)
instance.setPluginPromise(promise_name='succeeding.py',
success=True, promise_content=succeed)
worked2_file = os.path.join(instance.partition_path, 'succeed_worked2_plugin')
succeed = """import os
with open("%s", 'a'):
os.utime("%s", None)""" % (worked2_file, worked2_file)
instance.setPluginPromise(promise_name='succeeding2.py',
success=True, promise_content=succeed)
self.assertEqual(self.grid.processPromiseList(),
slapgrid.SLAPGRID_SUCCESS)
self.assertTrue(os.path.isfile(worked_file))
self.assertTrue(os.path.isfile(worked2_file))
with open(os.path.join(instance.partition_path, ".slapgrid/promise/result/succeeding2.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('success',
result["result"]["message"])
with open(os.path.join(instance.partition_path, ".slapgrid/promise/result/succeeding.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('success',
result["result"]["message"])
def test_one_succeeding_one_failing_promises(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
for i in range(2):
worked_file = os.path.join(instance.partition_path, 'promise_worked_%d' % i)
lockfile = os.path.join(instance.partition_path, 'lock')
promise = textwrap.dedent("""\
#!/usr/bin/env sh
touch "%(worked_file)s"
if [ ! -f %(lockfile)s ]
then
touch "%(lockfile)s"
exit 0
else
exit 127
fi""" % {
'worked_file': worked_file,
'lockfile': lockfile
})
instance.setPromise('promise_%s' % i, promise)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_PROMISE_FAIL)
def test_one_succeeding_one_failing_promises_plugin(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'succeed_worked_plugin')
succeed = """import os
with open("%s", 'a'):
os.utime("%s", None)""" % (worked_file, worked_file)
instance.setPluginPromise(promise_name='succeeding.py',
success=True, promise_content=succeed)
fail_file = os.path.join(instance.partition_path, 'fail_worked_plugin')
fail = """import os
with open("%s", 'a'):
os.utime("%s", None)""" % (fail_file, fail_file)
instance.setPluginPromise(promise_name='fail.py', success=False, promise_content=fail)
self.assertEqual(self.grid.processPromiseList(),
slapgrid.SLAPGRID_PROMISE_FAIL)
self.assertTrue(os.path.isfile(worked_file))
self.assertTrue(os.path.isfile(fail_file))
with open(os.path.join(instance.partition_path,
".slapgrid/promise/result/fail.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('failed', result["result"]["message"])
with open(os.path.join(instance.partition_path, ".slapgrid/promise/result/succeeding.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('success', result["result"]["message"])
def test_one_succeeding_one_timing_out_promises(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
for i in range(2):
worked_file = os.path.join(instance.partition_path, 'promise_worked_%d' % i)
lockfile = os.path.join(instance.partition_path, 'lock')
promise = textwrap.dedent("""\
#!/usr/bin/env sh
touch "%(worked_file)s"
if [ ! -f %(lockfile)s ]
then
touch "%(lockfile)s"
else
sleep 5
fi
exit 0""" % {
'worked_file': worked_file,
'lockfile': lockfile}
)
instance.setPromise('promise_%d' % i, promise)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_PROMISE_FAIL)
def test_one_succeeding_one_failing_promises_plugin(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'started'
worked_file = os.path.join(instance.partition_path, 'succeed_worked_plugin')
succeed = """import os
with open("%s", 'a'):
os.utime("%s", None)""" % (worked_file, worked_file)
instance.setPluginPromise(promise_name='succeeding.py',
success=True, promise_content=succeed)
timeout_file = os.path.join(instance.partition_path, 'timed_out_worked_plugin')
fail = """import os
with open("%s", 'a'):
os.utime("%s", None)
import time
time.sleep(7)""" % (timeout_file, timeout_file)
instance.setPluginPromise(promise_name='timeout_fail.py', success=True, promise_content=fail)
self.assertEqual(self.grid.processPromiseList(),
slapgrid.SLAPGRID_PROMISE_FAIL)
self.assertTrue(os.path.isfile(worked_file))
self.assertTrue(os.path.isfile(timeout_file))
with open(os.path.join(instance.partition_path, ".slapgrid/promise/result/succeeding.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('success', result["result"]["message"])
with open(os.path.join(instance.partition_path, ".slapgrid/promise/result/timeout_fail.status.json"), "r") as f:
result = json.loads(f.read())
self.assertEqual('Error: Promise timed out after 3 seconds',
result["result"]["message"])
def test_promise_notrun_if_partition_stopped(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'stopped'
promise_file = os.path.join(instance.partition_path, 'promise_ran')
promise = textwrap.dedent("""\
#!/usr/bin/env sh
touch "%s"
exit 127""" % promise_file)
instance.setPromise('promise_script', promise)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_SUCCESS)
self.assertFalse(os.path.exists(promise_file))
def test_promise_notrun_if_partition_stopped_plugin(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.requested_state = 'stopped'
worked_file = os.path.join(instance.partition_path, 'fail_worked_plugin')
fail = """import os
with open("%s", 'a'):
os.utime("%s", None)""" % (worked_file, worked_file)
instance.setPluginPromise(promise_name='fail.py', success=False, promise_content=fail)
self.assertEqual(self.grid.processPromiseList(),
slapos.grid.slapgrid.SLAPGRID_SUCCESS)
self.assertFalse(os.path.isfile(worked_file))
self.assertFalse(os.path.isfile(os.path.join(instance.partition_path,
".slapgrid/promise/result/fail.status.json")))
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