Merge "Consolidate container_create and container_run"

This commit is contained in:
Jenkins 2017-09-11 07:02:29 +00:00 committed by Gerrit Code Review
commit 61421d45ce
6 changed files with 115 additions and 105 deletions

View File

@ -305,12 +305,11 @@ class ContainersController(base.Controller):
new_container = objects.Container(context, **container_dict)
new_container.create(context)
if run:
compute_api.container_run(context, new_container, extra_spec,
requested_networks)
else:
compute_api.container_create(context, new_container, extra_spec,
requested_networks)
kwargs = {}
kwargs['extra_spec'] = extra_spec
kwargs['requested_networks'] = requested_networks
kwargs['run'] = run
compute_api.container_create(context, new_container, **kwargs)
# Set the HTTP Location Header
pecan.response.location = link.build_url('containers',
new_container.uuid)

View File

@ -29,7 +29,7 @@ class API(object):
super(API, self).__init__()
def container_create(self, context, new_container, extra_spec,
requested_networks):
requested_networks, run):
host_state = None
try:
host_state = self._schedule_container(context, new_container,
@ -42,22 +42,7 @@ class API(object):
self.rpcapi.container_create(context, host_state['host'],
new_container, host_state['limits'],
requested_networks)
def container_run(self, context, new_container, extra_spec,
requested_networks):
host_state = None
try:
host_state = self._schedule_container(context, new_container,
extra_spec)
except Exception as exc:
new_container.status = consts.ERROR
new_container.status_reason = str(exc)
new_container.save(context)
return
self.rpcapi.container_run(context, host_state['host'], new_container,
host_state['limits'], requested_networks)
requested_networks, run)
def _schedule_container(self, context, new_container, extra_spec):
dests = self.scheduler_client.select_destinations(context,

View File

@ -56,23 +56,16 @@ class Manager(periodic_task.PeriodicTasks):
container.host = None
container.save(context)
def container_create(self, context, limits, requested_networks, container):
utils.spawn_n(self._do_container_create, context, container,
requested_networks, limits)
def container_create(self, context, limits, requested_networks, container,
run):
def do_container_create(run, context, *args):
created_container = self._do_container_create(context, *args)
if run and created_container:
self._do_container_start(context, created_container)
def container_run(self, context, limits, requested_networks, container):
utils.spawn_n(self._do_container_run, context, container,
utils.spawn_n(do_container_create, run, context, container,
requested_networks, limits)
def _do_container_run(self, context, container, requested_networks,
limits=None):
created_container = self._do_container_create(context,
container,
requested_networks,
limits)
if created_container:
self._do_container_start(context, created_container)
def _do_sandbox_cleanup(self, context, container):
sandbox_id = container.get_sandbox_id()
if sandbox_id is None:

View File

@ -56,14 +56,10 @@ class API(rpc_service.API):
transport, context, topic=zun.conf.CONF.compute.topic)
def container_create(self, context, host, container, limits,
requested_networks):
requested_networks, run):
self._cast(host, 'container_create', limits=limits,
requested_networks=requested_networks, container=container)
def container_run(self, context, host, container, limits,
requested_networks):
self._cast(host, 'container_run', limits=limits,
requested_networks=requested_networks, container=container)
requested_networks=requested_networks, container=container,
run=run)
@check_container_host
def container_delete(self, context, container, force):

View File

