Merge "Introduce container resize API"

This commit is contained in:
Zuul 2018-06-29 04:26:17 +00:00 committed by Gerrit Code Review
commit e1e9ac23f4
11 changed files with 89 additions and 13 deletions

View File

@ -168,6 +168,7 @@ class ContainersController(base.Controller):
'rename': ['POST'], 'rename': ['POST'],
'attach': ['GET'], 'attach': ['GET'],
'resize': ['POST'], 'resize': ['POST'],
'resize_container': ['POST'],
'top': ['GET'], 'top': ['GET'],
'get_archive': ['GET'], 'get_archive': ['GET'],
'put_archive': ['POST'], 'put_archive': ['POST'],
@ -597,6 +598,31 @@ class ContainersController(base.Controller):
return view.format_container(context, pecan.request.host_url, return view.format_container(context, pecan.request.host_url,
container) container)
@base.Controller.api_version("1.19")
@pecan.expose('json')
@exception.wrap_pecan_controller_exception
@validation.validated(schema.container_update)
def resize_container(self, container_ident, **kwargs):
"""Resize an existing container.
:param container_ident: UUID or name of a container.
:param kwargs: cpu/memory to be updated.
"""
container = utils.get_container(container_ident)
check_policy_on_container(container.as_dict(),
"container:resize_container")
utils.validate_container_state(container, 'resize_container')
if 'memory' in kwargs:
kwargs['memory'] = str(kwargs['memory'])
if 'cpu' in kwargs:
kwargs['cpu'] = float(kwargs['cpu'])
context = pecan.request.context
compute_api = pecan.request.compute_api
compute_api.resize_container(context, container, kwargs)
pecan.response.status = 202
return view.format_container(context, pecan.request.host_url,
container)
@pecan.expose('json') @pecan.expose('json')
@exception.wrap_pecan_controller_exception @exception.wrap_pecan_controller_exception
@validation.validate_query_param(pecan.request, schema.query_param_delete) @validation.validate_query_param(pecan.request, schema.query_param_delete)

View File

