Files
kuryr-kubernetes/kuryr_kubernetes/tests/unit/controller/managers/test_pool.py
Luis Tomas Bolivar 3de89337f7 Add list and show pool commands to Pool Manager
This patch add the support to get the current status of the pools.
It can list the existing pools and their number of available
subports, as well as to show the ids of the ports associated to
a given pool.

Implements: blueprint kuryr-manager-cli-tool
Change-Id: I9332ffa259c4651b69c788985e5bbd1f98cb38cc
2017-10-10 10:36:10 +00:00

360 lines
15 KiB
Python

# Copyright 2017 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
try:
from BaseHTTPServer import BaseHTTPRequestHandler
except ImportError:
from http.server import BaseHTTPRequestHandler
from oslo_serialization import jsonutils
from kuryr_kubernetes.controller.managers import pool as m_pool
from kuryr_kubernetes.tests import base as test_base
class TestRequestHandler(test_base.TestCase):
def setUp(self):
super(TestRequestHandler, self).setUp()
client_address = 'localhost'
server = '/tmp/server.lock'
req = mock.MagicMock()
with mock.patch.object(BaseHTTPRequestHandler, '__init__') as m_http:
m_http.return_value = None
self._req_handler = m_pool.RequestHandler(req, client_address,
server)
self._req_handler.rfile = mock.Mock()
self._req_handler.wfile = mock.Mock()
def _do_POST_helper(self, method, path, headers, body, expected_resp,
trigger_exception, trunk_ips, num_ports=None):
self._req_handler.headers = headers
self._req_handler.path = path
with mock.patch.object(self._req_handler.rfile, 'read') as m_read,\
mock.patch.object(self._req_handler,
'_create_subports') as m_create,\
mock.patch.object(self._req_handler,
'_delete_subports') as m_delete:
m_read.return_value = body
if trigger_exception:
m_create.side_effect = Exception
m_delete.side_effect = Exception
with mock.patch.object(self._req_handler,
'send_header') as m_send_header,\
mock.patch.object(self._req_handler,
'end_headers') as m_end_headers,\
mock.patch.object(self._req_handler.wfile,
'write') as m_write:
self._req_handler.do_POST()
if method == 'create':
if trunk_ips:
m_create.assert_called_once_with(num_ports, trunk_ips)
else:
m_create.assert_not_called()
if method == 'delete':
m_delete.assert_called_once_with(trunk_ips)
m_send_header.assert_called_once_with('Content-Length',
len(expected_resp))
m_end_headers.assert_called_once()
m_write.assert_called_once_with(expected_resp)
def _do_GET_helper(self, method, method_resp, path, headers, body,
expected_resp, trigger_exception, pool_key=None):
self._req_handler.headers = headers
self._req_handler.path = path
with mock.patch.object(self._req_handler.rfile, 'read') as m_read,\
mock.patch.object(self._req_handler,
'_list_pools') as m_list,\
mock.patch.object(self._req_handler,
'_show_pool') as m_show:
m_read.return_value = body
if trigger_exception:
m_list.side_effect = Exception
m_show.side_effect = Exception
else:
m_list.return_value = method_resp
m_show.return_value = method_resp
with mock.patch.object(self._req_handler,
'send_header') as m_send_header,\
mock.patch.object(self._req_handler,
'end_headers') as m_end_headers,\
mock.patch.object(self._req_handler.wfile,
'write') as m_write:
self._req_handler.do_GET()
if method == 'list':
m_list.assert_called_once()
if method == 'show':
if pool_key and len(pool_key) == 3:
m_show.assert_called_once_with(
(pool_key[0], pool_key[1],
tuple(sorted(pool_key[2]))))
else:
m_show.assert_not_called()
m_send_header.assert_called_once_with('Content-Length',
len(expected_resp))
m_end_headers.assert_called_once()
m_write.assert_called_once_with(expected_resp)
def test_do_POST_populate(self):
method = 'create'
path = "http://localhost/populatePool"
trunk_ips = [u"10.0.0.6"]
num_ports = 3
body = jsonutils.dumps({"trunks": trunk_ips,
"num_ports": num_ports})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Ports pool at {} was populated with 3 ports.'
.format(trunk_ips)).encode()
self._do_POST_helper(method, path, headers, body, expected_resp,
trigger_exception, trunk_ips, num_ports)
def test_do_POST_populate_exception(self):
method = 'create'
path = "http://localhost/populatePool"
trunk_ips = [u"10.0.0.6"]
num_ports = 3
body = jsonutils.dumps({"trunks": trunk_ips,
"num_ports": num_ports})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = True
expected_resp = ('Error while populating pool {0} with {1} ports.'
.format(trunk_ips, num_ports)).encode()
self._do_POST_helper(method, path, headers, body, expected_resp,
trigger_exception, trunk_ips, num_ports)
def test_do_POST_populate_no_trunks(self):
method = 'create'
path = "http://localhost/populatePool"
trunk_ips = []
num_ports = 3
body = jsonutils.dumps({"trunks": trunk_ips,
"num_ports": num_ports})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Trunk port IP(s) missing.'
.format(trunk_ips, num_ports)).encode()
self._do_POST_helper(method, path, headers, body, expected_resp,
trigger_exception, trunk_ips, num_ports)
def test_do_POST_free(self):
method = 'delete'
path = "http://localhost/freePool"
trunk_ips = [u"10.0.0.6"]
body = jsonutils.dumps({"trunks": trunk_ips})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Ports pool belonging to {0} was freed.'
.format(trunk_ips)).encode()
self._do_POST_helper(method, path, headers, body, expected_resp,
trigger_exception, trunk_ips)
def test_do_POST_free_exception(self):
method = 'delete'
path = "http://localhost/freePool"
trunk_ips = [u"10.0.0.6"]
body = jsonutils.dumps({"trunks": trunk_ips})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = True
expected_resp = ('Error freeing ports pool: {0}.'
.format(trunk_ips)).encode()
self._do_POST_helper(method, path, headers, body, expected_resp,
trigger_exception, trunk_ips)
def test_do_POST_free_no_trunks(self):
method = 'delete'
path = "http://localhost/freePool"
trunk_ips = []
body = jsonutils.dumps({"trunks": trunk_ips})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Ports pool belonging to all was freed.').encode()
self._do_POST_helper(method, path, headers, body, expected_resp,
trigger_exception, trunk_ips)
def test_do_POST_wrong_action(self):
method = 'fake'
path = "http://localhost/fakeMethod"
trunk_ips = [u"10.0.0.6"]
body = jsonutils.dumps({"trunks": trunk_ips})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Method not allowed.').encode()
self._do_POST_helper(method, path, headers, body, expected_resp,
trigger_exception, trunk_ips)
def test_do_GET_list(self):
method = 'list'
method_resp = ('["10.0.0.6", "9d2b45c4efaa478481c30340b49fd4d2", '
'["00efc78c-f11c-414a-bfcd-a82e16dc07d1", '
'"fd6b13dc-7230-4cbe-9237-36b4614bc6b5"]] '
'has 5 ports')
path = "http://localhost/listPools"
body = jsonutils.dumps({})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Pools:\n{0}'.format(method_resp)).encode()
self._do_GET_helper(method, method_resp, path, headers, body,
expected_resp, trigger_exception)
def test_do_GET_list_exception(self):
method = 'list'
method_resp = ('["10.0.0.6", "9d2b45c4efaa478481c30340b49fd4d2", '
'["00efc78c-f11c-414a-bfcd-a82e16dc07d1", '
'"fd6b13dc-7230-4cbe-9237-36b4614bc6b5"]] '
'has 5 ports')
path = "http://localhost/listPools"
body = jsonutils.dumps({})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = True
expected_resp = ('Error listing the pools.').encode()
self._do_GET_helper(method, method_resp, path, headers, body,
expected_resp, trigger_exception)
def test_do_GET_list_empty(self):
method = 'list'
method_resp = 'There are no pools'
path = "http://localhost/listPools"
body = jsonutils.dumps({})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Pools:\n{0}'.format(method_resp)).encode()
self._do_GET_helper(method, method_resp, path, headers, body,
expected_resp, trigger_exception)
def test_do_GET_show(self):
method = 'show'
method_resp = "251f748d-2a0d-4143-bce8-2e616f7a6a4a"
path = "http://localhost/showPool"
pool_key = [u"10.0.0.6", u"9d2b45c4efaa478481c30340b49fd4d2",
[u"00efc78c-f11c-414a-bfcd-a82e16dc07d1",
u"fd6b13dc-7230-4cbe-9237-36b4614bc6b5"]]
body = jsonutils.dumps({"pool_key": pool_key})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
formated_key = (pool_key[0], pool_key[1], tuple(sorted(pool_key[2])))
expected_resp = ('Pool {0} ports are:\n{1}'
.format(formated_key, method_resp)).encode()
self._do_GET_helper(method, method_resp, path, headers, body,
expected_resp, trigger_exception, pool_key)
def test_do_GET_show_exception(self):
method = 'show'
method_resp = "251f748d-2a0d-4143-bce8-2e616f7a6a4a"
path = "http://localhost/showPool"
pool_key = [u"10.0.0.6", u"9d2b45c4efaa478481c30340b49fd4d2",
[u"00efc78c-f11c-414a-bfcd-a82e16dc07d1",
u"fd6b13dc-7230-4cbe-9237-36b4614bc6b5"]]
body = jsonutils.dumps({"pool_key": pool_key})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = True
formated_key = (pool_key[0], pool_key[1], tuple(sorted(pool_key[2])))
expected_resp = ('Error showing pool: {0}.'
.format(formated_key)).encode()
self._do_GET_helper(method, method_resp, path, headers, body,
expected_resp, trigger_exception, pool_key)
def test_do_GET_show_empty(self):
method = 'show'
method_resp = "Empty pool"
path = "http://localhost/showPool"
pool_key = [u"10.0.0.6", u"9d2b45c4efaa478481c30340b49fd4d2",
[u"00efc78c-f11c-414a-bfcd-a82e16dc07d1",
u"fd6b13dc-7230-4cbe-9237-36b4614bc6b5"]]
body = jsonutils.dumps({"pool_key": pool_key})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
formated_key = (pool_key[0], pool_key[1], tuple(sorted(pool_key[2])))
expected_resp = ('Pool {0} ports are:\n{1}'
.format(formated_key, method_resp)).encode()
self._do_GET_helper(method, method_resp, path, headers, body,
expected_resp, trigger_exception, pool_key)
def test_do_GET_show_wrong_key(self):
method = 'show'
method_resp = ""
path = "http://localhost/showPool"
pool_key = [u"10.0.0.6", u"9d2b45c4efaa478481c30340b49fd4d2"]
body = jsonutils.dumps({"pool_key": pool_key})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Invalid pool key. Proper format is:\n[trunk_ip, '
'project_id, [security_groups]]\n').encode()
self._do_GET_helper(method, method_resp, path, headers, body,
expected_resp, trigger_exception, pool_key)
def test_do_GET_wrong_action(self):
method = 'fake'
method_resp = ""
path = "http://localhost/fakeMethod"
body = jsonutils.dumps({})
headers = {'Content-Type': 'application/json', 'Connection': 'close'}
headers['Content-Length'] = len(body)
trigger_exception = False
expected_resp = ('Method not allowed.').encode()
self._do_GET_helper(method, method_resp, path, headers, body,
expected_resp, trigger_exception)