@ -28,11 +28,11 @@ CURRENT_VERSION = "container 1.7"
class TestContainerController(api_base.FunctionalTest):
@patch('zun.network.neutron.NeutronAPI.get_available_network')
@patch('zun.compute.api.API.container_run')
@patch('zun.compute.api.API.container_create')
@patch('zun.compute.api.API.image_search')
def test_run_container(self, mock_search, mock_container_run,
def test_run_container(self, mock_search, mock_container_create,
mock_neutron_get_network):
mock_container_run.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'
@ -45,13 +45,14 @@ class TestContainerController(api_base.FunctionalTest):
content_type='application/json')
self.assertEqual(202, response.status_int)
self.assertTrue(mock_container_run.called)
self.assertTrue(mock_container_create.called)
self.assertTrue(mock_container_create.call_args[1]['run'] is True)
mock_neutron_get_network.assert_called_once()
@patch('zun.compute.api.API.container_run')
@patch('zun.compute.api.API.container_create')
@patch('zun.compute.api.API.image_search')
def test_run_container_wrong_run_value(self, mock_search,
mock_container_run):
mock_container_create):
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'
'"environment": {"key1": "val1", "key2": "val2"}}')
@ -62,10 +63,10 @@ class TestContainerController(api_base.FunctionalTest):
content_type='application/json', headers=headers)
@patch('zun.network.neutron.NeutronAPI.get_available_network')
@patch('zun.compute.api.API.container_run')
@patch('zun.compute.api.API.container_create')
@patch('zun.compute.api.API.image_search')
def test_run_container_runtime(self, mock_search,
mock_container_run,
mock_container_create,
mock_neutron_get_network):
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'
@ -78,7 +79,8 @@ class TestContainerController(api_base.FunctionalTest):
headers=api_version)
self.assertEqual(202, response.status_int)
self.assertTrue(mock_container_run.called)
self.assertTrue(mock_container_create.called)
self.assertTrue(mock_container_create.call_args[1]['run'] is True)
mock_neutron_get_network.assert_called_once()
def test_run_container_runtime_wrong_api_version(self):
@ -107,12 +109,12 @@ class TestContainerController(api_base.FunctionalTest):
headers=api_version)
@patch('zun.network.neutron.NeutronAPI.get_available_network')
@patch('zun.compute.api.API.container_run')
@patch('zun.compute.api.API.container_create')
@patch('zun.compute.api.API.image_search')
def test_run_container_with_false(self, mock_search,
mock_container_run,
mock_container_create,
mock_neutron_get_network):
mock_container_run.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'
@ -123,14 +125,15 @@ class TestContainerController(api_base.FunctionalTest):
content_type='application/json',
headers=headers)
self.assertEqual(202, response.status_int)
self.assertFalse(mock_container_run.called)
self.assertTrue(mock_container_create.called)
self.assertTrue(mock_container_create.call_args[1]['run'] is False)
mock_neutron_get_network.assert_called_once()
@patch('zun.compute.api.API.container_run')
@patch('zun.compute.api.API.container_create')
@patch('zun.compute.api.API.image_search')
def test_run_container_with_wrong(self, mock_search,
mock_container_run):
mock_container_run.side_effect = exception.InvalidValue
mock_container_create):
mock_container_create.side_effect = exception.InvalidValue
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'
'"environment": {"key1": "val1", "key2": "val2"}}')
@ -138,15 +141,14 @@ class TestContainerController(api_base.FunctionalTest):
self.assertRaises(AppError, self.app.post, '/v1/containers?run=wrong',
params=params, content_type='application/json',
headers=headers)
self.assertTrue(mock_container_run.not_called)
self.assertTrue(mock_container_create.not_called)
@patch('zun.network.neutron.NeutronAPI.get_available_network')
@patch('zun.compute.api.API.container_create')
@patch('zun.compute.api.API.image_search')
def test_create_container(self, mock_search, mock_container_create,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'
'"environment": {"key1": "val1", "key2": "val2"}}')
@ -157,6 +159,7 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual(202, response.status_int)
self.assertTrue(mock_container_create.called)
self.assertTrue(mock_container_create.call_args[1]['run'] is False)
mock_neutron_get_network.assert_called_once()
@patch('zun.compute.api.API.container_create')
@ -179,7 +182,7 @@ class TestContainerController(api_base.FunctionalTest):
def test_create_container_image_not_found(self, mock_search,
mock_container_create,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
mock_search.side_effect = exception.ImageNotFound()
params = {"name": "MyDocker", "image": "not-found"}
@ -197,7 +200,7 @@ class TestContainerController(api_base.FunctionalTest):
def test_create_container_set_project_id_and_user_id(
self, mock_search, mock_container_create,
mock_neutron_get_network):
def _create_side_effect(cnxt, container, extra_spec, networks):
def _create_side_effect(cnxt, container, **kwargs):
self.assertEqual(self.context.project_id, container.project_id)
self.assertEqual(self.context.user_id, container.user_id)
return container
@ -218,7 +221,7 @@ class TestContainerController(api_base.FunctionalTest):
def test_create_container_resp_has_status_reason(self, mock_search,
mock_container_create,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
# Create a container with a command
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'
@ -241,7 +244,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_create,
mock_container_show,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_network = {'id': 'foo'}
mock_neutron_get_network.return_value = fake_network
# Create a container with a command
@ -268,7 +271,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual('512M', c.get('memory'))
self.assertEqual({"key1": "val1", "key2": "val2"},
c.get('environment'))
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_network['id'], requested_networks[0]['network'])
@ -297,7 +301,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_create,
mock_container_show,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_network = {'id': 'foo'}
mock_neutron_get_network.return_value = fake_network
# Create a container with a command
@ -325,7 +329,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual({"key1": "val1", "key2": "val2"},
c.get('environment'))
mock_neutron_get_network.assert_called_once()
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_network['id'], requested_networks[0]['network'])
@ -337,7 +342,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_create,
mock_container_show,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_network = {'id': 'foo'}
mock_neutron_get_network.return_value = fake_network
# Create a container with a command
@ -363,7 +368,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual('512M', c.get('memory'))
self.assertEqual({}, c.get('environment'))
mock_neutron_get_network.assert_called_once()
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_network['id'], requested_networks[0]['network'])
@ -376,7 +382,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_show,
mock_neutron_get_network):
# No name param
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_network = {'id': 'foo'}
mock_neutron_get_network.return_value = fake_network
params = ('{"image": "ubuntu", "command": "env", "memory": "512",'
@ -402,7 +408,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual({"key1": "val1", "key2": "val2"},
c.get('environment'))
mock_neutron_get_network.assert_called_once()
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_network['id'], requested_networks[0]['network'])
@ -416,7 +423,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_create,
mock_container_show,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_network = {'id': 'foo'}
mock_neutron_get_network.return_value = fake_network
# Create a container with a command
@ -445,7 +452,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual({"Name": "no", "MaximumRetryCount": "0"},
c.get('restart_policy'))
mock_neutron_get_network.assert_called_once()
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_network['id'], requested_networks[0]['network'])
@ -459,7 +467,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_create,
mock_container_show,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_network = {'id': 'foo'}
mock_neutron_get_network.return_value = fake_network
# Create a container with a command
@ -488,7 +496,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual({"Name": "no", "MaximumRetryCount": "0"},
c.get('restart_policy'))
mock_neutron_get_network.assert_called_once()
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_network['id'], requested_networks[0]['network'])
@ -502,7 +511,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_create,
mock_container_show,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_network = {'id': 'foo'}
mock_neutron_get_network.return_value = fake_network
# Create a container with a command
@ -530,7 +539,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual({"Name": "no", "MaximumRetryCount": "0"},
c.get('restart_policy'))
mock_neutron_get_network.assert_called_once()
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_network['id'], requested_networks[0]['network'])
@ -544,7 +554,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_create,
mock_container_show,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_network = {'id': 'foo'}
mock_neutron_get_network.return_value = fake_network
# Create a container with a command
@ -573,7 +583,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual({"Name": "unless-stopped", "MaximumRetryCount": "0"},
c.get('restart_policy'))
mock_neutron_get_network.assert_called_once()
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_network['id'], requested_networks[0]['network'])
@ -588,7 +599,7 @@ class TestContainerController(api_base.FunctionalTest):
self, mock_search, mock_container_delete, mock_container_create,
mock_container_show, mock_ensure_port_usable, mock_get_port,
mock_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
fake_port = {'network_id': 'foo', 'id': 'bar'}
fake_private_network = {'router:external': False, 'shared': False}
mock_get_port.return_value = fake_port
@ -618,7 +629,8 @@ class TestContainerController(api_base.FunctionalTest):
self.assertEqual('512M', c.get('memory'))
self.assertEqual({"key1": "val1", "key2": "val2"},
c.get('environment'))
requested_networks = mock_container_create.call_args[0][3]
requested_networks = \
mock_container_create.call_args[1]['requested_networks']
self.assertEqual(1, len(requested_networks))
self.assertEqual(fake_port['network_id'],
requested_networks[0]['network'])
@ -688,7 +700,7 @@ class TestContainerController(api_base.FunctionalTest):
mock_container_create,
mock_container_show,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
# Create a container with a command
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'
@ -1418,7 +1430,7 @@ class TestContainerController(api_base.FunctionalTest):
def test_create_container_resp_has_image_driver(self, mock_search,
mock_container_create,
mock_neutron_get_network):
mock_container_create.side_effect = lambda x, y, z, v: y
mock_container_create.side_effect = lambda x, y, **z: y
# Create a container with a command
params = ('{"name": "MyDocker", "image": "ubuntu",'
'"command": "env", "memory": "512",'

View File

@ -129,21 +129,26 @@ class TestManager(base.TestCase):
mock_fail.assert_called_once_with(
self.context, container, "Creation Failed", unset_host=True)
@mock.patch('zun.common.utils.spawn_n')
@mock.patch.object(Container, 'save')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(fake_driver, 'create')
@mock.patch.object(fake_driver, 'start')
def test_container_run(self, mock_start,
mock_create, mock_pull, mock_save):
mock_create, mock_pull, mock_save, mock_spawn_n):
container = Container(self.context, **utils.get_test_container())
image = {'image': 'repo', 'path': 'out_path', 'driver': 'glance'}
mock_create.return_value = container
mock_pull.return_value = image, False
mock_spawn_n.side_effect = lambda f, *x, **y: f(*x, **y)
container.status = 'Stopped'
self.compute_manager._resource_tracker = FakeResourceTracker()
networks = []
self.compute_manager._do_container_run(self.context, container,
networks)
self.compute_manager.container_create(
self.context,
requested_networks=networks,
container=container,
limits=None, run=True)
mock_save.assert_called_with(self.context)
mock_pull.assert_any_call(self.context, container.image, 'latest',
'always', 'glance')
@ -151,87 +156,107 @@ class TestManager(base.TestCase):
networks)
mock_start.assert_called_once_with(self.context, container)
@mock.patch('zun.common.utils.spawn_n')
@mock.patch.object(Container, 'save')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(manager.Manager, '_fail_container')
def test_container_run_image_not_found(self, mock_fail,
mock_pull, mock_save):
mock_pull, mock_save,
mock_spawn_n):
container_dict = utils.get_test_container(
image='test:latest', image_driver='docker',
image_pull_policy='ifnotpresent')
container = Container(self.context, **container_dict)
mock_pull.side_effect = exception.ImageNotFound(
message="Image Not Found")
mock_spawn_n.side_effect = lambda f, *x, **y: f(*x, **y)
networks = []
self.compute_manager._do_container_run(self.context,
container,
networks)
self.compute_manager.container_create(
self.context,
requested_networks=networks,
container=container,
limits=None, run=True)
mock_save.assert_called_with(self.context)
mock_fail.assert_called_with(self.context,
container, 'Image Not Found')
mock_pull.assert_called_once_with(self.context, 'test', 'latest',
'ifnotpresent', 'docker')
@mock.patch('zun.common.utils.spawn_n')
@mock.patch.object(Container, 'save')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(manager.Manager, '_fail_container')
def test_container_run_image_pull_exception_raised(self, mock_fail,
mock_pull, mock_save):
mock_pull, mock_save,
mock_spawn_n):
container_dict = utils.get_test_container(
image='test:latest', image_driver='docker',
image_pull_policy='ifnotpresent')
container = Container(self.context, **container_dict)
mock_pull.side_effect = exception.ZunException(
message="Image Not Found")
mock_spawn_n.side_effect = lambda f, *x, **y: f(*x, **y)
networks = []
self.compute_manager._do_container_run(self.context,
container,
networks)
self.compute_manager.container_create(
self.context,
requested_networks=networks,
container=container,
limits=None, run=True)
mock_save.assert_called_with(self.context)
mock_fail.assert_called_with(self.context,
container, 'Image Not Found')
mock_pull.assert_called_once_with(self.context, 'test', 'latest',
'ifnotpresent', 'docker')
@mock.patch('zun.common.utils.spawn_n')
@mock.patch.object(Container, 'save')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(manager.Manager, '_fail_container')
def test_container_run_image_pull_docker_error(self, mock_fail,
mock_pull, mock_save):
mock_pull, mock_save,
mock_spawn_n):
container_dict = utils.get_test_container(
image='test:latest', image_driver='docker',
image_pull_policy='ifnotpresent')
container = Container(self.context, **container_dict)
mock_pull.side_effect = exception.DockerError(
message="Docker Error occurred")
mock_spawn_n.side_effect = lambda f, *x, **y: f(*x, **y)
networks = []
self.compute_manager._do_container_run(self.context,
container,
networks)
self.compute_manager.container_create(
self.context,
requested_networks=networks,
container=container,
limits=None, run=True)
mock_save.assert_called_with(self.context)
mock_fail.assert_called_with(self.context,
container, 'Docker Error occurred')
mock_pull.assert_called_once_with(self.context, 'test', 'latest',
'ifnotpresent', 'docker')
@mock.patch('zun.common.utils.spawn_n')
@mock.patch.object(Container, 'save')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(manager.Manager, '_fail_container')
@mock.patch.object(fake_driver, 'create')
def test_container_run_create_raises_docker_error(self, mock_create,
mock_fail,
mock_pull, mock_save):
mock_pull, mock_save,
mock_spawn_n):
container = Container(self.context, **utils.get_test_container())
image = {'image': 'repo', 'path': 'out_path', 'driver': 'glance',
'repo': 'test', 'tag': 'testtag'}
mock_pull.return_value = image, True
mock_create.side_effect = exception.DockerError(
message="Docker Error occurred")
mock_spawn_n.side_effect = lambda f, *x, **y: f(*x, **y)
self.compute_manager._resource_tracker = FakeResourceTracker()
networks = []
self.compute_manager._do_container_run(self.context,
container,
networks)
self.compute_manager.container_create(
self.context,
requested_networks=networks,
container=container,
limits=None, run=True)
mock_save.assert_called_with(self.context)
mock_fail.assert_called_with(
self.context, container, 'Docker Error occurred', unset_host=True)