Merge "Make start/stop/pause/unpause/restart/kill action async"
This commit is contained in:
commit
62482a6acc
@ -14,6 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import strutils
|
||||
from oslo_utils import timeutils
|
||||
import pecan
|
||||
from pecan import rest
|
||||
@ -28,6 +29,7 @@ from zun.common import exception
|
||||
from zun.common.i18n import _LE
|
||||
from zun.common import name_generator
|
||||
from zun.common import policy
|
||||
from zun.common import utils
|
||||
from zun.common import validation
|
||||
from zun import objects
|
||||
from zun.objects import fields
|
||||
@ -330,6 +332,9 @@ class ContainersController(rest.RestController):
|
||||
"""
|
||||
container = _get_container(container_id)
|
||||
check_policy_on_container(container.as_dict(), "container:delete")
|
||||
force = strutils.bool_from_string(force, strict=True)
|
||||
if not force:
|
||||
utils.validate_container_state(container, 'delete')
|
||||
context = pecan.request.context
|
||||
pecan.request.rpcapi.container_delete(context, container, force)
|
||||
container.destroy()
|
||||
@ -340,57 +345,60 @@ class ContainersController(rest.RestController):
|
||||
def start(self, container_id, **kw):
|
||||
container = _get_container(container_id)
|
||||
check_policy_on_container(container.as_dict(), "container:start")
|
||||
utils.validate_container_state(container, 'start')
|
||||
LOG.debug('Calling compute.container_start with %s',
|
||||
container.uuid)
|
||||
context = pecan.request.context
|
||||
container = pecan.request.rpcapi.container_start(context, container)
|
||||
return Container.convert_with_links(container.as_dict())
|
||||
pecan.request.rpcapi.container_start(context, container)
|
||||
pecan.response.status = 202
|
||||
|
||||
@pecan.expose('json')
|
||||
@exception.wrap_pecan_controller_exception
|
||||
def stop(self, container_id, timeout=None, **kw):
|
||||
container = _get_container(container_id)
|
||||
check_policy_on_container(container.as_dict(), "container:stop")
|
||||
utils.validate_container_state(container, 'stop')
|
||||
LOG.debug('Calling compute.container_stop with %s' %
|
||||
container.uuid)
|
||||
context = pecan.request.context
|
||||
container = pecan.request.rpcapi.container_stop(context, container,
|
||||
timeout)
|
||||
return Container.convert_with_links(container.as_dict())
|
||||
pecan.request.rpcapi.container_stop(context, container, timeout)
|
||||
pecan.response.status = 202
|
||||
|
||||
@pecan.expose('json')
|
||||
@exception.wrap_pecan_controller_exception
|
||||
def reboot(self, container_id, timeout=None, **kw):
|
||||
container = _get_container(container_id)
|
||||
check_policy_on_container(container.as_dict(), "container:reboot")
|
||||
utils.validate_container_state(container, 'reboot')
|
||||
LOG.debug('Calling compute.container_reboot with %s' %
|
||||
container.uuid)
|
||||
context = pecan.request.context
|
||||
container = pecan.request.rpcapi.container_reboot(context, container,
|
||||
timeout)
|
||||
return Container.convert_with_links(container.as_dict())
|
||||
pecan.request.rpcapi.container_reboot(context, container, timeout)
|
||||
pecan.response.status = 202
|
||||
|
||||
@pecan.expose('json')
|
||||
@exception.wrap_pecan_controller_exception
|
||||
def pause(self, container_id, **kw):
|
||||
container = _get_container(container_id)
|
||||
check_policy_on_container(container.as_dict(), "container:pause")
|
||||
utils.validate_container_state(container, 'pause')
|
||||
LOG.debug('Calling compute.container_pause with %s' %
|
||||
container.uuid)
|
||||
context = pecan.request.context
|
||||
container = pecan.request.rpcapi.container_pause(context, container)
|
||||
return Container.convert_with_links(container.as_dict())
|
||||
pecan.request.rpcapi.container_pause(context, container)
|
||||
pecan.response.status = 202
|
||||
|
||||
@pecan.expose('json')
|
||||
@exception.wrap_pecan_controller_exception
|
||||
def unpause(self, container_id, **kw):
|
||||
container = _get_container(container_id)
|
||||
check_policy_on_container(container.as_dict(), "container:unpause")
|
||||
utils.validate_container_state(container, 'unpause')
|
||||
LOG.debug('Calling compute.container_unpause with %s' %
|
||||
container.uuid)
|
||||
context = pecan.request.context
|
||||
container = pecan.request.rpcapi.container_unpause(context, container)
|
||||
return Container.convert_with_links(container.as_dict())
|
||||
pecan.request.rpcapi.container_unpause(context, container)
|
||||
pecan.response.status = 202
|
||||
|
||||
@pecan.expose('json')
|
||||
@exception.wrap_pecan_controller_exception
|
||||
@ -407,6 +415,7 @@ class ContainersController(rest.RestController):
|
||||
def execute(self, container_id, **kw):
|
||||
container = _get_container(container_id)
|
||||
check_policy_on_container(container.as_dict(), "container:execute")
|
||||
utils.validate_container_state(container, 'execute')
|
||||
LOG.debug('Calling compute.container_exec with %s command %s'
|
||||
% (container.uuid, kw['command']))
|
||||
context = pecan.request.context
|
||||
@ -418,9 +427,10 @@ class ContainersController(rest.RestController):
|
||||
def kill(self, container_id, **kw):
|
||||
container = _get_container(container_id)
|
||||
check_policy_on_container(container.as_dict(), "container:kill")
|
||||
utils.validate_container_state(container, 'kill')
|
||||
LOG.debug('Calling compute.container_kill with %s signal %s'
|
||||
% (container.uuid, kw.get('signal', kw.get('signal'))))
|
||||
context = pecan.request.context
|
||||
container = pecan.request.rpcapi.container_kill(context, container,
|
||||
kw.get('signal'))
|
||||
return Container.convert_with_links(container.as_dict())
|
||||
pecan.request.rpcapi.container_kill(context, container,
|
||||
kw.get('signal', None))
|
||||
pecan.response.status = 202
|
||||
|
@ -35,6 +35,26 @@ from zun.common.i18n import _LW
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
VALID_STATES = {
|
||||
'delete': ['Stopped', 'Error'],
|
||||
'start': ['Stopped'],
|
||||
'stop': ['Running'],
|
||||
'reboot': ['Running', 'Stopped'],
|
||||
'pause': ['Running'],
|
||||
'unpause': ['Paused'],
|
||||
'kill': ['Running'],
|
||||
'execute': ['Running'],
|
||||
}
|
||||
|
||||
|
||||
def validate_container_state(container, action):
|
||||
if container.status not in VALID_STATES[action]:
|
||||
raise exception.InvalidStateException(
|
||||
id=container.uuid,
|
||||
action=action,
|
||||
actual_state=container.status)
|
||||
|
||||
|
||||
def safe_rstrip(value, chars=None):
|
||||
"""Removes trailing characters from a string if that does not make it empty
|
||||
|
||||
|
@ -16,7 +16,6 @@ import six
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import strutils
|
||||
|
||||
from zun.common import exception
|
||||
from zun.common.i18n import _LE
|
||||
@ -29,17 +28,6 @@ from zun.objects import fields
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
VALID_STATES = {
|
||||
'delete': ['Stopped', 'Error'],
|
||||
'start': ['Stopped'],
|
||||
'stop': ['Running'],
|
||||
'reboot': ['Running', 'Stopped'],
|
||||
'pause': ['Running'],
|
||||
'unpause': ['Paused'],
|
||||
'kill': ['Running'],
|
||||
'exec': ['Running'],
|
||||
}
|
||||
|
||||
|
||||
class Manager(object):
|
||||
'''Manages the running containers.'''
|
||||
@ -54,17 +42,9 @@ class Manager(object):
|
||||
container.task_state = None
|
||||
container.save()
|
||||
|
||||
def _validate_container_state(self, container, action):
|
||||
if container.status not in VALID_STATES[action]:
|
||||
raise exception.InvalidStateException(
|
||||
id=container.uuid,
|
||||
action=action,
|
||||
actual_state=container.status)
|
||||
|
||||
def container_create(self, context, container):
|
||||
utils.spawn_n(self._do_container_create, context, container)
|
||||
|
||||
@translate_exception
|
||||
def container_run(self, context, container):
|
||||
utils.spawn_n(self._do_container_run, context, container)
|
||||
|
||||
@ -156,32 +136,28 @@ class Manager(object):
|
||||
self._fail_container(container, six.text_type(e))
|
||||
return
|
||||
|
||||
def _do_container_start(self, context, container):
|
||||
def _do_container_start(self, context, container, reraise=False):
|
||||
LOG.debug('Starting container: %s', container.uuid)
|
||||
try:
|
||||
# Although we dont need this validation, but i still
|
||||
# keep it for extra surity
|
||||
self._validate_container_state(container, 'start')
|
||||
container = self.driver.start(container)
|
||||
container.save()
|
||||
return container
|
||||
except exception.DockerError as e:
|
||||
LOG.error(_LE("Error occurred while calling Docker start API: %s"),
|
||||
six.text_type(e))
|
||||
self._fail_container(container, six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.error(_LE(
|
||||
"Error occurred while calling Docker start API: %s"),
|
||||
six.text_type(e))
|
||||
self._fail_container(container, six.text_type(e))
|
||||
except Exception as e:
|
||||
LOG.exception(_LE("Unexpected exception: %s"), six.text_type(e))
|
||||
self._fail_container(container, six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.exception(_LE("Unexpected exception: %s"),
|
||||
six.text_type(e))
|
||||
self._fail_container(container, six.text_type(e))
|
||||
|
||||
@translate_exception
|
||||
def container_delete(self, context, container, force):
|
||||
LOG.debug('Deleting container: %s', container.uuid)
|
||||
try:
|
||||
force = strutils.bool_from_string(force, strict=True)
|
||||
if not force:
|
||||
self._validate_container_state(container, 'delete')
|
||||
self.driver.delete(container, force)
|
||||
except exception.DockerError as e:
|
||||
LOG.error(_LE("Error occurred while calling Docker "
|
||||
@ -230,74 +206,83 @@ class Manager(object):
|
||||
LOG.exception(_LE("Unexpected exception: %s"), six.text_type(e))
|
||||
raise
|
||||
|
||||
@translate_exception
|
||||
def container_reboot(self, context, container, timeout):
|
||||
def _do_container_reboot(self, context, container, timeout, reraise=False):
|
||||
LOG.debug('Rebooting container: %s', container.uuid)
|
||||
try:
|
||||
self._validate_container_state(container, 'reboot')
|
||||
container = self.driver.reboot(container, timeout)
|
||||
container.save()
|
||||
return container
|
||||
except exception.DockerError as e:
|
||||
LOG.error(_LE("Error occurred while calling Docker reboot "
|
||||
"API: %s"), six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.error(_LE("Error occurred while calling Docker reboot "
|
||||
"API: %s"), six.text_type(e))
|
||||
except Exception as e:
|
||||
LOG.exception(_LE("Unexpected exception: %s"), six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.exception(_LE("Unexpected exception: %s"),
|
||||
six.text_type(e))
|
||||
|
||||
@translate_exception
|
||||
def container_stop(self, context, container, timeout):
|
||||
def container_reboot(self, context, container, timeout):
|
||||
utils.spawn_n(self._do_container_reboot, context, container, timeout)
|
||||
|
||||
def _do_container_stop(self, context, container, timeout, reraise=False):
|
||||
LOG.debug('Stopping container: %s', container.uuid)
|
||||
try:
|
||||
self._validate_container_state(container, 'stop')
|
||||
container = self.driver.stop(container, timeout)
|
||||
container.save()
|
||||
return container
|
||||
except exception.DockerError as e:
|
||||
LOG.error(_LE("Error occurred while calling Docker stop API: %s"),
|
||||
six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.error(_LE(
|
||||
"Error occurred while calling Docker stop API: %s"),
|
||||
six.text_type(e))
|
||||
except Exception as e:
|
||||
LOG.exception(_LE("Unexpected exception: %s"), six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.exception(_LE("Unexpected exception: %s"),
|
||||
six.text_type(e))
|
||||
|
||||
def container_stop(self, context, container, timeout):
|
||||
utils.spawn_n(self._do_container_stop, context, container, timeout)
|
||||
|
||||
@translate_exception
|
||||
def container_start(self, context, container):
|
||||
return self._do_container_start(context, container)
|
||||
utils.spawn_n(self._do_container_start, context, container)
|
||||
|
||||
@translate_exception
|
||||
def container_pause(self, context, container):
|
||||
def _do_container_pause(self, context, container, reraise=False):
|
||||
LOG.debug('Pausing container: %s', container.uuid)
|
||||
try:
|
||||
self._validate_container_state(container, 'pause')
|
||||
container = self.driver.pause(container)
|
||||
container.save()
|
||||
return container
|
||||
except exception.DockerError as e:
|
||||
LOG.error(_LE("Error occurred while calling Docker pause API: %s"),
|
||||
six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.error(_LE(
|
||||
"Error occurred while calling Docker pause API: %s"),
|
||||
six.text_type(e))
|
||||
except Exception as e:
|
||||
LOG.exception(_LE("Unexpected exception: %s,"), six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.exception(_LE("Unexpected exception: %s,"),
|
||||
six.text_type(e))
|
||||
|
||||
@translate_exception
|
||||
def container_unpause(self, context, container):
|
||||
def container_pause(self, context, container):
|
||||
utils.spawn_n(self._do_container_pause, context, container)
|
||||
|
||||
def _do_container_unpause(self, context, container, reraise=False):
|
||||
LOG.debug('Unpausing container: %s', container.uuid)
|
||||
try:
|
||||
self._validate_container_state(container, 'unpause')
|
||||
container = self.driver.unpause(container)
|
||||
container.save()
|
||||
return container
|
||||
except exception.DockerError as e:
|
||||
LOG.error(_LE("Error occurred while calling Docker unpause "
|
||||
"API: %s"),
|
||||
six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.error(_LE(
|
||||
"Error occurred while calling Docker unpause API: %s"),
|
||||
six.text_type(e))
|
||||
except Exception as e:
|
||||
LOG.exception(_LE("Unexpected exception: %s"), six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.exception(_LE("Unexpected exception: %s"),
|
||||
six.text_type(e))
|
||||
|
||||
def container_unpause(self, context, container):
|
||||
utils.spawn_n(self._do_container_unpause, context, container)
|
||||
|
||||
@translate_exception
|
||||
def container_logs(self, context, container):
|
||||
@ -317,7 +302,6 @@ class Manager(object):
|
||||
# TODO(hongbin): support exec command interactively
|
||||
LOG.debug('Executing command in container: %s', container.uuid)
|
||||
try:
|
||||
self._validate_container_state(container, 'exec')
|
||||
return self.driver.execute(container, command)
|
||||
except exception.DockerError as e:
|
||||
LOG.error(_LE("Error occurred while calling Docker exec API: %s"),
|
||||
@ -327,18 +311,20 @@ class Manager(object):
|
||||
LOG.exception(_LE("Unexpected exception: %s"), six.text_type(e))
|
||||
raise
|
||||
|
||||
@translate_exception
|
||||
def container_kill(self, context, container, signal):
|
||||
def _do_container_kill(self, context, container, signal, reraise=False):
|
||||
LOG.debug('kill signal to container: %s', container.uuid)
|
||||
try:
|
||||
self._validate_container_state(container, 'kill')
|
||||
container = self.driver.kill(container, signal)
|
||||
container.save()
|
||||
return container
|
||||
except exception.DockerError as e:
|
||||
LOG.error(_LE("Error occurred while calling Docker kill API: %s"),
|
||||
six.text_type(e))
|
||||
raise
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.error(_LE(
|
||||
"Error occurred while calling Docker kill API: %s"),
|
||||
six.text_type(e))
|
||||
|
||||
def container_kill(self, context, container, signal):
|
||||
utils.spawn_n(self._do_container_kill, context, container, signal)
|
||||
|
||||
def image_pull(self, context, image):
|
||||
utils.spawn_n(self._do_image_pull, context, image)
|
||||
|
@ -47,21 +47,21 @@ class API(rpc_service.API):
|
||||
return self._call('container_show', container=container)
|
||||
|
||||
def container_reboot(self, context, container, timeout):
|
||||
return self._call('container_reboot', container=container,
|
||||
return self._cast('container_reboot', container=container,
|
||||
timeout=timeout)
|
||||
|
||||
def container_stop(self, context, container, timeout):
|
||||
return self._call('container_stop', container=container,
|
||||
return self._cast('container_stop', container=container,
|
||||
timeout=timeout)
|
||||
|
||||
def container_start(self, context, container):
|
||||
return self._call('container_start', container=container)
|
||||
return self._cast('container_start', container=container)
|
||||
|
||||
def container_pause(self, context, container):
|
||||
return self._call('container_pause', container=container)
|
||||
return self._cast('container_pause', container=container)
|
||||
|
||||
def container_unpause(self, context, container):
|
||||
return self._call('container_unpause', container=container)
|
||||
return self._cast('container_unpause', container=container)
|
||||
|
||||
def container_logs(self, context, container):
|
||||
return self._call('container_logs', container=container)
|
||||
@ -71,7 +71,7 @@ class API(rpc_service.API):
|
||||
command=command)
|
||||
|
||||
def container_kill(self, context, container, signal):
|
||||
return self._call('container_kill', container=container,
|
||||
return self._cast('container_kill', container=container,
|
||||
signal=signal)
|
||||
|
||||
def image_show(self, context, image):
|
||||
|
@ -123,34 +123,28 @@ class ZunClient(rest_client.RestClient):
|
||||
self.container_uri(container_id, params=params), **kwargs)
|
||||
|
||||
def start_container(self, container_id, **kwargs):
|
||||
resp, body = self.post(
|
||||
return self.post(
|
||||
self.container_uri(container_id, action='start'), None, **kwargs)
|
||||
return self.deserialize(resp, body, container_model.ContainerEntity)
|
||||
|
||||
def stop_container(self, container_id, **kwargs):
|
||||
resp, body = self.post(
|
||||
return self.post(
|
||||
self.container_uri(container_id, action='stop'), None, *kwargs)
|
||||
return self.deserialize(resp, body, container_model.ContainerEntity)
|
||||
|
||||
def pause_container(self, container_id, **kwargs):
|
||||
resp, body = self.post(
|
||||
return self.post(
|
||||
self.container_uri(container_id, action='pause'), None, **kwargs)
|
||||
return self.deserialize(resp, body, container_model.ContainerEntity)
|
||||
|
||||
def unpause_container(self, container_id, **kwargs):
|
||||
resp, body = self.post(
|
||||
return self.post(
|
||||
self.container_uri(container_id, action='unpause'), None, **kwargs)
|
||||
return self.deserialize(resp, body, container_model.ContainerEntity)
|
||||
|
||||
def kill_container(self, container_id, **kwargs):
|
||||
resp, body = self.post(
|
||||
return self.post(
|
||||
self.container_uri(container_id, action='kill'), None, **kwargs)
|
||||
return self.deserialize(resp, body, container_model.ContainerEntity)
|
||||
|
||||
def reboot_container(self, container_id, **kwargs):
|
||||
resp, body = self.post(
|
||||
return self.post(
|
||||
self.container_uri(container_id, action='reboot'), None, **kwargs)
|
||||
return self.deserialize(resp, body, container_model.ContainerEntity)
|
||||
|
||||
def exec_container(self, container_id, command, **kwargs):
|
||||
return self.post(
|
||||
@ -166,25 +160,14 @@ class ZunClient(rest_client.RestClient):
|
||||
return self.deserialize(resp, body,
|
||||
service_model.ServiceCollection)
|
||||
|
||||
def ensure_container_created(self, container_id):
|
||||
def container_created():
|
||||
def ensure_container_in_desired_state(self, container_id, status):
|
||||
def is_container_in_desired_state():
|
||||
_, container = self.get_container(container_id)
|
||||
if container.status == 'Creating':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
utils.wait_for_condition(container_created)
|
||||
|
||||
def ensure_container_started(self, container_id):
|
||||
def container_started():
|
||||
_, container = self.get_container(container_id)
|
||||
if container.status == 'Running':
|
||||
if container.status == status:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
utils.wait_for_condition(container_started)
|
||||
utils.wait_for_condition(is_container_in_desired_state)
|
||||
|
||||
|
||||
class DockerClient(object):
|
||||
@ -195,3 +178,13 @@ class DockerClient(object):
|
||||
if container_id in info['Name']:
|
||||
return info
|
||||
return None
|
||||
|
||||
def ensure_container_pid_changed(self, container_id, pid):
|
||||
def is_pid_changed():
|
||||
container = self.get_container(container_id)
|
||||
new_pid = container.get('State').get('Pid')
|
||||
if pid != new_pid:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
utils.wait_for_condition(is_pid_changed)
|
||||
|
@ -81,37 +81,42 @@ class TestContainer(base.BaseZunTest):
|
||||
def test_start_stop_container(self):
|
||||
_, model = self._run_container()
|
||||
|
||||
resp, model = self.container_client.stop_container(model.uuid)
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual('Stopped', model.status)
|
||||
resp, _ = self.container_client.stop_container(model.uuid)
|
||||
self.assertEqual(202, resp.status)
|
||||
self.container_client.ensure_container_in_desired_state(
|
||||
model.uuid, 'Stopped')
|
||||
self.assertEqual('Stopped', self._get_container_state(model.uuid))
|
||||
|
||||
resp, model = self.container_client.start_container(model.uuid)
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual('Running', model.status)
|
||||
resp, _ = self.container_client.start_container(model.uuid)
|
||||
self.assertEqual(202, resp.status)
|
||||
self.container_client.ensure_container_in_desired_state(
|
||||
model.uuid, 'Running')
|
||||
self.assertEqual('Running', self._get_container_state(model.uuid))
|
||||
|
||||
@decorators.idempotent_id('b5f39756-8898-4e0e-a48b-dda0a06b66b6')
|
||||
def test_pause_unpause_container(self):
|
||||
_, model = self._run_container()
|
||||
|
||||
resp, model = self.container_client.pause_container(model.uuid)
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual('Paused', model.status)
|
||||
resp, _ = self.container_client.pause_container(model.uuid)
|
||||
self.assertEqual(202, resp.status)
|
||||
self.container_client.ensure_container_in_desired_state(
|
||||
model.uuid, 'Paused')
|
||||
self.assertEqual('Paused', self._get_container_state(model.uuid))
|
||||
|
||||
resp, model = self.container_client.unpause_container(model.uuid)
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual('Running', model.status)
|
||||
resp, _ = self.container_client.unpause_container(model.uuid)
|
||||
self.assertEqual(202, resp.status)
|
||||
self.container_client.ensure_container_in_desired_state(
|
||||
model.uuid, 'Running')
|
||||
self.assertEqual('Running', self._get_container_state(model.uuid))
|
||||
|
||||
@decorators.idempotent_id('6179a588-3d48-4372-9599-f228411d1449')
|
||||
def test_kill_container(self):
|
||||
_, model = self._run_container()
|
||||
|
||||
resp, model = self.container_client.kill_container(model.uuid)
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual('Stopped', model.status)
|
||||
resp, _ = self.container_client.kill_container(model.uuid)
|
||||
self.assertEqual(202, resp.status)
|
||||
self.container_client.ensure_container_in_desired_state(
|
||||
model.uuid, 'Stopped')
|
||||
self.assertEqual('Stopped', self._get_container_state(model.uuid))
|
||||
|
||||
@decorators.idempotent_id('c2e54321-0a70-4331-ba62-9dcaa75ac250')
|
||||
@ -120,9 +125,9 @@ class TestContainer(base.BaseZunTest):
|
||||
container = self.docker_client.get_container(model.uuid)
|
||||
pid = container.get('State').get('Pid')
|
||||
|
||||
resp, model = self.container_client.reboot_container(model.uuid)
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertEqual('Running', model.status)
|
||||
resp, _ = self.container_client.reboot_container(model.uuid)
|
||||
self.assertEqual(202, resp.status)
|
||||
self.docker_client.ensure_container_pid_changed(model.uuid, pid)
|
||||
self.assertEqual('Running', self._get_container_state(model.uuid))
|
||||
# assert pid is changed
|
||||
container = self.docker_client.get_container(model.uuid)
|
||||
@ -149,7 +154,8 @@ class TestContainer(base.BaseZunTest):
|
||||
resp, model = self.container_client.post_container(gen_model)
|
||||
self.assertEqual(202, resp.status)
|
||||
# Wait for container to finish creation
|
||||
self.container_client.ensure_container_created(model.uuid)
|
||||
self.container_client.ensure_container_in_desired_state(
|
||||
model.uuid, 'Stopped')
|
||||
|
||||
# Assert the container is created
|
||||
resp, model = self.container_client.get_container(model.uuid)
|
||||
@ -163,13 +169,13 @@ class TestContainer(base.BaseZunTest):
|
||||
resp, model = self.container_client.run_container(gen_model)
|
||||
self.assertEqual(202, resp.status)
|
||||
# Wait for container to started
|
||||
self.container_client.ensure_container_started(model.uuid)
|
||||
self.container_client.ensure_container_in_desired_state(
|
||||
model.uuid, 'Running')
|
||||
|
||||
# Assert the container is started
|
||||
resp, model = self.container_client.get_container(model.uuid)
|
||||
self.assertTrue(model.status in ['Running', 'Stopped'])
|
||||
self.assertTrue(self._get_container_state(model.uuid) in
|
||||
['Running', 'Stopped'])
|
||||
self.assertEqual('Running', model.status)
|
||||
self.assertEqual('Running', self._get_container_state(model.uuid))
|
||||
return resp, model
|
||||
|
||||
def _delete_container(self, container_id):
|
||||
|
@ -146,7 +146,8 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
self.assertEqual({"key1": "val1", "key2": "val2"},
|
||||
c.get('environment'))
|
||||
# Delete the container we created
|
||||
response = self.app.delete('/v1/containers/%s/' % c.get('uuid'))
|
||||
response = self.app.delete(
|
||||
'/v1/containers/%s?force=True' % c.get('uuid'))
|
||||
self.assertEqual(204, response.status_int)
|
||||
|
||||
response = self.app.get('/v1/containers/')
|
||||
@ -415,7 +416,7 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
self.assertEqual('new_name', test_container_obj.name)
|
||||
|
||||
def _action_test(self, container, action, ident_field,
|
||||
mock_container_action, query_param=''):
|
||||
mock_container_action, status_code, query_param=''):
|
||||
test_container_obj = objects.Container(self.context, **container)
|
||||
ident = container.get(ident_field)
|
||||
get_by_ident_loc = 'zun.objects.Container.get_by_%s' % ident_field
|
||||
@ -423,7 +424,7 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
mock_get_by_indent.return_value = test_container_obj
|
||||
response = self.app.post('/v1/containers/%s/%s/?%s' %
|
||||
(ident, action, query_param))
|
||||
self.assertEqual(200, response.status_int)
|
||||
self.assertEqual(status_code, response.status_int)
|
||||
|
||||
# Only PUT should work, others like GET should fail
|
||||
self.assertRaises(AppError, self.app.get,
|
||||
@ -437,98 +438,154 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
mock_container_action.assert_called_once_with(
|
||||
mock.ANY, test_container_obj)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_start')
|
||||
def test_start_by_uuid(self, mock_container_start):
|
||||
def test_start_by_uuid(self, mock_container_start, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_start.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'start', 'uuid',
|
||||
mock_container_start)
|
||||
mock_container_start, 202)
|
||||
|
||||
def test_start_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Running')
|
||||
with self.assertRaisesRegexp(
|
||||
AppError, "Cannot start container %s in Running state" % uuid):
|
||||
self.app.post('/v1/containers/%s/%s/' % (test_object.uuid,
|
||||
'start'))
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_start')
|
||||
def test_start_by_name(self, mock_container_start):
|
||||
def test_start_by_name(self, mock_container_start, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_start.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'start', 'name',
|
||||
mock_container_start)
|
||||
mock_container_start, 202)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_stop')
|
||||
def test_stop_by_uuid(self, mock_container_stop):
|
||||
def test_stop_by_uuid(self, mock_container_stop, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_stop.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'stop', 'uuid',
|
||||
mock_container_stop,
|
||||
mock_container_stop, 202,
|
||||
query_param='timeout=10')
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_stop')
|
||||
def test_stop_by_name(self, mock_container_stop):
|
||||
def test_stop_by_name(self, mock_container_stop, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_stop.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'stop', 'name',
|
||||
mock_container_stop,
|
||||
mock_container_stop, 202,
|
||||
query_param='timeout=10')
|
||||
|
||||
def test_stop_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Stopped')
|
||||
with self.assertRaisesRegexp(
|
||||
AppError, "Cannot stop container %s in Stopped state" % uuid):
|
||||
self.app.post('/v1/containers/%s/%s/' % (test_object.uuid,
|
||||
'stop'))
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_pause')
|
||||
def test_pause_by_uuid(self, mock_container_pause):
|
||||
def test_pause_by_uuid(self, mock_container_pause, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_pause.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'pause', 'uuid',
|
||||
mock_container_pause)
|
||||
mock_container_pause, 202)
|
||||
|
||||
def test_pause_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Stopped')
|
||||
with self.assertRaisesRegexp(
|
||||
AppError, "Cannot pause container %s in Stopped state" % uuid):
|
||||
self.app.post('/v1/containers/%s/%s/' % (test_object.uuid,
|
||||
'pause'))
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_pause')
|
||||
def test_pause_by_name(self, mock_container_pause):
|
||||
def test_pause_by_name(self, mock_container_pause, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_pause.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'pause', 'name',
|
||||
mock_container_pause)
|
||||
mock_container_pause, 202)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_unpause')
|
||||
def test_unpause_by_uuid(self, mock_container_unpause):
|
||||
def test_unpause_by_uuid(self, mock_container_unpause, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_unpause.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'unpause', 'uuid',
|
||||
mock_container_unpause)
|
||||
mock_container_unpause, 202)
|
||||
|
||||
def test_unpause_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Running')
|
||||
with self.assertRaisesRegexp(
|
||||
AppError,
|
||||
"Cannot unpause container %s in Running state" % uuid):
|
||||
self.app.post('/v1/containers/%s/%s/' % (test_object.uuid,
|
||||
'unpause'))
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_unpause')
|
||||
def test_unpause_by_name(self, mock_container_unpause):
|
||||
def test_unpause_by_name(self, mock_container_unpause, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_unpause.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'unpause', 'name',
|
||||
mock_container_unpause)
|
||||
mock_container_unpause, 202)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_reboot')
|
||||
def test_reboot_by_uuid(self, mock_container_reboot):
|
||||
def test_reboot_by_uuid(self, mock_container_reboot, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_reboot.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'reboot', 'uuid',
|
||||
mock_container_reboot,
|
||||
mock_container_reboot, 202,
|
||||
query_param='timeout=10')
|
||||
|
||||
def test_reboot_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Paused')
|
||||
with self.assertRaisesRegexp(
|
||||
AppError, "Cannot reboot container %s in Paused state" % uuid):
|
||||
self.app.post('/v1/containers/%s/%s/' % (test_object.uuid,
|
||||
'reboot'))
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_reboot')
|
||||
def test_reboot_by_name(self, mock_container_reboot):
|
||||
def test_reboot_by_name(self, mock_container_reboot, mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_reboot.return_value = test_container_obj
|
||||
test_container = utils.get_test_container()
|
||||
self._action_test(test_container, 'reboot', 'name',
|
||||
mock_container_reboot,
|
||||
mock_container_reboot, 202,
|
||||
query_param='timeout=10')
|
||||
|
||||
@patch('zun.compute.rpcapi.API.container_logs')
|
||||
@ -573,10 +630,11 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
'/v1/containers/%s/logs/' % container_uuid)
|
||||
self.assertFalse(mock_container_logs.called)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_exec')
|
||||
@patch('zun.objects.Container.get_by_uuid')
|
||||
def test_execute_command_by_uuid(self, mock_get_by_uuid,
|
||||
mock_container_exec):
|
||||
mock_container_exec, mock_validate):
|
||||
mock_container_exec.return_value = ""
|
||||
test_container = utils.get_test_container()
|
||||
test_container_obj = objects.Container(self.context, **test_container)
|
||||
@ -590,10 +648,22 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
mock_container_exec.assert_called_once_with(
|
||||
mock.ANY, test_container_obj, cmd['command'])
|
||||
|
||||
def test_exec_command_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Stopped')
|
||||
cmd = {'command': 'ls'}
|
||||
with self.assertRaisesRegexp(
|
||||
AppError,
|
||||
"Cannot execute container %s in Stopped state" % uuid):
|
||||
self.app.post('/v1/containers/%s/%s/' % (test_object.uuid,
|
||||
'execute'), cmd)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_exec')
|
||||
@patch('zun.objects.Container.get_by_name')
|
||||
def test_execute_command_by_name(self, mock_get_by_name,
|
||||
mock_container_exec):
|
||||
mock_container_exec, mock_validate):
|
||||
mock_container_exec.return_value = ""
|
||||
test_container = utils.get_test_container()
|
||||
test_container_obj = objects.Container(self.context, **test_container)
|
||||
@ -607,10 +677,11 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
mock_container_exec.assert_called_once_with(
|
||||
mock.ANY, test_container_obj, cmd['command'])
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_delete')
|
||||
@patch('zun.objects.Container.get_by_uuid')
|
||||
def test_delete_container_by_uuid(self, mock_get_by_uuid,
|
||||
mock_container_delete):
|
||||
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
|
||||
@ -624,10 +695,29 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
mock.ANY, test_container_obj, False)
|
||||
mock_destroy.assert_called_once_with()
|
||||
|
||||
def test_delete_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Running')
|
||||
with self.assertRaisesRegexp(
|
||||
AppError,
|
||||
"Cannot delete container %s in Running state" % uuid):
|
||||
self.app.delete('/v1/containers/%s' % (test_object.uuid))
|
||||
|
||||
@patch('zun.compute.rpcapi.API.container_delete')
|
||||
def test_delete_by_uuid_invalid_state_force_true(self, mock_delete):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Running')
|
||||
response = self.app.delete('/v1/containers/%s?force=True' % (
|
||||
test_object.uuid))
|
||||
self.assertEqual(204, response.status_int)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_delete')
|
||||
@patch('zun.objects.Container.get_by_name')
|
||||
def test_delete_container_by_name(self, mock_get_by_name,
|
||||
mock_container_delete):
|
||||
mock_container_delete, mock_validate):
|
||||
test_container = utils.get_test_container()
|
||||
test_container_obj = objects.Container(self.context, **test_container)
|
||||
mock_get_by_name.return_value = test_container_obj
|
||||
@ -641,10 +731,12 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
mock.ANY, test_container_obj, False)
|
||||
mock_destroy.assert_called_once_with()
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_kill')
|
||||
@patch('zun.objects.Container.get_by_uuid')
|
||||
def test_kill_container_by_uuid(self,
|
||||
mock_get_by_uuid, mock_container_kill):
|
||||
mock_get_by_uuid, mock_container_kill,
|
||||
mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_kill.return_value = test_container_obj
|
||||
@ -656,14 +748,26 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
url = '/v1/containers/%s/%s/' % (container_uuid, 'kill')
|
||||
cmd = {'signal': '9'}
|
||||
response = self.app.post(url, cmd)
|
||||
self.assertEqual(200, response.status_int)
|
||||
self.assertEqual(202, response.status_int)
|
||||
mock_container_kill.assert_called_once_with(
|
||||
mock.ANY, test_container_obj, cmd['signal'])
|
||||
|
||||
def test_kill_by_uuid_invalid_state(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
test_object = utils.create_test_container(context=self.context,
|
||||
uuid=uuid, status='Stopped')
|
||||
body = {'signal': 9}
|
||||
with self.assertRaisesRegexp(
|
||||
AppError, "Cannot kill container %s in Stopped state" % uuid):
|
||||
self.app.post('/v1/containers/%s/%s/' % (test_object.uuid,
|
||||
'kill'), body)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_kill')
|
||||
@patch('zun.objects.Container.get_by_name')
|
||||
def test_kill_container_by_name(self,
|
||||
mock_get_by_name, mock_container_kill):
|
||||
mock_get_by_name, mock_container_kill,
|
||||
mock_validate):
|
||||
test_container_obj = objects.Container(self.context,
|
||||
**utils.get_test_container())
|
||||
mock_container_kill.return_value = test_container_obj
|
||||
@ -675,15 +779,17 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
url = '/v1/containers/%s/%s/' % (container_name, 'kill')
|
||||
cmd = {'signal': '9'}
|
||||
response = self.app.post(url, cmd)
|
||||
self.assertEqual(200, response.status_int)
|
||||
self.assertEqual(202, response.status_int)
|
||||
mock_container_kill.assert_called_once_with(
|
||||
mock.ANY, test_container_obj, cmd['signal'])
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_kill')
|
||||
@patch('zun.objects.Container.get_by_uuid')
|
||||
def test_kill_container_which_not_exist(self,
|
||||
mock_get_by_uuid,
|
||||
mock_container_kill):
|
||||
mock_container_kill,
|
||||
mock_validate):
|
||||
mock_container_kill.return_value = ""
|
||||
test_container = utils.get_test_container()
|
||||
test_container_obj = objects.Container(self.context, **test_container)
|
||||
@ -695,11 +801,13 @@ class TestContainerController(api_base.FunctionalTest):
|
||||
'/v1/containers/%s/%s/' % (container_uuid, 'kill'))
|
||||
self.assertTrue(mock_container_kill.called)
|
||||
|
||||
@patch('zun.common.utils.validate_container_state')
|
||||
@patch('zun.compute.rpcapi.API.container_kill')
|
||||
@patch('zun.objects.Container.get_by_uuid')
|
||||
def test_kill_container_with_exception(self,
|
||||
mock_get_by_uuid,
|
||||
mock_container_kill):
|
||||
mock_container_kill,
|
||||
mock_validate):
|
||||
mock_container_kill.return_value = ""
|
||||
test_container = utils.get_test_container()
|
||||
test_container_obj = objects.Container(self.context, **test_container)
|
||||
|
@ -18,10 +18,12 @@ from zun.common import exception
|
||||
from zun.common import utils
|
||||
from zun.common.utils import check_container_id
|
||||
from zun.common.utils import translate_exception
|
||||
from zun.objects.container import Container
|
||||
from zun.tests import base
|
||||
from zun.tests.unit.db import utils as db_utils
|
||||
|
||||
|
||||
class TestUtils(base.BaseTestCase):
|
||||
class TestUtils(base.TestCase):
|
||||
"""Test cases for zun.common.utils"""
|
||||
|
||||
def test_check_container_id(self):
|
||||
@ -73,3 +75,31 @@ class TestUtils(base.BaseTestCase):
|
||||
self.assertTrue(utils.should_pull_image('always', False))
|
||||
self.assertTrue(utils.should_pull_image('ifnotpresent', False))
|
||||
self.assertFalse(utils.should_pull_image('ifnotpresent', True))
|
||||
|
||||
def test_validate_container_state(self):
|
||||
container = Container(self.context, **db_utils.get_test_container())
|
||||
container.status = 'Stopped'
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
utils.validate_container_state(container, 'stop')
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
utils.validate_container_state(container, 'pause')
|
||||
container.status = 'Running'
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
utils.validate_container_state(container, 'start')
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
utils.validate_container_state(container, 'unpause')
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
utils.validate_container_state(container, 'delete')
|
||||
self.assertIsNone(utils.validate_container_state(
|
||||
container, 'reboot'))
|
||||
container.status = 'Stopped'
|
||||
self.assertIsNone(utils.validate_container_state(
|
||||
container, 'reboot'))
|
||||
container.status = 'Running'
|
||||
self.assertIsNone(utils.validate_container_state(
|
||||
container, 'execute'))
|
||||
|
@ -42,33 +42,6 @@ class TestManager(base.TestCase):
|
||||
self.assertEqual("Creation Failed", container.status_reason)
|
||||
self.assertIsNone(container.task_state)
|
||||
|
||||
def test_validate_container_state(self):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
container.status = 'Stopped'
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
self.compute_manager._validate_container_state(container, 'stop')
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
self.compute_manager._validate_container_state(container, 'pause')
|
||||
container.status = 'Running'
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
self.compute_manager._validate_container_state(container, 'start')
|
||||
with self.assertRaisesRegexp(exception.InvalidStateException,
|
||||
"%s" % container.uuid):
|
||||
self.compute_manager._validate_container_state(container,
|
||||
'unpause')
|
||||
container.status = 'Running'
|
||||
self.assertIsNone(self.compute_manager._validate_container_state(
|
||||
container, 'reboot'))
|
||||
container.status = 'Stopped'
|
||||
self.assertIsNone(self.compute_manager._validate_container_state(
|
||||
container, 'reboot'))
|
||||
container.status = 'Running'
|
||||
self.assertIsNone(self.compute_manager._validate_container_state(
|
||||
container, 'exec'))
|
||||
|
||||
@mock.patch.object(Container, 'save')
|
||||
@mock.patch('zun.image.driver.pull_image')
|
||||
@mock.patch.object(fake_driver, 'create')
|
||||
@ -218,24 +191,14 @@ class TestManager(base.TestCase):
|
||||
mock_create.assert_called_once_with(container, None,
|
||||
{'name': 'nginx', 'path': None})
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'delete')
|
||||
def test_container_delete(self, mock_delete, mock_validate):
|
||||
def test_container_delete(self, mock_delete):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
self.compute_manager.container_delete(self. context, container, False)
|
||||
mock_delete.assert_called_once_with(container, False)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
def test_container_delete_invalid_state(self, mock_validate):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_validate.side_effect = exception.InvalidStateException
|
||||
self.assertRaises(exception.InvalidStateException,
|
||||
self.compute_manager.container_delete,
|
||||
self.context, container, False)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'delete')
|
||||
def test_container_delete_failed(self, mock_delete, mock_validate):
|
||||
def test_container_delete_failed(self, mock_delete):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_delete.side_effect = exception.DockerError
|
||||
self.assertRaises(exception.DockerError,
|
||||
@ -268,130 +231,78 @@ class TestManager(base.TestCase):
|
||||
self.compute_manager.container_show,
|
||||
self.context, container)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'reboot')
|
||||
def test_container_reboot(self, mock_reboot, mock_validate):
|
||||
def test_container_reboot(self, mock_reboot):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
self.compute_manager.container_reboot(self.context, container, 10)
|
||||
self.compute_manager._do_container_reboot(self.context, container, 10)
|
||||
mock_reboot.assert_called_once_with(container, 10)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
def test_container_reboot_invalid_state(self, mock_validate):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_validate.side_effect = exception.InvalidStateException
|
||||
self.assertRaises(exception.InvalidStateException,
|
||||
self.compute_manager.container_reboot,
|
||||
self.context, container, 10)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'reboot')
|
||||
def test_container_reboot_failed(self, mock_reboot, mock_validate):
|
||||
def test_container_reboot_failed(self, mock_reboot):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_reboot.side_effect = exception.DockerError
|
||||
self.assertRaises(exception.DockerError,
|
||||
self.compute_manager.container_reboot,
|
||||
self.context, container, 10)
|
||||
self.compute_manager._do_container_reboot,
|
||||
self.context, container, 10, reraise=True)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'stop')
|
||||
def test_container_stop(self, mock_stop, mock_validate):
|
||||
def test_container_stop(self, mock_stop):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
self.compute_manager.container_stop(self.context, container, 10)
|
||||
self.compute_manager._do_container_stop(self.context, container, 10)
|
||||
mock_stop.assert_called_once_with(container, 10)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
def test_container_stop_invalid_state(self, mock_validate):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_validate.side_effect = exception.InvalidStateException
|
||||
self.assertRaises(exception.InvalidStateException,
|
||||
self.compute_manager.container_stop,
|
||||
self.context, container, 10)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'stop')
|
||||
def test_container_stop_failed(self, mock_stop, mock_validate):
|
||||
def test_container_stop_failed(self, mock_stop):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_stop.side_effect = exception.DockerError
|
||||
self.assertRaises(exception.DockerError,
|
||||
self.compute_manager.container_stop,
|
||||
self.context, container, 10)
|
||||
self.compute_manager._do_container_stop,
|
||||
self.context, container, 10, reraise=True)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'start')
|
||||
def test_container_start(self, mock_start, mock_validate):
|
||||
def test_container_start(self, mock_start):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
self.compute_manager.container_start(self.context, container)
|
||||
self.compute_manager._do_container_start(self.context, container)
|
||||
mock_start.assert_called_once_with(container)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(manager.Manager, '_fail_container')
|
||||
def test_container_start_invalid_state(self, mock_fail, mock_validate):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_validate.side_effect = exception.InvalidStateException
|
||||
self.assertRaises(exception.InvalidStateException,
|
||||
self.compute_manager.container_start,
|
||||
self.context, container)
|
||||
mock_fail.assert_called_once()
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(manager.Manager, '_fail_container')
|
||||
@mock.patch.object(fake_driver, 'start')
|
||||
def test_container_start_failed(self, mock_start,
|
||||
mock_fail, mock_validate):
|
||||
mock_fail):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_start.side_effect = exception.DockerError
|
||||
self.assertRaises(exception.DockerError,
|
||||
self.compute_manager.container_start,
|
||||
self.context, container)
|
||||
self.compute_manager._do_container_start,
|
||||
self.context, container, reraise=True)
|
||||
mock_fail.assert_called_once()
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'pause')
|
||||
def test_container_pause(self, mock_pause, mock_validate):
|
||||
def test_container_pause(self, mock_pause):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
self.compute_manager.container_pause(self.context, container)
|
||||
self.compute_manager._do_container_pause(self.context, container)
|
||||
mock_pause.assert_called_once_with(container)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
def test_container_pause_invalid_state(self, mock_validate):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_validate.side_effect = exception.InvalidStateException
|
||||
self.assertRaises(exception.InvalidStateException,
|
||||
self.compute_manager.container_pause,
|
||||
self.context, container)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'pause')
|
||||
def test_container_pause_failed(self, mock_pause, mock_validate):
|
||||
def test_container_pause_failed(self, mock_pause):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_pause.side_effect = exception.DockerError
|
||||
self.assertRaises(exception.DockerError,
|
||||
self.compute_manager.container_pause,
|
||||
self.context, container)
|
||||
self.compute_manager._do_container_pause,
|
||||
self.context, container, reraise=True)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'unpause')
|
||||
def test_container_unpause(self, mock_unpause, mock_validate):
|
||||
def test_container_unpause(self, mock_unpause):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
self.compute_manager.container_unpause(self.context, container)
|
||||
self.compute_manager._do_container_unpause(self.context, container)
|
||||
mock_unpause.assert_called_once_with(container)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
def test_container_unpause_invalid_state(self, mock_validate):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_validate.side_effect = exception.InvalidStateException
|
||||
self.assertRaises(exception.InvalidStateException,
|
||||
self.compute_manager.container_unpause,
|
||||
self.context, container)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'unpause')
|
||||
def test_container_unpause_failed(self, mock_unpause, mock_validate):
|
||||
def test_container_unpause_failed(self, mock_unpause):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_unpause.side_effect = exception.DockerError
|
||||
self.assertRaises(exception.DockerError,
|
||||
self.compute_manager.container_unpause,
|
||||
self.context, container)
|
||||
self.compute_manager._do_container_unpause,
|
||||
self.context, container, reraise=True)
|
||||
|
||||
@mock.patch.object(fake_driver, 'show_logs')
|
||||
def test_container_logs(self, mock_logs):
|
||||
@ -414,14 +325,6 @@ class TestManager(base.TestCase):
|
||||
self.context, container, 'fake_cmd')
|
||||
mock_execute.assert_called_once_with(container, 'fake_cmd')
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
def test_container_execute_invalid_state(self, mock_validate):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_validate.side_effect = exception.InvalidStateException
|
||||
self.assertRaises(exception.InvalidStateException,
|
||||
self.compute_manager.container_exec,
|
||||
self.context, container, 'fake_cmd')
|
||||
|
||||
@mock.patch.object(fake_driver, 'execute')
|
||||
def test_container_execute_failed(self, mock_execute):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
@ -433,22 +336,13 @@ class TestManager(base.TestCase):
|
||||
@mock.patch.object(fake_driver, 'kill')
|
||||
def test_container_kill(self, mock_kill):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
self.compute_manager.container_kill(self.context, container, None)
|
||||
self.compute_manager._do_container_kill(self.context, container, None)
|
||||
mock_kill.assert_called_once_with(container, None)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
def test_container_kill_invalid_state(self, mock_validate):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_validate.side_effect = exception.InvalidStateException
|
||||
self.assertRaises(exception.InvalidStateException,
|
||||
self.compute_manager.container_kill,
|
||||
self.context, container, None)
|
||||
|
||||
@mock.patch.object(manager.Manager, '_validate_container_state')
|
||||
@mock.patch.object(fake_driver, 'kill')
|
||||
def test_container_kill_failed(self, mock_kill, mock_validate):
|
||||
def test_container_kill_failed(self, mock_kill):
|
||||
container = Container(self.context, **utils.get_test_container())
|
||||
mock_kill.side_effect = exception.DockerError
|
||||
self.assertRaises(exception.DockerError,
|
||||
self.compute_manager.container_kill,
|
||||
self.context, container, None)
|
||||
self.compute_manager._do_container_kill,
|
||||
self.context, container, None, reraise=True)
|
||||
|
Loading…
x
Reference in New Issue
Block a user