Commit 4337b2fa authored by Gabriel Monnerat's avatar Gabriel Monnerat

merge 'master' into slave_instance

parents dc812047 1eddcede
...@@ -74,7 +74,13 @@ graph = {}\n ...@@ -74,7 +74,13 @@ graph = {}\n
# Get root software instance and create initial graph\n # Get root software instance and create initial graph\n
predecessor_software_instance = software_instance\n predecessor_software_instance = software_instance\n
while (predecessor_software_instance is not None):\n while (predecessor_software_instance is not None):\n
graph[predecessor_software_instance.getUid()] = predecessor_software_instance.getPredecessorUidList()\n predecessor_software_instance_pred_uid_list = predecessor_software_instance.getPredecessorUidList()\n
graph[predecessor_software_instance.getUid()] = predecessor_software_instance_pred_uid_list\n
# as this walking is not fetching all instances fill predecessors into graph, in order to have\n
# "nearly" complete representation\n
for uid in predecessor_software_instance_pred_uid_list:\n
if uid not in graph:\n
graph[uid] = []\n
root_software_instance = predecessor_software_instance\n root_software_instance = predecessor_software_instance\n
predecessor_software_instance = predecessor_software_instance.getPredecessorRelatedValue(\n predecessor_software_instance = predecessor_software_instance.getPredecessorRelatedValue(\n
portal_type="Software Instance")\n portal_type="Software Instance")\n
...@@ -160,9 +166,9 @@ if not request_software_instance.getUid() in graph:\n ...@@ -160,9 +166,9 @@ if not request_software_instance.getUid() in graph:\n
# update graph to reflect requested operation\n # update graph to reflect requested operation\n
graph[software_instance.getUid()] = software_instance.getPredecessorUidList() + [request_software_instance.getUid()]\n graph[software_instance.getUid()] = software_instance.getPredecessorUidList() + [request_software_instance.getUid()]\n
\n \n
# check if all elements are still connected\n # check if all elements are still connected and if there is no cycle\n
software_instance.checkNotCyclic(graph)\n
software_instance.checkConnected(graph, root_software_instance.getUid())\n software_instance.checkConnected(graph, root_software_instance.getUid())\n
software_instance.checkNotCyclic(graph)\n
\n \n
software_instance.edit(\n software_instance.edit(\n
predecessor_list=predecessor_list,\n predecessor_list=predecessor_list,\n
......
...@@ -3149,6 +3149,9 @@ class TestVifibSlapWebService(testVifibMixin): ...@@ -3149,6 +3149,9 @@ class TestVifibSlapWebService(testVifibMixin):
def stepCheckSoftwareInstanceAndRelatedComputerPartition(self, def stepCheckSoftwareInstanceAndRelatedComputerPartition(self,
sequence, **kw): sequence, **kw):
self.stepCheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck(sequence, **kw) self.stepCheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck(sequence, **kw)
software_instance_uid = sequence['software_instance_uid']
software_instance = self.portal.portal_catalog.getResultValue(
uid=software_instance_uid)
self._checkSoftwareInstanceAndRelatedPartition(software_instance) self._checkSoftwareInstanceAndRelatedPartition(software_instance)
def stepCheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck(self, def stepCheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck(self,
...@@ -9220,7 +9223,6 @@ class TestVifibSlapWebService(testVifibMixin): ...@@ -9220,7 +9223,6 @@ class TestVifibSlapWebService(testVifibMixin):
sequence, **kw): sequence, **kw):
software_instance = self.portal.portal_catalog.getResultValue( software_instance = self.portal.portal_catalog.getResultValue(
uid = sequence['software_instance_uid']) uid = sequence['software_instance_uid'])
requested_reference = sequence['requested_reference']
from erp5.document.SoftwareInstance import DisconnectedSoftwareTree from erp5.document.SoftwareInstance import DisconnectedSoftwareTree
self.assertRaises(DisconnectedSoftwareTree, self.assertRaises(DisconnectedSoftwareTree,
software_instance.requestSoftwareInstance, software_instance.requestSoftwareInstance,
...@@ -9370,7 +9372,6 @@ class TestVifibSlapWebService(testVifibMixin): ...@@ -9370,7 +9372,6 @@ class TestVifibSlapWebService(testVifibMixin):
sequence, **kw): sequence, **kw):
software_instance = self.portal.portal_catalog.getResultValue( software_instance = self.portal.portal_catalog.getResultValue(
uid = sequence['software_instance_uid']) uid = sequence['software_instance_uid'])
requested_reference = sequence['requested_reference']
from erp5.document.SoftwareInstance import CyclicSoftwareTree from erp5.document.SoftwareInstance import CyclicSoftwareTree
self.assertRaises(CyclicSoftwareTree, self.assertRaises(CyclicSoftwareTree,
software_instance.requestSoftwareInstance, software_instance.requestSoftwareInstance,
...@@ -9520,7 +9521,6 @@ class TestVifibSlapWebService(testVifibMixin): ...@@ -9520,7 +9521,6 @@ class TestVifibSlapWebService(testVifibMixin):
sequence, **kw): sequence, **kw):
software_instance = self.portal.portal_catalog.getResultValue( software_instance = self.portal.portal_catalog.getResultValue(
uid = sequence['software_instance_uid']) uid = sequence['software_instance_uid'])
requested_reference = sequence['requested_reference']
self.assertRaises(ValueError, self.assertRaises(ValueError,
software_instance.requestSoftwareInstance, software_instance.requestSoftwareInstance,
software_release=sequence['software_release_uri'], software_release=sequence['software_release_uri'],
...@@ -9764,7 +9764,7 @@ class TestVifibSlapWebService(testVifibMixin): ...@@ -9764,7 +9764,7 @@ class TestVifibSlapWebService(testVifibMixin):
from erp5.document.SoftwareInstance import CyclicSoftwareTree from erp5.document.SoftwareInstance import CyclicSoftwareTree
self.assertRaises(CyclicSoftwareTree, self.checkNotCyclic, graph) self.assertRaises(CyclicSoftwareTree, self.checkNotCyclic, graph)
def test_si_tree_simple_list_cyclic(self): def test_si_tree_simple_list_cyclic_non_root(self):
"""Graph of cyclic list is cyclic """Graph of cyclic list is cyclic
B->C->D->A-\ B->C->D->A-\
...@@ -9862,7 +9862,7 @@ class TestVifibSlapWebService(testVifibMixin): ...@@ -9862,7 +9862,7 @@ class TestVifibSlapWebService(testVifibMixin):
def stepRequestCredentialFromWebSite(self, sequence, **kw): def stepRequestCredentialFromWebSite(self, sequence, **kw):
sequence['web_user'] = '%s.%s' % (self.id(), random()) sequence['web_user'] = '%s.%s' % (self.id(), random())
result = self.portal.ERP5Site_newCredentialRequest(\ self.portal.ERP5Site_newCredentialRequest(\
first_name='Homer', first_name='Homer',
last_name='Simpson', last_name='Simpson',
reference=sequence['web_user'], reference=sequence['web_user'],
......
...@@ -35,6 +35,7 @@ if sys.version_info < (2, 6): ...@@ -35,6 +35,7 @@ if sys.version_info < (2, 6):
import socket import socket
import subprocess import subprocess
import traceback import traceback
import time
#from time import strftime #from time import strftime
from SlapObject import Software, Partition, WrongPermissionError, \ from SlapObject import Software, Partition, WrongPermissionError, \
...@@ -105,6 +106,9 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple): ...@@ -105,6 +106,9 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple):
help="Enables console output and live output from subcommands.") help="Enables console output and live output from subcommands.")
parser.add_argument("-v", "--verbose", action="store_true", default=False, parser.add_argument("-v", "--verbose", action="store_true", default=False,
help="Be verbose.") help="Be verbose.")
parser.add_argument("--promise-timeout",
type=int, default=3,
help="Promise timeout in seconds.")
parser.add_argument("configuration_file", nargs=1, type=argparse.FileType(), parser.add_argument("configuration_file", nargs=1, type=argparse.FileType(),
help="SlapOS configuration file.") help="SlapOS configuration file.")
...@@ -198,7 +202,8 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple): ...@@ -198,7 +202,8 @@ def parseArgumentTupleAndReturnSlapgridObject(*argument_tuple):
master_ca_file=master_ca_file, master_ca_file=master_ca_file,
certificate_repository_path=certificate_repository_path, certificate_repository_path=certificate_repository_path,
console=option_dict['console'], console=option_dict['console'],
buildout=option_dict.get('buildout')), buildout=option_dict.get('buildout'),
promise_timeout=option_dict['promise_timeout']),
option_dict]) option_dict])
...@@ -267,7 +272,8 @@ class Slapgrid(object): ...@@ -267,7 +272,8 @@ class Slapgrid(object):
cert_file=None, cert_file=None,
master_ca_file=None, master_ca_file=None,
certificate_repository_path=None, certificate_repository_path=None,
console=False): console=False,
promise_timeout=3):
"""Makes easy initialisation of class parameters""" """Makes easy initialisation of class parameters"""
# Parses arguments # Parses arguments
self.software_root = os.path.abspath(software_root) self.software_root = os.path.abspath(software_root)
...@@ -294,6 +300,7 @@ class Slapgrid(object): ...@@ -294,6 +300,7 @@ class Slapgrid(object):
os.path.join(self.instance_etc_directory, 'supervisord.conf.d') os.path.join(self.instance_etc_directory, 'supervisord.conf.d')
self.console = console self.console = console
self.buildout = buildout self.buildout = buildout
self.promise_timeout = promise_timeout
def checkEnvironmentAndCreateStructure(self): def checkEnvironmentAndCreateStructure(self):
"""Checks for software_root and instance_root existence, then creates """Checks for software_root and instance_root existence, then creates
...@@ -452,6 +459,53 @@ class Slapgrid(object): ...@@ -452,6 +459,53 @@ class Slapgrid(object):
exception = traceback.format_exc() exception = traceback.format_exc()
logger.error(exception) logger.error(exception)
computer_partition.error(exception) computer_partition.error(exception)
# Promises
instance_path = os.path.join(self.instance_root,
computer_partition.getId())
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
# Get the list of promises
promise_dir = os.path.join(instance_path, 'etc', 'promise')
if os.path.exists(promise_dir) and os.path.isdir(promise_dir):
cwd = instance_path
promises_list = os.listdir(promise_dir)
# Check whether every promise is kept
for promise in promises_list:
command = os.path.join(promise_dir, promise)
kw = dict()
if not self.console:
kw.update(stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process_handler = SlapPopen(command,
preexec_fn=lambda: dropPrivileges(uid, gid),
cwd=cwd,
env=None, **kw)
time.sleep(self.promise_timeout)
promise = os.path.basename(command)
if process_handler.poll() is None:
process_handler.kill()
computer_partition.error("The promise %r timed out" % promise)
elif process_handler.poll() != 0:
stderr = process_handler.communicate()[1]
if stderr is None:
stderr = 'No error output from %r.' % promise
computer_partition.error(stderr)
logger.info("Finished computer partitions...") logger.info("Finished computer partitions...")
return clean_run return clean_run
......
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
"""Mocked httplib """Mocked httplib
""" """
from urlparse import urlparse
__all__ = [] __all__ = []
def log(message): def log(message):
...@@ -83,7 +81,6 @@ class HTTPSConnection(HTTPConnection): ...@@ -83,7 +81,6 @@ class HTTPSConnection(HTTPConnection):
source_address=None): source_address=None):
super().__init__(self, host, port, strict, timeout, super().__init__(self, host, port, strict, timeout,
source_address) source_address)
pass
class HTTPResponse(object): class HTTPResponse(object):
......
...@@ -79,12 +79,51 @@ class MasterMixin(BasicMixin): ...@@ -79,12 +79,51 @@ class MasterMixin(BasicMixin):
setattr(httplib, name, original_value) setattr(httplib, name, original_value)
del self.saved_httplib del self.saved_httplib
def _mock_sleep(self):
self.fake_waiting_time = None
self.real_sleep = time.sleep
def mocked_sleep(secs):
if self.fake_waiting_time is not None:
secs = self.fake_waiting_time
self.real_sleep(secs)
time.sleep = mocked_sleep
def _unmock_sleep(self):
time.sleep = self.real_sleep
def _create_instance(self, name=0):
if not os.path.isdir(self.instance_root):
os.mkdir(self.instance_root)
partition_path = os.path.join(self.instance_root, str(name))
os.mkdir(partition_path, 0750)
return partition_path
def _bootstrap(self):
os.mkdir(self.software_root)
software_hash = slapos.grid.utils.getSoftwareUrlHash('http://sr/')
srdir = os.path.join(self.software_root, software_hash)
os.mkdir(srdir)
open(os.path.join(srdir, 'template.cfg'), 'w').write(
"""[buildout]""")
srbindir = os.path.join(srdir, 'bin')
os.mkdir(srbindir)
open(os.path.join(srbindir, 'buildout'), 'w').write("""#!/bin/sh
touch worked""")
os.chmod(os.path.join(srbindir, 'buildout'), 0755)
return software_hash
def setUp(self): def setUp(self):
self._patchHttplib() self._patchHttplib()
self._mock_sleep()
BasicMixin.setUp(self) BasicMixin.setUp(self)
def tearDown(self): def tearDown(self):
self._unpatchHttplib() self._unpatchHttplib()
self._unmock_sleep()
BasicMixin.tearDown(self) BasicMixin.tearDown(self)
class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase): class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
...@@ -113,9 +152,9 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase): ...@@ -113,9 +152,9 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
def test_one_partition(self): def test_one_partition(self):
def server_response(self, path, method, body, header): def server_response(self, path, method, body, header):
parsed_url = urlparse.urlparse('/' + path) parsed_url = urlparse.urlparse(path.lstrip('/'))
parsed_qs = urlparse.parse_qs(parsed_url.query) parsed_qs = urlparse.parse_qs(parsed_url.query)
if parsed_url.path == '/getComputerInformation' and \ if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs: 'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id']) slap_computer = slapos.slap.Computer(parsed_qs['computer_id'])
slap_computer._software_release_list = [] slap_computer._software_release_list = []
...@@ -158,9 +197,9 @@ touch worked""") ...@@ -158,9 +197,9 @@ touch worked""")
def test_one_partition_started(self): def test_one_partition_started(self):
def server_response(self, path, method, body, header): def server_response(self, path, method, body, header):
parsed_url = urlparse.urlparse('/' + path) parsed_url = urlparse.urlparse(path.lstrip('/'))
parsed_qs = urlparse.parse_qs(parsed_url.query) parsed_qs = urlparse.parse_qs(parsed_url.query)
if parsed_url.path == '/getComputerInformation' and \ if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs: 'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id']) slap_computer = slapos.slap.Computer(parsed_qs['computer_id'])
slap_computer._software_release_list = [] slap_computer._software_release_list = []
...@@ -215,9 +254,9 @@ chmod 755 etc/run/wrapper ...@@ -215,9 +254,9 @@ chmod 755 etc/run/wrapper
def test_one_partition_started_stopped(self): def test_one_partition_started_stopped(self):
def server_response(self, path, method, body, header): def server_response(self, path, method, body, header):
parsed_url = urlparse.urlparse('/' + path) parsed_url = urlparse.urlparse(path.lstrip('/'))
parsed_qs = urlparse.parse_qs(parsed_url.query) parsed_qs = urlparse.parse_qs(parsed_url.query)
if parsed_url.path == '/getComputerInformation' and \ if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs: 'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id']) slap_computer = slapos.slap.Computer(parsed_qs['computer_id'])
slap_computer._software_release_list = [] slap_computer._software_release_list = []
...@@ -282,9 +321,9 @@ chmod 755 etc/run/wrapper ...@@ -282,9 +321,9 @@ chmod 755 etc/run/wrapper
[software_hash]) [software_hash])
def server_response(self, path, method, body, header): def server_response(self, path, method, body, header):
parsed_url = urlparse.urlparse('/' + path) parsed_url = urlparse.urlparse(path.lstrip('/'))
parsed_qs = urlparse.parse_qs(parsed_url.query) parsed_qs = urlparse.parse_qs(parsed_url.query)
if parsed_url.path == '/getComputerInformation' and \ if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs: 'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id']) slap_computer = slapos.slap.Computer(parsed_qs['computer_id'])
slap_computer._software_release_list = [] slap_computer._software_release_list = []
...@@ -318,9 +357,9 @@ chmod 755 etc/run/wrapper ...@@ -318,9 +357,9 @@ chmod 755 etc/run/wrapper
def test_one_partition_stopped_started(self): def test_one_partition_stopped_started(self):
def server_response(self, path, method, body, header): def server_response(self, path, method, body, header):
parsed_url = urlparse.urlparse('/' + path) parsed_url = urlparse.urlparse(path.lstrip('/'))
parsed_qs = urlparse.parse_qs(parsed_url.query) parsed_qs = urlparse.parse_qs(parsed_url.query)
if parsed_url.path == '/getComputerInformation' and \ if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs: 'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id']) slap_computer = slapos.slap.Computer(parsed_qs['computer_id'])
slap_computer._software_release_list = [] slap_computer._software_release_list = []
...@@ -366,9 +405,9 @@ chmod 755 etc/run/wrapper ...@@ -366,9 +405,9 @@ chmod 755 etc/run/wrapper
[software_hash]) [software_hash])
def server_response(self, path, method, body, header): def server_response(self, path, method, body, header):
parsed_url = urlparse.urlparse('/' + path) parsed_url = urlparse.urlparse(path.lstrip('/'))
parsed_qs = urlparse.parse_qs(parsed_url.query) parsed_qs = urlparse.parse_qs(parsed_url.query)
if parsed_url.path == '/getComputerInformation' and \ if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs: 'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id']) slap_computer = slapos.slap.Computer(parsed_qs['computer_id'])
slap_computer._software_release_list = [] slap_computer._software_release_list = []
...@@ -401,3 +440,411 @@ chmod 755 etc/run/wrapper ...@@ -401,3 +440,411 @@ chmod 755 etc/run/wrapper
break break
time.sleep(0.2) time.sleep(0.2)
self.assertTrue('Working' in open(wrapper_log, 'r').read()) self.assertTrue('Working' in open(wrapper_log, 'r').read())
class TestSlapgridCPWithMasterPromise(MasterMixin, unittest.TestCase):
def test_one_failing_promise(self):
def server_response(self_httplib, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/'))
if method == 'GET':
parsed_qs = urlparse.parse_qs(parsed_url.query)
else:
parsed_qs = urlparse.parse_qs(body)
if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'][0])
slap_computer._software_release_list = []
partition = slapos.slap.ComputerPartition(parsed_qs['computer_id'][0],
'0')
partition._need_modification = True
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'stopped'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'softwareInstanceError' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.error = True
self.assertEqual(parsed_qs['computer_partition_id'][0], '0')
return (200, {}, '')
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
self.fake_waiting_time = 0.2
self.error = False
instance_path = self._create_instance('0')
software_hash = self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise')
os.makedirs(promise_path)
fail = os.path.join(promise_path, 'fail')
worked_file = os.path.join(instance_path, 'fail_worked')
with open(fail, 'w') as f:
f.write("""#!/usr/bin/env sh
touch "%(worked_file)s"
exit 127""" % {'worked_file': worked_file})
os.chmod(fail, 0777)
self.assertTrue(self.grid.processComputerPartitionList())
self.assertTrue(os.path.isfile(worked_file))
self.assertTrue(self.error)
def test_one_succeeding_promise(self):
def server_response(self_httplib, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/'))
if method == 'GET':
parsed_qs = urlparse.parse_qs(parsed_url.query)
else:
parsed_qs = urlparse.parse_qs(body)
if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'][0])
slap_computer._software_release_list = []
partition = slapos.slap.ComputerPartition(parsed_qs['computer_id'][0],
'0')
partition._need_modification = True
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'stopped'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'softwareInstanceError' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.error = True
raise AssertionError('ComputerPartition.error was raised')
return (200, {}, '')
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
self.fake_waiting_time = 0.2
self.error = False
instance_path = self._create_instance('0')
software_hash = self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise')
os.makedirs(promise_path)
succeed = os.path.join(promise_path, 'succeed')
worked_file = os.path.join(instance_path, 'succeed_worked')
with open(succeed, 'w') as f:
f.write("""#!/usr/bin/env sh
touch "%(worked_file)s"
exit 0""" % {'worked_file': worked_file})
os.chmod(succeed, 0777)
self.assertTrue(self.grid.processComputerPartitionList())
self.assertTrue(os.path.isfile(worked_file))
self.assertFalse(self.error)
def test_stderr_has_been_sent(self):
def server_response(self_httplib, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/'))
if method == 'GET':
parsed_qs = urlparse.parse_qs(parsed_url.query)
else:
parsed_qs = urlparse.parse_qs(body)
if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'][0])
slap_computer._software_release_list = []
partition = slapos.slap.ComputerPartition(parsed_qs['computer_id'][0],
'0')
partition._need_modification = True
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'stopped'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'softwareInstanceError' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.error = True
self.assertEqual(parsed_qs['computer_partition_id'][0], '0')
# XXX: Hardcoded dropPrivileges line ignore
self.error_log = '\n'.join([line for line in parsed_qs['error_log'][0].splitlines()
if 'dropPrivileges' not in line])
# end XXX
return (200, {}, '')
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
self.fake_waiting_time = 0.5
self.error = False
instance_path = self._create_instance('0')
software_hash = self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise')
os.makedirs(promise_path)
succeed = os.path.join(promise_path, 'stderr_writer')
worked_file = os.path.join(instance_path, 'stderr_worked')
with open(succeed, 'w') as f:
f.write("""#!/usr/bin/env sh
touch "%(worked_file)s"
echo -n Error 1>&2
exit 127""" % {'worked_file': worked_file})
os.chmod(succeed, 0777)
self.assertTrue(self.grid.processComputerPartitionList())
self.assertTrue(os.path.isfile(worked_file))
self.assertEqual(self.error_log, 'Error')
self.assertTrue(self.error)
def test_timeout_works(self):
def server_response(self_httplib, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/'))
if method == 'GET':
parsed_qs = urlparse.parse_qs(parsed_url.query)
else:
parsed_qs = urlparse.parse_qs(body)
if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'][0])
slap_computer._software_release_list = []
partition = slapos.slap.ComputerPartition(parsed_qs['computer_id'][0],
'0')
partition._need_modification = True
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'stopped'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'softwareInstanceError' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.error = True
self.assertEqual(parsed_qs['computer_partition_id'][0], '0')
# XXX: Hardcoded dropPrivileges line ignore
error_log = '\n'.join([line for line in parsed_qs['error_log'][0].splitlines()
if 'dropPrivileges' not in line])
# end XXX
self.assertEqual(error_log, 'The promise %r timed out' % 'timed_out_promise')
return (200, {}, '')
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
self.fake_waiting_time = 0.2
self.error = False
instance_path = self._create_instance('0')
software_hash = self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise')
os.makedirs(promise_path)
succeed = os.path.join(promise_path, 'timed_out_promise')
worked_file = os.path.join(instance_path, 'timed_out_worked')
with open(succeed, 'w') as f:
f.write("""#!/usr/bin/env sh
touch "%(worked_file)s"
sleep 5
exit 0""" % {'worked_file': worked_file})
os.chmod(succeed, 0777)
self.assertTrue(self.grid.processComputerPartitionList())
self.assertTrue(os.path.isfile(worked_file))
self.assertTrue(self.error)
def test_two_succeeding_promises(self):
def server_response(self_httplib, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/'))
if method == 'GET':
parsed_qs = urlparse.parse_qs(parsed_url.query)
else:
parsed_qs = urlparse.parse_qs(body)
if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'][0])
slap_computer._software_release_list = []
partition = slapos.slap.ComputerPartition(parsed_qs['computer_id'][0],
'0')
partition._need_modification = True
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'stopped'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'softwareInstanceError' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.error = True
raise AssertionError('ComputerPartition.error was raised')
return (200, {}, '')
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
self.fake_waiting_time = 0.2
self.error = False
instance_path = self._create_instance('0')
software_hash = self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise')
os.makedirs(promise_path)
succeed = os.path.join(promise_path, 'succeed')
worked_file = os.path.join(instance_path, 'succeed_worked')
with open(succeed, 'w') as f:
f.write("""#!/usr/bin/env sh
touch "%(worked_file)s"
exit 0""" % {'worked_file': worked_file})
os.chmod(succeed, 0777)
succeed_2 = os.path.join(promise_path, 'succeed_2')
worked_file_2 = os.path.join(instance_path, 'succeed_2_worked')
with open(succeed_2, 'w') as f:
f.write("""#!/usr/bin/env sh
touch "%(worked_file)s"
exit 0""" % {'worked_file': worked_file_2})
os.chmod(succeed_2, 0777)
self.assertTrue(self.grid.processComputerPartitionList())
self.assertTrue(os.path.isfile(worked_file))
self.assertTrue(os.path.isfile(worked_file_2))
self.assertFalse(self.error)
def test_one_succeeding_one_failing_promises(self):
def server_response(self_httplib, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/'))
if method == 'GET':
parsed_qs = urlparse.parse_qs(parsed_url.query)
else:
parsed_qs = urlparse.parse_qs(body)
if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'][0])
slap_computer._software_release_list = []
partition = slapos.slap.ComputerPartition(parsed_qs['computer_id'][0],
'0')
partition._need_modification = True
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'stopped'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'softwareInstanceError' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.error += 1
self.assertEqual(parsed_qs['computer_partition_id'][0], '0')
return (200, {}, '')
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
self.fake_waiting_time = 0.2
self.error = 0
instance_path = self._create_instance('0')
software_hash = self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise')
os.makedirs(promise_path)
promises_files = []
for i in range(2):
promise = os.path.join(promise_path, 'promise_%d')
promises_files.append(promise)
worked_file = os.path.join(instance_path, 'promise_worked_%d')
lockfile = os.path.join(instance_path, 'lock')
with open(promise, 'w') as f:
f.write("""#!/usr/bin/env sh
touch "%(worked_file)s"
[[ ! -f "%(lockfile)s" ]] || { touch "%(lockfile)s" ; exit 127 }
exit 0""" % {'worked_file': worked_file, 'lockfile': lockfile})
os.chmod(promise, 0777)
self.assertTrue(self.grid.processComputerPartitionList())
for file_ in promises_files:
self.assertTrue(os.path.isfile(file_))
self.assertEquals(self.error, 1)
def test_one_succeeding_one_timing_out_promises(self):
def server_response(self_httplib, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/'))
if method == 'GET':
parsed_qs = urlparse.parse_qs(parsed_url.query)
else:
parsed_qs = urlparse.parse_qs(body)
if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'][0])
slap_computer._software_release_list = []
partition = slapos.slap.ComputerPartition(parsed_qs['computer_id'][0],
'0')
partition._need_modification = True
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'stopped'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'softwareInstanceError' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.error += 1
self.assertEqual(parsed_qs['computer_partition_id'][0], '0')
return (200, {}, '')
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
self.fake_waiting_time = 0.2
self.error = 0
instance_path = self._create_instance('0')
software_hash = self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise')
os.makedirs(promise_path)
promises_files = []
for i in range(2):
promise = os.path.join(promise_path, 'promise_%d')
promises_files.append(promise)
worked_file = os.path.join(instance_path, 'promise_worked_%d')
lockfile = os.path.join(instance_path, 'lock')
with open(promise, 'w') as f:
f.write("""#!/usr/bin/env sh
touch "%(worked_file)s"
[[ ! -f "%(lockfile)s" ]] || { touch "%(lockfile)s" ; sleep 5 }
exit 0""" % {'worked_file': worked_file, 'lockfile': lockfile})
os.chmod(promise, 0777)
self.assertTrue(self.grid.processComputerPartitionList())
for file_ in promises_files:
self.assertTrue(os.path.isfile(file_))
self.assertEquals(self.error, 1)
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