@ -51,10 +51,11 @@ REST_API_VERSION_HISTORY = """REST API Version History:
* 1.16 - Modify restart_policy to capsule spec content * 1.16 - Modify restart_policy to capsule spec content
* 1.17 - Add support for detaching ports * 1.17 - Add support for detaching ports
* 1.18 - Modify the response of network list * 1.18 - Modify the response of network list
* 1.19 - Intoduce container resize API
""" """
BASE_VER = '1.1' BASE_VER = '1.1'
CURRENT_MAX_VER = '1.18' CURRENT_MAX_VER = '1.19'
class Version(object): class Version(object):

View File

@ -161,3 +161,9 @@ user documentation.
} }
] ]
} }
1.19
----
Introduce an API endpoint for resizing a container, such as changing the
CPU or memory of the container.

View File

@ -418,6 +418,17 @@ rules = [
} }
] ]
), ),
policy.DocumentedRuleDefault(
name=CONTAINER % 'resize_container',
check_str=base.RULE_ADMIN_OR_OWNER,
description='Resize an existing container.',
operations=[
{
'path': '/v1/containers/{container_ident}/resize_container',
'method': 'POST'
}
]
),
] ]

View File

@ -80,7 +80,9 @@ VALID_STATES = {
'add_security_group': [consts.CREATED, consts.RUNNING, consts.STOPPED, 'add_security_group': [consts.CREATED, consts.RUNNING, consts.STOPPED,
consts.PAUSED], consts.PAUSED],
'remove_security_group': [consts.CREATED, consts.RUNNING, consts.STOPPED, 'remove_security_group': [consts.CREATED, consts.RUNNING, consts.STOPPED,
consts.PAUSED] consts.PAUSED],
'resize_container': [consts.CREATED, consts.RUNNING, consts.STOPPED,
consts.PAUSED]
} }
VALID_CONTAINER_FILED = { VALID_CONTAINER_FILED = {

View File

@ -236,3 +236,6 @@ class API(object):
def network_create(self, context, network): def network_create(self, context, network):
return self.rpcapi.network_create(context, network) return self.rpcapi.network_create(context, network)
def resize_container(self, context, container, *args):
return self.rpcapi.resize_container(context, container, *args)

View File

@ -1217,3 +1217,10 @@ class Manager(periodic_task.PeriodicTasks):
docker_network = self.driver.create_network(context, network) docker_network = self.driver.create_network(context, network)
network.network_id = docker_network['Id'] network.network_id = docker_network['Id']
network.save() network.save()
def resize_container(self, context, container, patch):
@utils.synchronized(container.uuid)
def do_container_resize():
self.container_update(context, container, patch)
utils.spawn_n(do_container_resize)

View File

@ -123,6 +123,10 @@ class API(rpc_service.API):
return self._call(container.host, 'container_update', return self._call(container.host, 'container_update',
container=container, patch=patch) container=container, patch=patch)
def resize_container(self, context, container, patch):
self._cast(container.host, 'resize_container',
container=container, patch=patch)
@check_container_host @check_container_host
def container_attach(self, context, container): def container_attach(self, context, container):
return self._call(container.host, 'container_attach', return self._call(container.host, 'container_attach',

View File

@ -26,7 +26,7 @@ from zun.tests.unit.db import base
PATH_PREFIX = '/v1' PATH_PREFIX = '/v1'
CURRENT_VERSION = "container 1.18" CURRENT_VERSION = "container 1.19"
class FunctionalTest(base.DbTestCase): class FunctionalTest(base.DbTestCase):

View File

@ -28,7 +28,7 @@ class TestRootController(api_base.FunctionalTest):
'default_version': 'default_version':
{'id': 'v1', {'id': 'v1',
'links': [{'href': 'http://localhost/v1/', 'rel': 'self'}], 'links': [{'href': 'http://localhost/v1/', 'rel': 'self'}],
'max_version': '1.18', 'max_version': '1.19',
'min_version': '1.1', 'min_version': '1.1',
'status': 'CURRENT'}, 'status': 'CURRENT'},
'description': 'Zun is an OpenStack project which ' 'description': 'Zun is an OpenStack project which '
@ -37,7 +37,7 @@ class TestRootController(api_base.FunctionalTest):
'versions': [{'id': 'v1', 'versions': [{'id': 'v1',
'links': [{'href': 'http://localhost/v1/', 'links': [{'href': 'http://localhost/v1/',
'rel': 'self'}], 'rel': 'self'}],
'max_version': '1.18', 'max_version': '1.19',
'min_version': '1.1', 'min_version': '1.1',
'status': 'CURRENT'}]} 'status': 'CURRENT'}]}

View File

@ -1524,10 +1524,8 @@ class TestContainerController(api_base.FunctionalTest):
@patch('zun.common.utils.validate_container_state') @patch('zun.common.utils.validate_container_state')
@patch('zun.compute.api.API.container_resize') @patch('zun.compute.api.API.container_resize')
@patch('zun.objects.Container.get_by_name') @patch('zun.objects.Container.get_by_name')
def test_resize_container_by_uuid(self, def test_resize_by_uuid(self, mock_get_by_uuid, mock_container_resize,
mock_get_by_uuid, mock_validate):
mock_container_resize,
mock_validate):
test_container_obj = objects.Container(self.context, test_container_obj = objects.Container(self.context,
**utils.get_test_container()) **utils.get_test_container())
mock_container_resize.return_value = test_container_obj mock_container_resize.return_value = test_container_obj
@ -1546,10 +1544,8 @@ class TestContainerController(api_base.FunctionalTest):
@patch('zun.common.utils.validate_container_state') @patch('zun.common.utils.validate_container_state')
@patch('zun.compute.api.API.container_resize') @patch('zun.compute.api.API.container_resize')
@patch('zun.objects.Container.get_by_uuid') @patch('zun.objects.Container.get_by_uuid')
def test_resize_container_with_exception(self, def test_resize_with_exception(self, mock_get_by_uuid,
mock_get_by_uuid, mock_container_resize, mock_validate):
mock_container_resize,
mock_validate):
mock_container_resize.return_value = "" mock_container_resize.return_value = ""
test_container = utils.get_test_container() test_container = utils.get_test_container()
test_container_obj = objects.Container(self.context, **test_container) test_container_obj = objects.Container(self.context, **test_container)
@ -1563,6 +1559,26 @@ class TestContainerController(api_base.FunctionalTest):
(container_uuid, 'resize'), body) (container_uuid, 'resize'), body)
self.assertTrue(mock_container_resize.called) self.assertTrue(mock_container_resize.called)
@patch('zun.common.utils.validate_container_state')
@patch('zun.compute.api.API.resize_container')
@patch('zun.objects.Container.get_by_name')
def test_resize_container(self, mock_get_by_uuid,
mock_resize_container, mock_validate):
test_container_obj = objects.Container(self.context,
**utils.get_test_container())
mock_resize_container.return_value = test_container_obj
test_container = utils.get_test_container()
test_container_obj = objects.Container(self.context, **test_container)
mock_get_by_uuid.return_value = test_container_obj
container_name = test_container.get('name')
url = '/v1/containers/%s/resize_container/' % container_name
params = {'cpu': 1, 'memory': '512'}
response = self.post(url, params)
self.assertEqual(202, response.status_int)
mock_resize_container.assert_called_once_with(
mock.ANY, test_container_obj, params)
@patch('zun.common.utils.validate_container_state') @patch('zun.common.utils.validate_container_state')
@patch('zun.compute.api.API.container_top') @patch('zun.compute.api.API.container_top')
@patch('zun.objects.Container.get_by_uuid') @patch('zun.objects.Container.get_by_uuid')