Merge "Support stop and delete container"
This commit is contained in:
commit
d7bda42363
@ -221,6 +221,8 @@ Delete a container
|
||||
|
||||
Delete a container. To delete a container in `Creating` or `Running`
|
||||
state, request to /v1/containers/{container_ident}?force=True
|
||||
To stop and delete a container, request to /v1/containers/{container
|
||||
_ident}?stop=True
|
||||
|
||||
Response Codes
|
||||
--------------
|
||||
@ -243,6 +245,7 @@ Request
|
||||
|
||||
- container_ident: container_ident
|
||||
- force: force
|
||||
- stop: stop
|
||||
|
||||
Response
|
||||
--------
|
||||
|
@ -89,6 +89,12 @@ stdout:
|
||||
in: query
|
||||
required: false
|
||||
type: boolean
|
||||
stop:
|
||||
description: |
|
||||
Whether or not stop a container firstly before deleting it.
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
tag:
|
||||
description: |
|
||||
The tag of the container image.
|
||||
|
@ -476,16 +476,39 @@ class ContainersController(base.Controller):
|
||||
except ValueError:
|
||||
msg = _('Valid force values are true, false, 0, 1, yes and no')
|
||||
raise exception.InvalidValue(msg)
|
||||
if not force:
|
||||
stop = kwargs.pop('stop', None)
|
||||
compute_api = pecan.request.compute_api
|
||||
if not force and stop is None:
|
||||
utils.validate_container_state(container, 'delete')
|
||||
else:
|
||||
elif force and stop is None:
|
||||
req_version = pecan.request.version
|
||||
min_version = versions.Version('', '', '', '1.7')
|
||||
if req_version >= min_version:
|
||||
policy.enforce(context, "container:delete_force",
|
||||
action="container:delete_force")
|
||||
utils.validate_container_state(container, 'delete_force')
|
||||
compute_api = pecan.request.compute_api
|
||||
utils.validate_container_state(container, 'delete_force')
|
||||
# Remove this line temporarily for tempest issues.
|
||||
# else:
|
||||
# raise exception.InvalidParamInVersion(param='force',
|
||||
# req_version=req_version,
|
||||
# min_version=min_version)
|
||||
elif stop is not None:
|
||||
req_version = pecan.request.version
|
||||
min_version = versions.Version('', '', '', '1.11')
|
||||
if req_version >= min_version:
|
||||
if stop:
|
||||
check_policy_on_container(container.as_dict(),
|
||||
"container:stop")
|
||||
utils.validate_container_state(container,
|
||||
'delete_after_stop')
|
||||
LOG.debug('Calling compute.container_stop with %s '
|
||||
'before delete',
|
||||
container.uuid)
|
||||
compute_api.container_stop(context, container, 10)
|
||||
else:
|
||||
raise exception.InvalidParamInVersion(param='stop',
|
||||
req_version=req_version,
|
||||
min_version=min_version)
|
||||
container.status = consts.DELETING
|
||||
compute_api.container_delete(context, container, force)
|
||||
pecan.response.status = 204
|
||||
|
@ -74,7 +74,8 @@ query_param_delete = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'force': parameter_types.boolean_extended,
|
||||
'all_tenants': parameter_types.boolean_extended
|
||||
'all_tenants': parameter_types.boolean_extended,
|
||||
'stop': parameter_types.boolean_extended
|
||||
},
|
||||
'additionalProperties': False
|
||||
}
|
||||
|
@ -44,10 +44,11 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
||||
* 1.9 - Add support set container's hostname
|
||||
* 1.10 - Make delete container async
|
||||
* 1.11 - Add mounts to container create
|
||||
* 1.12 - Add support to stop container before delete
|
||||
"""
|
||||
|
||||
BASE_VER = '1.1'
|
||||
CURRENT_MAX_VER = '1.11'
|
||||
CURRENT_MAX_VER = '1.12'
|
||||
|
||||
|
||||
class Version(object):
|
||||
|
@ -79,16 +79,19 @@ user documentation.
|
||||
|
||||
1.9
|
||||
---
|
||||
|
||||
Add a new attribute 'hostname' to the request to create a container.
|
||||
Users can use this attribute to specify container's hostname.
|
||||
|
||||
1.10
|
||||
----
|
||||
|
||||
Make container delete API async. Delete operation for a container
|
||||
can take long time, so making it async to improve user experience.
|
||||
|
||||
1.11
|
||||
----
|
||||
|
||||
Add a new attribute 'mounts' to the request to create a container.
|
||||
Users can use this attribute to specify one or multiple mounts for
|
||||
the container. Each mount could specify the source and destination.
|
||||
@ -97,3 +100,10 @@ user documentation.
|
||||
For examples:
|
||||
|
||||
[{'source': 'my-vol', 'destination': '/data'}]
|
||||
|
||||
1.12
|
||||
----
|
||||
|
||||
Add a new attribute 'stop' to the request to delete containers.
|
||||
Users can use this attribute to stop and delete the container without
|
||||
using the --force option.
|
||||
|
@ -48,6 +48,7 @@ VALID_STATES = {
|
||||
'delete_force': [consts.CREATED, consts.CREATING, consts.ERROR,
|
||||
consts.RUNNING, consts.STOPPED, consts.UNKNOWN,
|
||||
consts.DELETED],
|
||||
'delete_after_stop': [consts.RUNNING],
|
||||
'start': [consts.CREATED, consts.STOPPED, consts.ERROR],
|
||||
'stop': [consts.RUNNING],
|
||||
'reboot': [consts.CREATED, consts.RUNNING, consts.STOPPED, consts.ERROR],
|
||||
|
@ -27,7 +27,7 @@ from zun.tests.unit.db import base
|
||||
|
||||
|
||||
PATH_PREFIX = '/v1'
|
||||
CURRENT_VERSION = "container 1.11"
|
||||
CURRENT_VERSION = "container 1.12"
|
||||
|
||||
|
||||
class FunctionalTest(base.DbTestCase):
|
||||
|
@ -28,7 +28,7 @@ class TestRootController(api_base.FunctionalTest):
|
||||
'default_version':
|
||||
{'id': 'v1',
|
||||
'links': [{'href': 'http://localhost/v1/', 'rel': 'self'}],
|
||||
'max_version': '1.11',
|
||||
'max_version': '1.12',
|
||||
'min_version': '1.1',
|
||||
'status': 'CURRENT'},
|
||||
'description': 'Zun is an OpenStack project which '
|
||||
@ -37,7 +37,7 @@ class TestRootController(api_base.FunctionalTest):
|
||||
'versions': [{'id': 'v1',
|
||||
'links': [{'href': 'http://localhost/v1/',
|
||||
'rel': 'self'}],
|
||||
'max_version': '1.11',
|
||||
'max_version': '1.12',
|
||||
'min_version': '1.1',
|
||||
'status': 'CURRENT'}]}
|
||||
|
||||
|
@ -1323,6 +1323,24 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
context = mock_container_delete.call_args[0][0]
|
||||
self.assertIs(True, context.all_tenants)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.api.API.container_stop')
|
||||
@patch('zun.compute.api.API.container_delete')
|
||||
@patch('zun.objects.Container.get_by_uuid')
|
||||
def test_delete_container_by_uuid_with_stop(self, mock_get_by_uuid,
|
||||
mock_container_stop,
|
||||
mock_container_delete,
|
||||
mock_validate):
|
||||
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_uuid = test_container.get('uuid')
|
||||
response = self.delete('/v1/containers/%s?stop=True' %
|
||||
container_uuid)
|
||||
|
||||
self.assertEqual(204, response.status_int)
|
||||
|
||||
def test_delete_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
|
Loading…
x
Reference in New Issue
Block a user