Commit 3ee6542b authored by Cédric Le Ninivin's avatar Cédric Le Ninivin

Added test on multi partitions

parent 1a283a07
...@@ -54,12 +54,12 @@ class BasicMixin: ...@@ -54,12 +54,12 @@ class BasicMixin:
def setUp(self): def setUp(self):
self._tempdir = tempfile.mkdtemp() self._tempdir = tempfile.mkdtemp()
self.software_root = os.path.join(self._tempdir, 'software')
self.instance_root = os.path.join(self._tempdir, 'instance')
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
self.setSlapgrid() self.setSlapgrid()
def setSlapgrid(self, develop=False): def setSlapgrid(self, develop=False):
self.software_root = os.path.join(self._tempdir, 'software')
self.instance_root = os.path.join(self._tempdir, 'instance')
if getattr(self, 'master_url', None) is None: if getattr(self, 'master_url', None) is None:
self.master_url = 'http://127.0.0.1:80/' self.master_url = 'http://127.0.0.1:80/'
self.computer_id = 'computer' self.computer_id = 'computer'
...@@ -219,34 +219,49 @@ touch worked""") ...@@ -219,34 +219,49 @@ touch worked""")
class ComputerForTest: class ComputerForTest:
"""
Class to set up environment for tests setting instance, software
and server response
"""
def __init__(self, def __init__(self,
software_root, software_root,
instance_root, instance_root,
instance_amount=1, instance_amount=1,
software_amount=1): software_amount=1):
"""
Will set up instances, software and sequence
"""
self.sequence = []
self.instance_amount = instance_amount self.instance_amount = instance_amount
self.software_amount = software_amount self.software_amount = software_amount
self.software_root = software_root self.software_root = software_root
self.instance_root = instance_root self.instance_root = instance_root
self.sequence = []
self.setSoftwares() self.setSoftwares()
self.setInstances() self.setInstances()
def setSoftwares(self):
"""
Will set requested amount of software
"""
self.software_list = range(0,self.software_amount)
for i in self.software_list:
name = str(i)
self.software_list[i] = SoftwareForTest(self.software_root, name=name)
def setInstances(self): def setInstances(self):
"""
Will set requested amount of instance giving them by default first software
"""
self.instance_list = range(0, self.instance_amount) self.instance_list = range(0, self.instance_amount)
for i in self.instance_list: for i in self.instance_list:
name = str(i) name = str(i)
self.instance_list[i] = InstanceForTest(self.instance_root, name=name, self.instance_list[i] = InstanceForTest(self.instance_root, name=name,
software=self.software_list[0]) software=self.software_list[0])
def setSoftwares(self):
self.software_list = range(0,self.software_amount)
for i in self.software_list:
name = str(i)
self.software_list[i] = SoftwareForTest(self.software_root, name=name)
print self.software_list
def getComputer (self, computer_id): def getComputer (self, computer_id):
"""
Will return current requested state of computer
"""
slap_computer = slapos.slap.Computer(computer_id) slap_computer = slapos.slap.Computer(computer_id)
slap_computer._software_release_list = [] slap_computer._software_release_list = []
slap_computer._computer_partition_list = [] slap_computer._computer_partition_list = []
...@@ -256,6 +271,11 @@ class ComputerForTest: ...@@ -256,6 +271,11 @@ class ComputerForTest:
return slap_computer return slap_computer
def getServerResponse(self): def getServerResponse(self):
"""
Define _callback.
Will register global sequence of message, sequence by partition
and error and error message by partition
"""
def server_response(self_httplib, path, method, body, header): def server_response(self_httplib, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/')) parsed_url = urlparse.urlparse(path.lstrip('/'))
self.sequence.append(parsed_url.path) self.sequence.append(parsed_url.path)
...@@ -279,6 +299,9 @@ class ComputerForTest: ...@@ -279,6 +299,9 @@ class ComputerForTest:
instance.state = 'stopped' instance.state = 'stopped'
return (200, {}, '') return (200, {}, '')
if parsed_url.path == 'softwareInstanceError': if parsed_url.path == 'softwareInstanceError':
instance.error_log = '\n'.join([line for line \
in parsed_qs['error_log'][0].splitlines()
if 'dropPrivileges' not in line])
instance.error = True instance.error = True
return (200, {}, '') return (200, {}, '')
else: else:
...@@ -292,10 +315,11 @@ class InstanceForTest: ...@@ -292,10 +315,11 @@ class InstanceForTest:
""" """
def __init__(self, instance_root, name, software): def __init__(self, instance_root, name, software):
self.instance_root = instance_root self.instance_root = instance_root
self.software = software
self.requested_state = 'stopped' self.requested_state = 'stopped'
self.sate = None self.state = None
self.error = False self.error = False
self.software = software self.error_log = None
self.sequence = [] self.sequence = []
self.name = name self.name = name
if not os.path.isdir(self.instance_root): if not os.path.isdir(self.instance_root):
...@@ -305,6 +329,9 @@ class InstanceForTest: ...@@ -305,6 +329,9 @@ class InstanceForTest:
self.timestamp = None self.timestamp = None
def getInstance (self, computer_id): def getInstance (self, computer_id):
"""
Will return current requested state of instance
"""
partition = slapos.slap.ComputerPartition(computer_id, self.name) partition = slapos.slap.ComputerPartition(computer_id, self.name)
partition._software_release_document = self.getSoftwareRelease() partition._software_release_document = self.getSoftwareRelease()
partition._requested_state = self.requested_state partition._requested_state = self.requested_state
...@@ -313,18 +340,28 @@ class InstanceForTest: ...@@ -313,18 +340,28 @@ class InstanceForTest:
return partition return partition
def getSoftwareRelease (self): def getSoftwareRelease (self):
"""
Return software release for Instance
"""
sr = slapos.slap.SoftwareRelease() sr = slapos.slap.SoftwareRelease()
sr._software_release = self.software.name sr._software_release = self.software.name
return sr return sr
class SoftwareForTest: class SoftwareForTest:
"""
Class to prepare and simulate software.
each instance has a sotfware attributed
"""
def __init__(self, software_root, name=''): def __init__(self, software_root, name=''):
"""
Will set file and variable for software
"""
self.software_root = software_root self.software_root = software_root
if not os.path.isdir(self.software_root):
os.mkdir(self.software_root)
self.name = 'http://sr%s/' % name self.name = 'http://sr%s/' % name
self.sequence = [] self.sequence = []
os.mkdir(self.software_root)
self.software_hash = \ self.software_hash = \
slapos.grid.utils.getSoftwareUrlHash(self.name) slapos.grid.utils.getSoftwareUrlHash(self.name)
self.srdir = os.path.join(self.software_root, self.software_hash) self.srdir = os.path.join(self.software_root, self.software_hash)
...@@ -335,14 +372,23 @@ class SoftwareForTest: ...@@ -335,14 +372,23 @@ class SoftwareForTest:
self.setBuildout() self.setBuildout()
def setTemplateCfg (self,template = """[buildout]"""): def setTemplateCfg (self,template = """[buildout]"""):
"""
Set template.cfg
"""
open(os.path.join(self.srdir, 'template.cfg'), 'w').write(template) open(os.path.join(self.srdir, 'template.cfg'), 'w').write(template)
def setBuildout (self,buildout = """#!/bin/sh def setBuildout (self,buildout = """#!/bin/sh
touch worked"""): touch worked"""):
"""
Set a buildout exec in bin
"""
open(os.path.join(self.srbindir, 'buildout'), 'w').write(buildout) open(os.path.join(self.srbindir, 'buildout'), 'w').write(buildout)
os.chmod(os.path.join(self.srbindir, 'buildout'), 0755) os.chmod(os.path.join(self.srbindir, 'buildout'), 0755)
def setPeriodicity(self,periodicity): def setPeriodicity(self,periodicity):
"""
Set a periodicity file
"""
open(os.path.join(self.srdir, 'periodicity'), 'w').write( open(os.path.join(self.srdir, 'periodicity'), 'w').write(
"""%s""" % (periodicity)) """%s""" % (periodicity))
...@@ -503,22 +549,12 @@ touch worked""") ...@@ -503,22 +549,12 @@ touch worked""")
def test_one_partition_started_stopped(self): def test_one_partition_started_stopped(self):
self.started = True computer = ComputerForTest(self.software_root,self.instance_root)
self.sequence = [] instance = computer.instance_list[0]
httplib.HTTPConnection._callback = self._server_response('started') httplib.HTTPConnection._callback = computer.getServerResponse()
os.mkdir(self.software_root) instance.requested_state = 'started'
os.mkdir(self.instance_root) instance.software.setBuildout("""#!/bin/sh
partition_path = os.path.join(self.instance_root, '0')
os.mkdir(partition_path, 0750)
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 && touch worked &&
mkdir -p etc/run && mkdir -p etc/run &&
( (
...@@ -536,13 +572,12 @@ HEREDOC ...@@ -536,13 +572,12 @@ HEREDOC
)> etc/run/wrapper && )> etc/run/wrapper &&
chmod 755 etc/run/wrapper chmod 755 etc/run/wrapper
""" % dict(python = sys.executable)) """ % dict(python = sys.executable))
os.chmod(os.path.join(srbindir, 'buildout'), 0755)
self.assertTrue(self.grid.processComputerPartitionList()) self.assertTrue(self.grid.processComputerPartitionList())
self.assertSortedListEqual(os.listdir(self.instance_root), ['0', 'etc', self.assertSortedListEqual(os.listdir(self.instance_root), ['0', 'etc',
'var']) 'var'])
self.assertSortedListEqual(os.listdir(partition_path), ['.0_wrapper.log', self.assertSortedListEqual(os.listdir(instance.partition_path), ['.0_wrapper.log',
'worked', 'buildout.cfg', 'etc']) 'worked', 'buildout.cfg', 'etc'])
wrapper_log = os.path.join(partition_path, '.0_wrapper.log') wrapper_log = os.path.join(instance.partition_path, '.0_wrapper.log')
tries = 10 tries = 10
while tries > 0: while tries > 0:
tries -= 1 tries -= 1
...@@ -552,21 +587,18 @@ chmod 755 etc/run/wrapper ...@@ -552,21 +587,18 @@ chmod 755 etc/run/wrapper
os.path.getsize(wrapper_log) os.path.getsize(wrapper_log)
self.assertTrue('Working' in open(wrapper_log, 'r').read()) self.assertTrue('Working' in open(wrapper_log, 'r').read())
self.assertSortedListEqual(os.listdir(self.software_root), self.assertSortedListEqual(os.listdir(self.software_root),
[software_hash]) [instance.software.software_hash])
self.assertEqual(self.sequence, self.assertEqual(computer.sequence,
['getFullComputerInformation', 'availableComputerPartition', ['getFullComputerInformation', 'availableComputerPartition',
'startedComputerPartition']) 'startedComputerPartition'])
self.assertTrue(self.started) self.assertEqual(instance.state,'started')
self.stopped = False
self.sequence = []
self.setSlapgrid()
httplib.HTTPConnection._callback = self._server_response('stopped')
self.assertTrue(self.grid.processComputerPartitionList()) computer.sequence = []
instance.requested_state = 'stopped'
self.assertTrue(self.launchSlapgrid())
self.assertSortedListEqual(os.listdir(self.instance_root), ['0', 'etc', self.assertSortedListEqual(os.listdir(self.instance_root), ['0', 'etc',
'var']) 'var'])
self.assertSortedListEqual(os.listdir(partition_path), ['.0_wrapper.log', self.assertSortedListEqual(os.listdir(instance.partition_path), ['.0_wrapper.log',
'.0_wrapper.log.1', 'worked', 'buildout.cfg', 'etc']) '.0_wrapper.log.1', 'worked', 'buildout.cfg', 'etc'])
tries = 10 tries = 10
expected_text = 'Signal handler called with signal 15' expected_text = 'Signal handler called with signal 15'
...@@ -577,10 +609,10 @@ chmod 755 etc/run/wrapper ...@@ -577,10 +609,10 @@ chmod 755 etc/run/wrapper
break break
time.sleep(0.2) time.sleep(0.2)
self.assertTrue(found) self.assertTrue(found)
self.assertEqual(self.sequence, self.assertEqual(computer.sequence,
['getFullComputerInformation', 'availableComputerPartition', ['getFullComputerInformation', 'availableComputerPartition',
'stoppedComputerPartition']) 'stoppedComputerPartition'])
self.assertTrue(self.stopped) self.assertEqual(instance.state,'stopped')
def test_one_partition_stopped_started(self): def test_one_partition_stopped_started(self):
...@@ -796,37 +828,46 @@ class TestSlapgridCPPartitionProcessing (MasterMixin, unittest.TestCase): ...@@ -796,37 +828,46 @@ class TestSlapgridCPPartitionProcessing (MasterMixin, unittest.TestCase):
If time between last processing of instance and now is superior If time between last processing of instance and now is superior
to periodicity then instance should be proceed to periodicity then instance should be proceed
1. We set a wanted maximum_periodicity in periodicity file in 1. We set a wanted maximum_periodicity in periodicity file in
in software release directory in one software release directory and not the other one
2. We process computer partition and check if wanted_periodicity was 2. We process computer partition and check if wanted_periodicity was
used as maximum_periodicty used as maximum_periodicty
3. We wait for a time superior to wanted_periodicty 3. We wait for a time superior to wanted_periodicty
4. We launch processComputerPartition and check that partition is 4. We launch processComputerPartition and check that partition using
processed one more time software with periodicity was runned and not the other
5. We check that modification time of .timestamp was modified 5. We check that modification time of .timestamp was modified
""" """
computer = ComputerForTest(self.software_root,self.instance_root) computer = ComputerForTest(self.software_root,self.instance_root,20,20)
instance = computer.instance_list[0] instance0 = computer.instance_list[0]
timestamp = str(int(time.time()-5)) timestamp = str(int(time.time()-5))
instance0.timestamp = timestamp
for instance in computer.instance_list[1:]:
instance.software = \
computer.software_list[computer.instance_list.index(instance)]
instance.timestamp = timestamp instance.timestamp = timestamp
wanted_periodicity = 3 wanted_periodicity = 3
instance.software.setPeriodicity(wanted_periodicity) instance0.software.setPeriodicity(wanted_periodicity)
httplib.HTTPConnection._callback = computer.getServerResponse() httplib.HTTPConnection._callback = computer.getServerResponse()
self.launchSlapgrid() self.launchSlapgrid()
self.assertNotEqual(wanted_periodicity,self.grid.maximum_periodicity) self.assertNotEqual(wanted_periodicity,self.grid.maximum_periodicity)
last_runtime = os.path.getmtime( last_runtime = os.path.getmtime(
os.path.join(instance.partition_path, '.timestamp')) os.path.join(instance0.partition_path, '.timestamp'))
time.sleep(wanted_periodicity + 1) time.sleep(wanted_periodicity + 1)
for instance in computer.instance_list[1:]:
self.assertEqual(instance.sequence,
['availableComputerPartition', 'stoppedComputerPartition'])
self.launchSlapgrid() self.launchSlapgrid()
self.assertEqual(computer.sequence, self.assertEqual(instance0.sequence,
['getFullComputerInformation', 'availableComputerPartition', ['availableComputerPartition', 'stoppedComputerPartition',
'stoppedComputerPartition', 'getFullComputerInformation',
'availableComputerPartition', 'stoppedComputerPartition', 'availableComputerPartition', 'stoppedComputerPartition',
]) ])
for instance in computer.instance_list[1:]:
self.assertEqual(instance.sequence,
['availableComputerPartition', 'stoppedComputerPartition'])
self.assertGreater( self.assertGreater(
os.path.getmtime(os.path.join(instance.partition_path,'.timestamp')), os.path.getmtime(os.path.join(instance0.partition_path,'.timestamp')),
last_runtime) last_runtime)
self.assertNotEqual(wanted_periodicity,self.grid.maximum_periodicity) self.assertNotEqual(wanted_periodicity,self.grid.maximum_periodicity)
...@@ -1224,59 +1265,17 @@ exit 0""" % {'worked_file': worked_file}) ...@@ -1224,59 +1265,17 @@ exit 0""" % {'worked_file': worked_file})
self.assertTrue(self.started) self.assertTrue(self.started)
def test_stderr_has_been_sent(self): def test_stderr_has_been_sent(self):
computer = ComputerForTest(self.software_root,self.instance_root)
instance = computer.instance_list[0]
httplib.HTTPConnection._callback = computer.getServerResponse()
def server_response(self_httplib, path, method, body, header): instance.requested_state = 'started'
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 == 'getFullComputerInformation' 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')
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'started'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'availableComputerPartition' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
return (200, {}, '')
if parsed_url.path == 'startedComputerPartition' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.assertEqual(parsed_qs['computer_partition_id'][0], '0')
self.started = True
return (200, {}, '')
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.fake_waiting_time = 0.5
self.error = False
self.started = False
instance_path = self._create_instance('0')
self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise') promise_path = os.path.join(instance.partition_path, 'etc', 'promise')
os.makedirs(promise_path) os.makedirs(promise_path)
succeed = os.path.join(promise_path, 'stderr_writer') succeed = os.path.join(promise_path, 'stderr_writer')
worked_file = os.path.join(instance_path, 'stderr_worked') worked_file = os.path.join(instance.partition_path, 'stderr_worked')
with open(succeed, 'w') as f: with open(succeed, 'w') as f:
f.write("""#!/usr/bin/env sh f.write("""#!/usr/bin/env sh
touch "%(worked_file)s" touch "%(worked_file)s"
...@@ -1286,65 +1285,23 @@ exit 127""" % {'worked_file': worked_file}) ...@@ -1286,65 +1285,23 @@ exit 127""" % {'worked_file': worked_file})
self.assertFalse(self.grid.processComputerPartitionList()) self.assertFalse(self.grid.processComputerPartitionList())
self.assertTrue(os.path.isfile(worked_file)) self.assertTrue(os.path.isfile(worked_file))
self.assertEqual(self.error_log, 'Error') self.assertEqual(instance.error_log, 'Error')
self.assertTrue(self.error) self.assertTrue(instance.error)
self.assertFalse(self.started) self.assertIsNone(instance.state)
def test_timeout_works(self): def test_timeout_works(self):
computer = ComputerForTest(self.software_root,self.instance_root)
instance = computer.instance_list[0]
httplib.HTTPConnection._callback = computer.getServerResponse()
def server_response(self_httplib, path, method, body, header): instance.requested_state = 'started'
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 == 'getFullComputerInformation' 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')
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'started'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
if parsed_url.path == 'availableComputerPartition' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
return (200, {}, '')
if parsed_url.path == 'startedComputerPartition' and \
method == 'POST' and 'computer_partition_id' in parsed_qs:
self.assertEqual(parsed_qs['computer_partition_id'][0], '0')
self.started = True
return (200, {}, '')
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.fake_waiting_time = 0.2
self.error = False
self.started = False
instance_path = self._create_instance('0') promise_path = os.path.join(instance.partition_path, 'etc', 'promise')
self._bootstrap()
promise_path = os.path.join(instance_path, 'etc', 'promise')
os.makedirs(promise_path) os.makedirs(promise_path)
succeed = os.path.join(promise_path, 'timed_out_promise') succeed = os.path.join(promise_path, 'timed_out_promise')
worked_file = os.path.join(instance_path, 'timed_out_worked') worked_file = os.path.join(instance.partition_path, 'timed_out_worked')
with open(succeed, 'w') as f: with open(succeed, 'w') as f:
f.write("""#!/usr/bin/env sh f.write("""#!/usr/bin/env sh
touch "%(worked_file)s" touch "%(worked_file)s"
...@@ -1354,8 +1311,8 @@ exit 0""" % {'worked_file': worked_file}) ...@@ -1354,8 +1311,8 @@ exit 0""" % {'worked_file': worked_file})
self.assertFalse(self.grid.processComputerPartitionList()) self.assertFalse(self.grid.processComputerPartitionList())
self.assertTrue(os.path.isfile(worked_file)) self.assertTrue(os.path.isfile(worked_file))
self.assertTrue(self.error) self.assertTrue(instance.error)
self.assertFalse(self.started) self.assertIsNone(instance.state)
def test_two_succeeding_promises(self): def test_two_succeeding_promises(self):
......
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