Commit 20ef7ed7 authored by Stavros Sachtouris's avatar Stavros Sachtouris

Unit test compute methods, fix emerging bugs

parent 1b369c3e
...@@ -21,7 +21,7 @@ setup( ...@@ -21,7 +21,7 @@ setup(
description='OCCI to Openstack/Cyclades API bridge', description='OCCI to Openstack/Cyclades API bridge',
url='http://code.grnet.gr/projects/snf-occi', url='http://code.grnet.gr/projects/snf-occi',
license='GPLv3', license='GPLv3',
packages=['soi', ], packages=['soi', 'soi.tests'],
entry_points=''' entry_points='''
[paste.app_factory] [paste.app_factory]
snf_occi_app=soi:main snf_occi_app=soi:main
......
...@@ -142,32 +142,21 @@ def snf_delete_server(cls, req, server_id): ...@@ -142,32 +142,21 @@ def snf_delete_server(cls, req, server_id):
def snf_run_action(cls, req, action, server_id): def snf_run_action(cls, req, action, server_id):
"""Synnefo: server actions""" """Synnefo: server actions"""
actions_map = {
"stop": {"kwargs": {"server_id": server_id,
"json_data": {"shutdown": {}}
}
},
"start": {"kwargs": {"server_id": server_id,
"json_data": {"start": {}}
}
},
"restart": {"kwargs": {"server_id": server_id,
"json_data": {"reboot": {"type": "SOFT"}}
}
}
}
try: try:
action = actions_map[action] json_data = {
req.environ['service_type'] = 'compute' 'start': {'start': {}},
req.environ['method_name'] = 'servers_action_post' 'stop': {'shutdown': {}},
req.environ.update(action) 'restart': {'reboot': {'type': 'SOFT'}}
req.get_response(cls.app) }[action]
except KeyError: except KeyError:
raise webob.exc.HTTPNotImplemented( raise webob.exc.HTTPNotImplemented(
explanation='Action {0} not supported'.format(action)) explanation='Action {0} not supported'.format(action))
req.environ['service_type'] = 'compute'
req.environ['method_name'] = 'servers_action_post'
req.environ['kwargs'] = {'server_id': server_id, 'json_data': json_data}
req.get_response(cls.app)
function_map = { function_map = {
'index': snf_index, 'index': snf_index,
......
...@@ -12,31 +12,3 @@ ...@@ -12,31 +12,3 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
This it the entry point for paste deploy .
Paste config file needs to point to egg:<package name>:<entrypoint name>:
use = egg:snfOCCI#sample_app
sample_app entry point is defined in setup.py:
entry_points='''
[paste.app_factory]
sample_app = soi:main
''',
which point to this function call (<module name>:function).
"""
from soi import wsgi
from soi import synnefo
# W0613:unused args
# pylint: disable=W0613
def main(global_config, **settings):
"""This is the entry point for paste into the Synnefo OCCI Interface"""
factory = wsgi.SNFOCCIMiddleware.factory({})
return factory(synnefo.call_kamaki)
# Copyright (C) 2016 GRNET S.A.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
class FakeReq:
"""use it for testing"""
def __init__(self, *args, **kwargs):
self.environ = dict()
def get_response(self, *args, **kwargs):
"""Don't do enything"""
class DummyClass:
"""use it for testing"""
def app(self, *args, **kwargs):
"""inner app"""
def get_from_response(self, *args, **kwargs):
"""Don't do enything"""
# Copyright (C) 2016 GRNET S.A.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
from soi.tests import fakes
from soi import compute
from mock import patch
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value='g f r')
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_index(gr, gfr):
"""Test snf_index"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
r = compute.snf_index(cls, req)
assert r == 'g f r'
assert req.environ == dict(
service_type='compute',
method_name='servers_get')
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'servers', [])
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value='g f r')
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_get_flavors(gr, gfr):
"""Test snf_get_flavors"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
r = compute.snf_get_flavors(cls, req)
assert r == 'g f r'
assert req.environ == dict(
service_type='compute',
method_name='flavors_get',
kwargs=dict(detail=True))
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'flavors', [])
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value='g f r')
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_get_images(gr, gfr):
"""Test snf_get_images"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
r = compute.snf_get_images(cls, req)
assert r == 'g f r'
assert req.environ == dict(
service_type='compute',
method_name='images_get',
kwargs=dict(detail=True))
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'images', [])
def test__openstackify_addresses():
"""Test _openstackify_addresses"""
addresses = {
'12345': [{
'version': '4',
'addr': '123.45.67.89',
'OS-EXT-IPS:type': 'floating',
}, ],
'67890': [{
'version': '6',
'addr': '2001:123:5gf6:6789:a800:ff:dast:434d',
'OS-EXT-IPS:type': 'fixed',
}, ],
}
attachments = [
{
'network_id': '12345',
'mac_address': 'a mac address',
'id': 'an attachment id',
'firewallProfile': 'DISABLED',
'OS-EXT-IPS:type': 'floating',
'ipv4': '123.45.67.89',
'ipv6': '',
},
{
'network_id': '67890',
'mac_address': 'another mac address',
'id': 'another attachment id',
'firewallProfile': 'DISABLED',
'OS-EXT-IPS:type': 'fixed',
'ipv4': '',
'ipv6': '2001:123:5gf6:6789:a800:ff:dast:434d',
},
]
expected_addresses = {
'12345': [{
'version': '4',
'addr': '123.45.67.89',
'OS-EXT-IPS:type': 'floating',
'net_id': '12345',
'OS-EXT-IPS-MAC:mac_addr': 'a mac address',
}, ],
'67890': [{
'version': '6',
'addr': '2001:123:5gf6:6789:a800:ff:dast:434d',
'OS-EXT-IPS:type': 'fixed',
'net_id': '67890',
'OS-EXT-IPS-MAC:mac_addr': 'another mac address',
}, ],
}
compute._openstackify_addresses(addresses, attachments)
assert addresses == expected_addresses
_response = {
'addresses': 'some addresses', 'attachments': 'some attachments'
}
@patch('soi.compute._openstackify_addresses')
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value=_response)
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_get_server(gr, gfr, _oa):
"""Test snf_get_server"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
r = compute.snf_get_server(cls, req, 'my server id')
assert r == _response
assert req.environ == dict(
service_type='compute',
method_name='servers_get',
kwargs=dict(server_id='my server id'))
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'server', {})
_oa.assert_called_once_with(
_response['addresses'], _response['attachments'])
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value='g f r')
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_get_flavor(gr, gfr):
"""Test snf_get_flavor"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
r = compute.snf_get_flavor(cls, req, 'my flavor id')
assert r == 'g f r'
assert req.environ == dict(
service_type='compute',
method_name='flavors_get',
kwargs=dict(flavor_id='my flavor id'))
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'flavor', {})
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value='g f r')
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_get_image(gr, gfr):
"""Test snf_get_image"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
r = compute.snf_get_image(cls, req, 'my image id')
assert r == 'g f r'
assert req.environ == dict(
service_type='compute',
method_name='images_get',
kwargs=dict(image_id='my image id'))
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'image', {})
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value='g f r')
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_get_server_volume_links(gr, gfr):
"""Test snf_get_server_volume_links"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
r = compute.snf_get_server_volumes_link(cls, req, 'my server id')
assert r == 'g f r'
assert req.environ == dict(
service_type='compute',
method_name='volume_attachment_get',
kwargs=dict(server_id='my server id'))
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'volumeAttachments', [])
def test__openstackify_net_attachments():
"""Test _openstackify_net_attachments"""
input_ = [
{
'network_id': '12345',
'mac_address': 'a mac address',
'id': 'an attachment id',
'firewallProfile': 'DISABLED',
'OS-EXT-IPS:type': 'floating',
'ipv4': '123.45.67.89',
'ipv6': '',
},
{
'network_id': '67890',
'mac_address': 'another mac address',
'id': 'another attachment id',
'firewallProfile': 'DISABLED',
'OS-EXT-IPS:type': 'fixed',
'ipv4': '',
'ipv6': '2001:123:5gf6:6789:a800:ff:dast:434d',
},
]
expected_output = [
{
'network_id': '12345',
'net_id': '12345',
'mac_address': 'a mac address',
'mac_addr': 'a mac address',
'id': 'an attachment id',
'port_id': 'an attachment id',
'firewallProfile': 'DISABLED',
'OS-EXT-IPS:type': 'floating',
'ipv4': '123.45.67.89',
'ipv6': '',
},
{
'network_id': '67890',
'net_id': '67890',
'mac_address': 'another mac address',
'mac_addr': 'another mac address',
'id': 'another attachment id',
'port_id': 'another attachment id',
'firewallProfile': 'DISABLED',
'OS-EXT-IPS:type': 'fixed',
'ipv4': '',
'ipv6': '2001:123:5gf6:6789:a800:ff:dast:434d',
'fixed_ips': {
'ip_address': '2001:123:5gf6:6789:a800:ff:dast:434d'},
},
]
compute._openstackify_net_attachments(input_)
assert input_ == expected_output
@patch('soi.compute._openstackify_net_attachments')
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value='g f r')
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_get_server_net_attachments(gr, gfr, _ona):
"""Test snf_get_server_net_attachments"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
r = compute.snf_get_server_net_attachments(cls, req, 'my server id')
assert r == 'g f r'
assert req.environ == dict(
service_type='compute',
method_name='servers_ips_get',
kwargs=dict(server_id='my server id'))
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'attachments', [])
_ona.assert_called_once_with('g f r')
@patch('soi.compute._openstackify_addresses')
@patch('soi.tests.fakes.DummyClass.get_from_response', return_value=_response)
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_snf_create_server(gr, gfr, _oa):
"""Test snf_create_server"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
req.environ['HTTP_X_PROJECT_ID'] = 'a project id'
args = ('a name', 'an image', 'a flavor')
r = compute.snf_create_server(cls, req, *args)
assert r == _response
assert req.environ == dict(
HTTP_X_PROJECT_ID='a project id',
service_type='compute',
method_name='servers_post',
kwargs=dict(json_data=dict(server=dict(
name='a name', imageRef='an image', flavorRef='a flavor',
project='a project id'))))
gr.assert_called_once_with(cls.app)
gfr.assert_called_once_with('my response', 'server', {})
_oa.assert_called_once_with(
_response['addresses'], _response['attachments'])
@patch('soi.tests.fakes.FakeReq.get_response')
def test_snf_delete_server(gr):
"""Test snf_delete_server"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
compute.snf_delete_server(cls, req, 'my server id')
assert req.environ == dict(
service_type='compute',
method_name='servers_delete',
kwargs=dict(server_id='my server id'))
gr.assert_called_once_with(cls.app)
def _test_snf_run_action(action, json_data, gr):
"""used by "test_snf_run_action_* methods"""
cls, req = fakes.DummyClass(), fakes.FakeReq()
compute.snf_run_action(cls, req, action, 'my server id')
assert req.environ == dict(
service_type='compute',
method_name='servers_action_post',
kwargs=dict(server_id='my server id', json_data=json_data))
gr.assert_called_once_with(cls.app)
@patch('soi.tests.fakes.FakeReq.get_response')
def test_snf_run_action_start(gr):
"""Test snf_run_action start"""
_test_snf_run_action('start', {'start': {}}, gr)
@patch('soi.tests.fakes.FakeReq.get_response')
def test_snf_run_action_stop(gr):
"""Test snf_run_action stop"""
_test_snf_run_action('stop', {'shutdown': {}}, gr)
@patch('soi.tests.fakes.FakeReq.get_response')
def test_snf_run_action_restart(gr):
"""Test snf_run_action restart"""
_test_snf_run_action('restart', {'reboot': {'type': 'SOFT'}}, gr)
@patch('soi.tests.fakes.FakeReq.get_response')
def test_snf_run_action_suspend(gr):
"""Test snf_run_action suspend"""
try:
_test_snf_run_action('suspend', {}, gr)
except Exception as e:
from webob.exc import HTTPNotImplemented
assert isinstance(e, HTTPNotImplemented)
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
from soi import utils from soi import utils
from mock import patch from mock import patch
from soi.tests import fakes
def test_patch_class_methods(): def test_patch_class_methods():
...@@ -38,34 +39,12 @@ def test_patch_class_methods(): ...@@ -38,34 +39,12 @@ def test_patch_class_methods():
assert client.an_other_method('arg1', 'arg2') == 'replace arg1 arg2' assert client.an_other_method('arg1', 'arg2') == 'replace arg1 arg2'
def test_empty_list_200(): @patch('soi.tests.fakes.DummyClass.get_from_response', return_value='g f r')
@patch('soi.tests.fakes.FakeReq.get_response', return_value='my response')
def test_empty_list_200(gr, gfr):
"""Test the empty list method""" """Test the empty list method"""
class FakeReq: cls, req = fakes.DummyClass(), fakes.FakeReq()
"""use it for testing""" r = utils.empty_list_200(cls, req)
environ = dict() assert r == 'g f r'
gfr.assert_called_once_with('my response', 'empty list', [])
def get_response(self, *args, **kwargs): gr.assert_called_once_with(cls.app)
"""Don't do enything"""
class DummyClass:
"""use it for testing"""
def app(self, *args, **kwargs):
"""inner app"""
def get_from_response(self, *args, **kwargs):
"""Don't do enything"""
setattr(utils, 'FakeReq', FakeReq)
setattr(utils, 'DummyClass', DummyClass)
with patch(
'soi.utils.FakeReq.get_response',
return_value='my response') as gr:
with patch(
'soi.utils.DummyClass.get_from_response',
return_value='get from response') as gfr:
cls, req = DummyClass(), FakeReq()
r = utils.empty_list_200(cls, req)
assert r == 'get from response'
gfr.assert_called_once_with('my response', 'empty list', [])
gr.assert_called_once_with(cls.app)
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