Commit 504266f8 authored by Cédric Le Ninivin's avatar Cédric Le Ninivin

Added documentation for slapproxy and cleaned code

parent a0cfee01
...@@ -30,42 +30,42 @@ ...@@ -30,42 +30,42 @@
import os import os
import logging import logging
import shutil import shutil
import signal
import slapos.proxy import slapos.proxy
import slapos.proxy.views as views import slapos.proxy.views as views
import slapos.slap.slap import slapos.slap.slap
import sqlite3
import sys
import tempfile import tempfile
import time
import threading
import unittest import unittest
import urllib
import xml_marshaller import xml_marshaller
class WrongFormat(Exception): class WrongFormat(Exception):
pass pass
class Config: class ProxyOption:
def __init__(self,proxy_db): """
Will simulate options given to slapproxy
"""
def __init__(self, proxy_db):
self.verbose=True self.verbose=True
self.database_uri=proxy_db self.database_uri=proxy_db
self.console = False self.console = False
self.log_file = None self.log_file = None
class BasicMixin: class BasicMixin:
def assertSortedListEqual(self, list1, list2, msg=None):
self.assertListEqual(sorted(list1), sorted(list2), msg)
def setUp(self): def setUp(self):
"""
Will set files and start slapproxy
"""
self._tempdir = tempfile.mkdtemp() self._tempdir = tempfile.mkdtemp()
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
self.setFiles() self.setFiles()
self.startProxy() self.startProxy()
def setFiles(self): def setFiles(self):
"""
Set environment to run slapproxy
"""
self.slapos_cfg = os.path.join(self._tempdir, 'slapos.cfg') self.slapos_cfg = os.path.join(self._tempdir, 'slapos.cfg')
self.proxy_db = os.path.join(self._tempdir,'lib', 'proxy.db') self.proxy_db = os.path.join(self._tempdir, 'lib', 'proxy.db')
self.proxyaddr = 'http://127.0.0.1:8080/' self.proxyaddr = 'http://127.0.0.1:8080/'
self.computer_id = 'computer' self.computer_id = 'computer'
open(self.slapos_cfg, 'w').write("""[slapos] open(self.slapos_cfg, 'w').write("""[slapos]
...@@ -78,17 +78,17 @@ host = 127.0.0.1 ...@@ -78,17 +78,17 @@ host = 127.0.0.1
port = 8080 port = 8080
database_uri = %(tempdir)s/lib/proxy.db database_uri = %(tempdir)s/lib/proxy.db
"""% dict (tempdir = self._tempdir, proxyaddr = self.proxyaddr)) """% dict (tempdir = self._tempdir, proxyaddr = self.proxyaddr))
for directory in ("opt","srv","lib"): for directory in ("opt", "srv", "lib"):
path = os.path.join(self._tempdir,directory) path = os.path.join(self._tempdir, directory)
os.mkdir(path) os.mkdir(path)
def startProxy(self): def startProxy(self):
"""
Set config for slapproxy and start it
"""
config = slapos.proxy.Config() config = slapos.proxy.Config()
config.setConfig(*(Config(self.proxy_db), config.setConfig(*(ProxyOption(self.proxy_db),
self.slapos_cfg)) self.slapos_cfg))
self.proxy_launch(config)
def proxy_launch(self,config):
views.app.config['TESTING'] = True views.app.config['TESTING'] = True
views.app.config['computer_id'] = self.computer_id views.app.config['computer_id'] = self.computer_id
views.app.config['DATABASE_URI'] = self.proxy_db views.app.config['DATABASE_URI'] = self.proxy_db
...@@ -97,12 +97,22 @@ database_uri = %(tempdir)s/lib/proxy.db ...@@ -97,12 +97,22 @@ database_uri = %(tempdir)s/lib/proxy.db
self.app = views.app.test_client() self.app = views.app.test_client()
def tearDown(self): def tearDown(self):
"""
Remove files generated for test
"""
shutil.rmtree(self._tempdir, True) shutil.rmtree(self._tempdir, True)
class TestInformation(BasicMixin, unittest.TestCase): class TestInformation(BasicMixin, unittest.TestCase):
"""
Test Basic response of slapproxy
"""
def test_getComputerInformation (self): def test_getComputerInformation (self):
"""
Check that getComputerInformation return a Computer
and database is generated
"""
rv = self.app.get('/getComputerInformation?computer_id=' rv = self.app.get('/getComputerInformation?computer_id='
+self.computer_id) +self.computer_id)
self.assertIsInstance( self.assertIsInstance(
...@@ -111,6 +121,10 @@ class TestInformation(BasicMixin, unittest.TestCase): ...@@ -111,6 +121,10 @@ class TestInformation(BasicMixin, unittest.TestCase):
self.assertTrue(os.path.exists(self.proxy_db)) self.assertTrue(os.path.exists(self.proxy_db))
def test_getFullComputerInformation (self): def test_getFullComputerInformation (self):
"""
Check that getFullComputerInformation return a Computer
and database is generated
"""
rv = self.app.get('/getFullComputerInformation?computer_id=' rv = self.app.get('/getFullComputerInformation?computer_id='
+ self.computer_id) + self.computer_id)
self.assertIsInstance( self.assertIsInstance(
...@@ -119,20 +133,30 @@ class TestInformation(BasicMixin, unittest.TestCase): ...@@ -119,20 +133,30 @@ class TestInformation(BasicMixin, unittest.TestCase):
self.assertTrue(os.path.exists(self.proxy_db)) self.assertTrue(os.path.exists(self.proxy_db))
def test_getComputerInformation_wrong_computer (self): def test_getComputerInformation_wrong_computer (self):
"""
Test that computer information won't be given to a requester different
from the one specified
"""
with self.assertRaises(views.UnauthorizedError): with self.assertRaises(views.UnauthorizedError):
rv =self.app.get('/getComputerInformation?computer_id=' self.app.get('/getComputerInformation?computer_id='
+ self.computer_id + '42') + self.computer_id + '42')
self.assertTrue(os.path.exists(self.proxy_db))
class MasterMixin(BasicMixin): class MasterMixin(BasicMixin):
"""
def add_free_partition (self,partition_amount): Define advanced tool for test proxy simulating behavior slap library tools
"""
def add_free_partition (self, partition_amount):
"""
Will simulate a slapformat first run
and create "partition_amount" partitions
"""
computer_dict = {'reference':self.computer_id, computer_dict = {'reference':self.computer_id,
'address':'123.456.789', 'address':'123.456.789',
'netmask':'fffffffff', 'netmask':'fffffffff',
'partition_list':[]} 'partition_list':[]}
for i in range(0,partition_amount): for i in range(0, partition_amount):
partition_example = {'reference':'slappart%s' %i, partition_example = {'reference':'slappart%s' %i,
'address_list':[]} 'address_list':[]}
computer_dict['partition_list'].append(partition_example) computer_dict['partition_list'].append(partition_example)
...@@ -140,13 +164,17 @@ class MasterMixin(BasicMixin): ...@@ -140,13 +164,17 @@ class MasterMixin(BasicMixin):
request_dict = { 'computer_id': self.computer_id, request_dict = { 'computer_id': self.computer_id,
'xml': xml_marshaller.xml_marshaller.dumps(computer_dict), 'xml': xml_marshaller.xml_marshaller.dumps(computer_dict),
} }
rv = self.app.post('/loadComputerConfigurationFromXML', self.app.post('/loadComputerConfigurationFromXML',
data = request_dict) data = request_dict)
def request(self, software_release, software_type, partition_reference, def request(self, software_release, software_type, partition_reference,
partition_id, partition_id,
shared=False, partition_parameter_kw=None, filter_kw=None, shared=False, partition_parameter_kw=None, filter_kw=None,
state=None): state=None):
"""
Simulate a request with above parameters
Return response by server (a computer partition or an error)
"""
if partition_parameter_kw is None: if partition_parameter_kw is None:
partition_parameter_kw = {} partition_parameter_kw = {}
if filter_kw is None: if filter_kw is None:
...@@ -186,8 +214,12 @@ class MasterMixin(BasicMixin): ...@@ -186,8 +214,12 @@ class MasterMixin(BasicMixin):
'_parameter_dict', None) '_parameter_dict', None)
return computer_partition return computer_partition
def setComputerPartitionConnectionXml(self,instance): def setComputerPartitionConnectionXml(self, instance):
# Will post info about slaves """
Will send instance connection information to server
including from slaves in this partition
"""
# Will post information about slaves
for slave in instance._parameter_dict['slave_instance_list']: for slave in instance._parameter_dict['slave_instance_list']:
request_dict = { request_dict = {
'slave_reference': slave['slave_reference'], 'slave_reference': slave['slave_reference'],
...@@ -197,6 +229,7 @@ class MasterMixin(BasicMixin): ...@@ -197,6 +229,7 @@ class MasterMixin(BasicMixin):
} }
self.app.post('/setComputerPartitionConnectionXml', self.app.post('/setComputerPartitionConnectionXml',
data = request_dict) data = request_dict)
# Will post information about instance
request_dict = { request_dict = {
'slave_reference': None, 'slave_reference': None,
'computer_partition_id': instance._partition_id, 'computer_partition_id': instance._partition_id,
...@@ -208,56 +241,99 @@ class MasterMixin(BasicMixin): ...@@ -208,56 +241,99 @@ class MasterMixin(BasicMixin):
class TestRequest (MasterMixin, unittest.TestCase): class TestRequest (MasterMixin, unittest.TestCase):
"""
Set of tests for requests
"""
def test_two_request_one_partition_free (self): def test_two_request_one_partition_free (self):
"""
If only one partition is available and two different request are made
first will succeed second will fail
"""
self.add_free_partition(1) self.add_free_partition(1)
self.assertIsInstance(self.request('http://sr//',None,'Maria','slappart2'), self.assertIsInstance(self.request('http://sr//', None,
'Maria', 'slappart2'),
slapos.slap.ComputerPartition) slapos.slap.ComputerPartition)
with self.assertRaises(WrongFormat): with self.assertRaises(WrongFormat):
self.request('http://sr//',None,'Maria','slappart3') self.request('http://sr//', None, 'Maria', 'slappart3')
def test_two_request_two_partition_free (self): def test_two_request_two_partition_free (self):
"""
If two requests are made with two available partition
both will succeed
"""
self.add_free_partition(2) self.add_free_partition(2)
self.assertIsInstance(self.request('http://sr//',None,'Maria','slappart2'), self.assertIsInstance(self.request('http://sr//', None,
'Maria', 'slappart2'),
slapos.slap.ComputerPartition) slapos.slap.ComputerPartition)
self.assertIsInstance(self.request('http://sr//',None,'Maria','slappart3'), self.assertIsInstance(self.request('http://sr//', None,
'Maria', 'slappart3'),
slapos.slap.ComputerPartition) slapos.slap.ComputerPartition)
def test_two_same_request_from_one_partition (self): def test_two_same_request_from_one_partition (self):
"""
Request will return same partition for two equal requests
"""
self.add_free_partition(2) self.add_free_partition(2)
self.assertEqual( self.assertEqual(
self.request('http://sr//',None,'Maria','slappart2').__dict__, self.request('http://sr//', None, 'Maria', 'slappart2').__dict__,
self.request('http://sr//',None,'Maria','slappart2').__dict__) self.request('http://sr//', None, 'Maria', 'slappart2').__dict__)
def test_two_different_request_from_two_partition (self): def test_two_different_request_from_two_partition (self):
"""
Two request from different partitions
will return two differents partitions
"""
self.add_free_partition(2) self.add_free_partition(2)
self.assertNotEqual( self.assertNotEqual(
self.request('http://sr//',None,'Maria','slappart2').__dict__, self.request('http://sr//', None, 'Maria', 'slappart2').__dict__,
self.request('http://sr//',None,'Maria','slappart3').__dict__) self.request('http://sr//', None, 'Maria', 'slappart3').__dict__)
def test_two_different_request_from_one_partition (self): def test_two_different_request_from_one_partition (self):
"""
Two different request from same partition
will return two different partitions
"""
self.add_free_partition(2) self.add_free_partition(2)
self.assertNotEqual( self.assertNotEqual(
self.request('http://sr//',None,'Maria','slappart2').__dict__, self.request('http://sr//', None, 'Maria', 'slappart2').__dict__,
self.request('http://sr//',None,'frontend','slappart2').__dict__) self.request('http://sr//', None, 'frontend', 'slappart2').__dict__)
def test_slave_request_no_corresponding_partition (self): def test_slave_request_no_corresponding_partition (self):
"""
Slave instance request will fail if no corresponding are found
"""
self.add_free_partition(2) self.add_free_partition(2)
with self.assertRaises(WrongFormat): with self.assertRaises(WrongFormat):
self.request('http://sr//',None,'Maria','slappart2',shared=True) self.request('http://sr//', None, 'Maria', 'slappart2', shared=True)
def test_slave_request_one_corresponding_partition (self): def test_slave_request_one_corresponding_partition (self):
"""
Successfull request slave instance follow these steps:
1. Provide one corresponding partition
2. Ask for Slave instance. Error is raise because it is not ready
But slave is added to Master Instance slave list
3. Master Instance get updated information (including slave list)
4. Master instance post information about slaves and itself
5. Ask for slave instance is successfull and return a computer instance
"""
self.add_free_partition(6) self.add_free_partition(6)
master_partition_id = self.request('http://sr//',None, # Provide partition
'Maria','slappart4')._partition_id master_partition_id = self.request('http://sr//', None,
'Maria', 'slappart4')._partition_id
# Failed request of slave instance
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
self.request('http://sr//',None,'Maria','slappart2',shared=True) self.request('http://sr//', None, 'Maria', 'slappart2', shared=True)
# Get updated information for master partition
rv = self.app.get('/getFullComputerInformation?computer_id=' rv = self.app.get('/getFullComputerInformation?computer_id='
+ self.computer_id) + self.computer_id)
computer = xml_marshaller.xml_marshaller.loads(rv.data) computer = xml_marshaller.xml_marshaller.loads(rv.data)
for instance in computer._computer_partition_list: for instance in computer._computer_partition_list:
if instance._partition_id == master_partition_id: if instance._partition_id == master_partition_id:
master_partition = instance master_partition = instance
# Send information about slave
self.setComputerPartitionConnectionXml(master_partition) self.setComputerPartitionConnectionXml(master_partition)
self.request('http://sr//',None,'Maria','slappart2',shared=True) # Successfull slave request
self.assertIsInstance(
self.request('http://sr//', None, 'Maria', 'slappart2', shared=True),
slapos.slap.ComputerPartition)
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