Merge "Make sandbox container optional"

This commit is contained in:
Jenkins 2017-07-27 03:57:44 +00:00 committed by Gerrit Code Review
commit 080f4fb00f
11 changed files with 191 additions and 154 deletions

View File

@ -40,6 +40,10 @@ class Manager(object):
self.driver = driver.load_container_driver(container_driver)
self.host = CONF.host
self._resource_tracker = None
if self._use_sandbox():
self.use_sandbox = True
else:
self.use_sandbox = False
def _fail_container(self, context, container, error, unset_host=False):
container.status = consts.ERROR
@ -66,9 +70,13 @@ class Manager(object):
if created_container:
self._do_container_start(context, created_container)
def _do_sandbox_cleanup(self, context, container, sandbox_id):
def _do_sandbox_cleanup(self, context, container):
sandbox_id = container.get_sandbox_id()
if sandbox_id is None:
return
try:
self.driver.delete_sandbox(context, container, sandbox_id)
self.driver.delete_sandbox(context, container)
except Exception as e:
LOG.error("Error occurred while deleting sandbox: %s",
six.text_type(e))
@ -90,10 +98,12 @@ class Manager(object):
self._fail_container(self, context, container, msg)
return
sandbox_id = self._create_sandbox(context, container,
requested_networks, reraise)
if sandbox_id is None:
return
sandbox_id = None
if self.use_sandbox:
sandbox_id = self._create_sandbox(context, container,
requested_networks, reraise)
if sandbox_id is None:
return
self._update_task_state(context, container, consts.IMAGE_PULLING)
repo, tag = utils.parse_image_name(container.image)
@ -108,21 +118,21 @@ class Manager(object):
except exception.ImageNotFound as e:
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.error(six.text_type(e))
self._do_sandbox_cleanup(context, container, sandbox_id)
self._do_sandbox_cleanup(context, container)
self._fail_container(context, container, six.text_type(e))
return
except exception.DockerError as e:
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.error("Error occurred while calling Docker image API: %s",
six.text_type(e))
self._do_sandbox_cleanup(context, container, sandbox_id)
self._do_sandbox_cleanup(context, container)
self._fail_container(context, container, six.text_type(e))
return
except Exception as e:
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.exception("Unexpected exception: %s",
six.text_type(e))
self._do_sandbox_cleanup(context, container, sandbox_id)
self._do_sandbox_cleanup(context, container)
self._fail_container(context, container, six.text_type(e))
return
@ -134,15 +144,14 @@ class Manager(object):
rt = self._get_resource_tracker()
with rt.container_claim(context, container, container.host,
limits):
container = self.driver.create(context, container,
sandbox_id, image)
container = self.driver.create(context, container, image)
self._update_task_state(context, container, None)
return container
except exception.DockerError as e:
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.error("Error occurred while calling Docker create API: %s",
six.text_type(e))
self._do_sandbox_cleanup(context, container, sandbox_id)
self._do_sandbox_cleanup(context, container)
self._fail_container(context, container, six.text_type(e),
unset_host=True)
return
@ -150,11 +159,24 @@ class Manager(object):
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.exception("Unexpected exception: %s",
six.text_type(e))
self._do_sandbox_cleanup(context, container, sandbox_id)
self._do_sandbox_cleanup(context, container)
self._fail_container(context, container, six.text_type(e),
unset_host=True)
return
def _use_sandbox(self):
if CONF.use_sandbox and self.driver.capabilities["support_sandbox"]:
return True
elif (not CONF.use_sandbox and
self.driver.capabilities["support_standalone"]):
return False
else:
raise exception.ZunException(_(
"The configuration of use_sandbox '%(use_sandbox)s' is not "
"supported by driver '%(driver)s'.") %
{'use_sandbox': CONF.use_sandbox,
'driver': self.driver})
def _create_sandbox(self, context, container, requested_networks,
reraise=False):
self._update_task_state(context, container, consts.SANDBOX_CREATING)
@ -202,7 +224,7 @@ class Manager(object):
self._update_task_state(context, container, consts.CONTAINER_DELETING)
reraise = not force
try:
self.driver.delete(container, force)
self.driver.delete(context, container, force)
except exception.DockerError as e:
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.error(("Error occurred while calling Docker "
@ -213,7 +235,9 @@ class Manager(object):
LOG.exception("Unexpected exception: %s", six.text_type(e))
self._fail_container(context, container, six.text_type(e))
self._delete_sandbox(context, container, reraise)
if self.use_sandbox:
self._delete_sandbox(context, container, reraise)
self._update_task_state(context, container, None)
container.destroy(context)
self._get_resource_tracker()
@ -224,12 +248,12 @@ class Manager(object):
return container
def _delete_sandbox(self, context, container, reraise=False):
sandbox_id = self.driver.get_sandbox_id(container)
sandbox_id = container.get_sandbox_id()
if sandbox_id:
self._update_task_state(context, container,
consts.SANDBOX_DELETING)
try:
self.driver.delete_sandbox(context, container, sandbox_id)
self.driver.delete_sandbox(context, container)
except Exception as e:
with excutils.save_and_reraise_exception(reraise=reraise):
LOG.exception("Unexpected exception: %s", six.text_type(e))
@ -242,9 +266,7 @@ class Manager(object):
def _add_security_group(self, context, container, security_group):
LOG.debug('Adding security_group to container: %s', container.uuid)
try:
sandbox_id = self.driver.get_sandbox_id(container)
self.driver.add_security_group(context, container, security_group,
sandbox_id=sandbox_id)
self.driver.add_security_group(context, container, security_group)
container.security_groups += [security_group]
container.save(context)
except Exception as e:

View File

@ -37,6 +37,16 @@ Interdependencies to other options:
cfg.StrOpt('floating_cpu_set',
default="",
help='Define the cpusets to be excluded from pinning'),
cfg.BoolOpt('use_sandbox',
default=False,
help="""Whether to use infra container. If set to True,
Zun will create an infra container that serves as a placeholder of a few
Linux namespaces (i.e. network namespace). Then, one or multiple containers
could join the namespaces of the infra container thus sharing resources inside
the sandbox (i.e. the network interface). This is typically used to group
a set of high-coupled containers into a unit. If set to False, infra container
won't be created.
""")
]

View File

@ -76,6 +76,10 @@ def wrap_docker_error(function):
class DockerDriver(driver.ContainerDriver):
"""Implementation of container drivers for Docker."""
capabilities = {
"support_sandbox": True,
"support_standalone": True,
}
def __init__(self):
super(DockerDriver, self).__init__()
@ -102,12 +106,24 @@ class DockerDriver(driver.ContainerDriver):
with docker_utils.docker_client() as docker:
return docker.images(repo, quiet)
def create(self, context, container, sandbox_id, image):
def create(self, context, container, image, requested_networks=None):
sandbox_id = container.get_sandbox_id()
network_standalone = False if sandbox_id else True
with docker_utils.docker_client() as docker:
network_api = zun_network.api(context=context, docker_api=docker)
name = container.name
image = container.image
LOG.debug('Creating container with image %(image)s name %(name)s',
{'image': image, 'name': name})
if requested_networks is None:
if network_standalone:
network = self._provision_network(context, container,
network_api)
requested_networks = [{'network': network['Name'],
'port': '',
'v4-fixed-ip': '',
'v6-fixed-ip': ''}]
kwargs = {
'name': self.get_container_name(container),
@ -120,12 +136,13 @@ class DockerDriver(driver.ContainerDriver):
}
host_config = {}
host_config['network_mode'] = 'container:%s' % sandbox_id
# TODO(hongbin): Uncomment this after docker-py add support for
# container mode for pid namespace.
# host_config['pid_mode'] = 'container:%s' % sandbox_id
host_config['ipc_mode'] = 'container:%s' % sandbox_id
host_config['volumes_from'] = sandbox_id
if sandbox_id:
host_config['network_mode'] = 'container:%s' % sandbox_id
# TODO(hongbin): Uncomment this after docker-py add support for
# container mode for pid namespace.
# host_config['pid_mode'] = 'container:%s' % sandbox_id
host_config['ipc_mode'] = 'container:%s' % sandbox_id
host_config['volumes_from'] = sandbox_id
if container.auto_remove:
host_config['auto_remove'] = container.auto_remove
if container.memory is not None:
@ -142,6 +159,12 @@ class DockerDriver(driver.ContainerDriver):
response = docker.create_container(image, **kwargs)
container.container_id = response['Id']
if network_standalone:
addresses = self._setup_network_for_container(
context, container, requested_networks, network_api)
container.addresses = addresses
container.status = consts.CREATED
container.status_reason = None
container.save(context)
@ -160,26 +183,32 @@ class DockerDriver(driver.ContainerDriver):
def _setup_network_for_container(self, context, container,
requested_networks, network_api):
sandbox_id = self.get_sandbox_id(container)
security_group_ids = self._get_security_group_ids(
context, container.security_groups)
# Container connects to the bridge network by default so disconnect
# the container from it before connecting it to neutron network.
# This avoids potential conflict between these two networks.
network_api.disconnect_container_from_network(container, 'bridge',
sandbox_id)
network_api.disconnect_container_from_network(container, 'bridge')
addresses = {}
for network in requested_networks:
network_name = network['network']
addrs = network_api.connect_container_to_network(
container, network_name, sandbox_id=sandbox_id,
security_groups=security_group_ids)
container, network_name, security_groups=security_group_ids)
addresses[network_name] = addrs
return addresses
def delete(self, container, force):
def delete(self, context, container, force):
teardown_network = True
if container.get_sandbox_id():
teardown_network = False
with docker_utils.docker_client() as docker:
if teardown_network:
network_api = zun_network.api(context=context,
docker_api=docker)
self._cleanup_network_for_container(container, network_api)
if container.container_id:
try:
docker.remove_container(container.container_id,
@ -189,11 +218,9 @@ class DockerDriver(driver.ContainerDriver):
return
raise
def _cleanup_network_for_container(self, container, network_api,
sandbox_id):
def _cleanup_network_for_container(self, container, network_api):
for name in container.addresses:
network_api.disconnect_container_from_network(container, name,
sandbox_id)
network_api.disconnect_container_from_network(container, name)
def list(self, context):
id_to_container_map = {}
@ -619,9 +646,13 @@ class DockerDriver(driver.ContainerDriver):
name = self.get_sandbox_name(container)
sandbox = docker.create_container(image, name=name,
hostname=name[:63])
self.set_sandbox_id(container, sandbox['Id'])
container.set_sandbox_id(sandbox['Id'])
addresses = self._setup_network_for_container(
context, container, requested_networks, network_api)
if addresses is None:
raise exception.ZunException(_(
"Unexpected missing of addresses"))
container.addresses = addresses
container.save(context)
@ -669,11 +700,11 @@ class DockerDriver(driver.ContainerDriver):
return docker_networks[0]
def delete_sandbox(self, context, container, sandbox_id):
def delete_sandbox(self, context, container):
sandbox_id = container.get_sandbox_id()
with docker_utils.docker_client() as docker:
network_api = zun_network.api(context=context, docker_api=docker)
self._cleanup_network_for_container(container, network_api,
sandbox_id)
self._cleanup_network_for_container(container, network_api)
try:
docker.remove_container(sandbox_id, force=True)
except errors.APIError as api_error:
@ -685,19 +716,6 @@ class DockerDriver(driver.ContainerDriver):
with docker_utils.docker_client() as docker:
docker.stop(sandbox_id)
def get_sandbox_id(self, container):
if container.meta:
return container.meta.get('sandbox_id', None)
else:
LOG.warning("Unexpected missing of sandbox_id")
return None
def set_sandbox_id(self, container, sandbox_id):
if container.meta is None:
container.meta = {'sandbox_id': sandbox_id}
else:
container.meta['sandbox_id'] = sandbox_id
def get_sandbox_name(self, container):
return 'zun-sandbox-' + container.uuid
@ -754,13 +772,18 @@ class DockerDriver(driver.ContainerDriver):
sandbox = docker.inspect_container(sandbox_id)
for network in sandbox["NetworkSettings"]["Networks"]:
network_api.add_security_groups_to_ports(
container, security_group_ids, sandbox_id)
container, security_group_ids)
def get_available_nodes(self):
return [self._host.get_hostname()]
class NovaDockerDriver(DockerDriver):
capabilities = {
"support_sandbox": True,
"support_standalone": False,
}
def add_security_group(self, context, container, security_group, **kwargs):
msg = "NovaDockerDriver does not support security_groups"
raise exception.ZunException(msg)
@ -839,7 +862,7 @@ class NovaDockerDriver(DockerDriver):
def get_addresses(self, context, container):
elevated = context.elevated()
novaclient = nova.NovaClient(elevated)
sandbox_id = self.get_sandbox_id(container)
sandbox_id = container.get_sandbox_id()
if sandbox_id:
server_name = self._find_server_by_container_id(sandbox_id)
if server_name:

View File

@ -68,7 +68,7 @@ class ContainerDriver(object):
"""Commit a container."""
raise NotImplementedError()
def delete(self, container, force):
def delete(self, context, container, force):
"""Delete a container."""
raise NotImplementedError()
@ -163,14 +163,6 @@ class ContainerDriver(object):
"""Stop a sandbox."""
raise NotImplementedError()
def get_sandbox_id(self, container):
"""Retrieve sandbox ID."""
raise NotImplementedError()
def set_sandbox_id(self, container, sandbox_id):
"""Set sandbox ID."""
raise NotImplementedError()
def get_sandbox_name(self, container):
"""Retrieve sandbox name."""
raise NotImplementedError()

View File

@ -116,15 +116,15 @@ class KuryrNetwork(network.Network):
return self.docker.networks(**kwargs)
def connect_container_to_network(self, container, network_name,
sandbox_id=None, security_groups=None):
security_groups=None):
"""Connect container to the network
This method will create a neutron port, retrieve the ip address(es)
of the port, and pass them to docker.connect_container_to_network.
"""
container_id = container.container_id
if sandbox_id:
container_id = sandbox_id
container_id = container.get_sandbox_id()
if not container_id:
container_id = container.container_id
network = self.inspect_network(network_name)
neutron_net_id = network['Options']['neutron.net.uuid']
@ -166,11 +166,10 @@ class KuryrNetwork(network.Network):
container_id, network_name, **kwargs)
return addresses
def disconnect_container_from_network(self, container, network_name,
sandbox_id=None):
container_id = container.container_id
if sandbox_id:
container_id = sandbox_id
def disconnect_container_from_network(self, container, network_name):
container_id = container.get_sandbox_id()
if not container_id:
container_id = container.container_id
neutron_ports = set()
if container.addresses:
@ -190,8 +189,11 @@ class KuryrNetwork(network.Network):
'or neutron tag extension does not supported or'
' not enabled.')
def add_security_groups_to_ports(self, container, security_group_ids,
sandbox_id=None):
def add_security_groups_to_ports(self, container, security_group_ids):
container_id = container.get_sandbox_id()
if not container_id:
container_id = container.container_id
port_ids = set()
for addrs_list in container.addresses.values():
for addr in addrs_list:

View File

@ -58,6 +58,6 @@ class Network(object):
**kwargs):
raise NotImplementedError()
def add_security_groups_to_ports(self, container, network_name,
security_group_ids, **kwargs):
def add_security_groups_to_ports(self, container, security_group_ids,
**kwargs):
raise NotImplementedError()

View File

@ -214,3 +214,15 @@ class Container(base.ZunPersistentObject, base.ZunObject):
if self.obj_attr_is_set(field) and \
getattr(self, field) != getattr(current, field):
setattr(self, field, getattr(current, field))
def get_sandbox_id(self):
if self.meta:
return self.meta.get('sandbox_id', None)
else:
return None
def set_sandbox_id(self, sandbox_id):
if self.meta is None:
self.meta = {'sandbox_id': sandbox_id}
else:
self.meta['sandbox_id'] = sandbox_id

View File

@ -55,13 +55,10 @@ class TestManager(base.TestCase):
@mock.patch.object(Container, 'save')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(fake_driver, 'create')
@mock.patch.object(fake_driver, 'create_sandbox')
def test_container_create(self, mock_create_sandbox, mock_create,
mock_pull, mock_save):
def test_container_create(self, mock_create, mock_pull, mock_save):
container = Container(self.context, **utils.get_test_container())
image = {'image': 'repo', 'path': 'out_path', 'driver': 'glance'}
mock_pull.return_value = image, False
mock_create_sandbox.return_value = 'fake_id'
self.compute_manager._resource_tracker = FakeResourceTracker()
networks = []
self.compute_manager._do_container_create(self.context, container,
@ -69,18 +66,15 @@ class TestManager(base.TestCase):
mock_save.assert_called_with(self.context)
mock_pull.assert_any_call(self.context, container.image, 'latest',
'always', 'glance')
mock_create.assert_called_once_with(self.context, container,
'fake_id', image)
mock_create.assert_called_once_with(self.context, container, image)
@mock.patch.object(Container, 'save')
@mock.patch.object(fake_driver, 'create_sandbox')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(manager.Manager, '_fail_container')
def test_container_create_pull_image_failed_docker_error(
self, mock_fail, mock_pull, mock_create_sandbox, mock_save):
self, mock_fail, mock_pull, mock_save):
container = Container(self.context, **utils.get_test_container())
mock_pull.side_effect = exception.DockerError("Pull Failed")
mock_create_sandbox.return_value = mock.MagicMock()
networks = []
self.compute_manager._do_container_create(self.context, container,
networks)
@ -88,14 +82,12 @@ class TestManager(base.TestCase):
container, "Pull Failed")
@mock.patch.object(Container, 'save')
@mock.patch.object(fake_driver, 'create_sandbox')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(manager.Manager, '_fail_container')
def test_container_create_pull_image_failed_image_not_found(
self, mock_fail, mock_pull, mock_create_sandbox, mock_save):
self, mock_fail, mock_pull, mock_save):
container = Container(self.context, **utils.get_test_container())
mock_pull.side_effect = exception.ImageNotFound("Image Not Found")
mock_create_sandbox.return_value = mock.MagicMock()
networks = []
self.compute_manager._do_container_create(self.context, container,
networks)
@ -103,15 +95,13 @@ class TestManager(base.TestCase):
container, "Image Not Found")
@mock.patch.object(Container, 'save')
@mock.patch.object(fake_driver, 'create_sandbox')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(manager.Manager, '_fail_container')
def test_container_create_pull_image_failed_zun_exception(
self, mock_fail, mock_pull, mock_create_sandbox, mock_save):
self, mock_fail, mock_pull, mock_save):
container = Container(self.context, **utils.get_test_container())
mock_pull.side_effect = exception.ZunException(
message="Image Not Found")
mock_create_sandbox.return_value = mock.MagicMock()
networks = []
self.compute_manager._do_container_create(self.context, container,
networks)
@ -121,17 +111,14 @@ class TestManager(base.TestCase):
@mock.patch.object(Container, 'save')
@mock.patch('zun.image.driver.pull_image')
@mock.patch.object(fake_driver, 'create')
@mock.patch.object(fake_driver, 'create_sandbox')
@mock.patch.object(manager.Manager, '_fail_container')
def test_container_create_docker_create_failed(self, mock_fail,
mock_create_sandbox,
mock_create, mock_pull,
mock_save):
container = Container(self.context, **utils.get_test_container())
image = {'image': 'repo', 'path': 'out_path', 'driver': 'glance'}
mock_pull.return_value = image, False
mock_create.side_effect = exception.DockerError("Creation Failed")
mock_create_sandbox.return_value = mock.MagicMock()
self.compute_manager._resource_tracker = FakeResourceTracker()
networks = []
self.compute_manager._do_container_create(self.context, container,
@ -157,8 +144,7 @@ class TestManager(base.TestCase):
mock_save.assert_called_with(self.context)
mock_pull.assert_any_call(self.context, container.image, 'latest',
'always', 'glance')
mock_create.assert_called_once_with(self.context, container,
'fake_sandbox', image)
mock_create.assert_called_once_with(self.context, container, image)
mock_start.assert_called_once_with(self.context, container)
@mock.patch.object(Container, 'save')
@ -166,7 +152,10 @@ class TestManager(base.TestCase):
@mock.patch.object(manager.Manager, '_fail_container')
def test_container_run_image_not_found(self, mock_fail,
mock_pull, mock_save):
container = Container(self.context, **utils.get_test_container())
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")
networks = []
@ -176,15 +165,18 @@ class TestManager(base.TestCase):
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, 'kubernetes/pause',
'latest', 'ifnotpresent', 'docker')
mock_pull.assert_called_once_with(self.context, 'test', 'latest',
'ifnotpresent', 'docker')
@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):
container = Container(self.context, **utils.get_test_container())
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")
networks = []
@ -194,15 +186,18 @@ class TestManager(base.TestCase):
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, 'kubernetes/pause',
'latest', 'ifnotpresent', 'docker')
mock_pull.assert_called_once_with(self.context, 'test', 'latest',
'ifnotpresent', 'docker')
@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):
container = Container(self.context, **utils.get_test_container())
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")
networks = []
@ -212,8 +207,8 @@ class TestManager(base.TestCase):
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, 'kubernetes/pause',
'latest', 'ifnotpresent', 'docker')
mock_pull.assert_called_once_with(self.context, 'test', 'latest',
'ifnotpresent', 'docker')
@mock.patch.object(Container, 'save')
@mock.patch('zun.image.driver.pull_image')
@ -237,8 +232,7 @@ class TestManager(base.TestCase):
mock_pull.assert_any_call(self.context, container.image, 'latest',
'always', 'glance')
mock_create.assert_called_once_with(
self.context, container, 'fake_sandbox',
{'name': 'nginx', 'path': None})
self.context, container, {'name': 'nginx', 'path': None})
@mock.patch.object(compute_node_tracker.ComputeNodeTracker,
'remove_usage_from_container')
@ -250,7 +244,7 @@ class TestManager(base.TestCase):
container = Container(self.context, **utils.get_test_container())
self.compute_manager.container_delete(self. context, container, False)
mock_save.assert_called_with(self.context)
mock_delete.assert_called_once_with(container, False)
mock_delete.assert_called_once_with(self.context, container, False)
mock_cnt_destroy.assert_called_once_with(self.context)
mock_remove_usage.assert_called_once_with(self.context, container,
True)
@ -272,14 +266,14 @@ class TestManager(base.TestCase):
@mock.patch.object(manager.Manager, '_fail_container')
@mock.patch.object(fake_driver, 'delete_sandbox')
@mock.patch.object(fake_driver, 'get_sandbox_id')
@mock.patch.object(Container, 'save')
@mock.patch.object(fake_driver, 'delete')
def test_container_delete_sandbox_failed(self, mock_delete, mock_save,
mock_sandbox, mock_delete_sandbox,
mock_delete_sandbox,
mock_fail):
self.compute_manager.use_sandbox = True
container = Container(self.context, **utils.get_test_container())
mock_sandbox.return_value = "sandbox_id"
container.set_sandbox_id("sandbox_id")
mock_delete_sandbox.side_effect = exception.ZunException(
message="Unexpected exception")
self.assertRaises(exception.ZunException,

View File

@ -79,20 +79,24 @@ class TestDockerDriver(base.DriverTestCase):
self.driver.images(repo='test')
self.mock_docker.images.assert_called_once_with('test', False)
@mock.patch('zun.network.kuryr_network.KuryrNetwork'
'.connect_container_to_network')
@mock.patch(
'zun.container.docker.driver.DockerDriver._get_security_group_ids')
@mock.patch('zun.objects.container.Container.save')
def test_create_image_path_is_none(self, mock_save):
def test_create_image_path_is_none(self, mock_save,
mock_get_security_group_ids,
mock_connect):
self.mock_docker.create_host_config = mock.Mock(
return_value={'Id1': 'val1', 'key2': 'val2'})
self.mock_docker.create_container = mock.Mock(
return_value={'Id': 'val1', 'key1': 'val2'})
image = {'path': ''}
mock_container = self.mock_default_container
result_container = self.driver.create(self.context, mock_container,
'test_sandbox', image)
with mock.patch.object(self.driver, '_get_available_network'):
result_container = self.driver.create(self.context, mock_container,
image, None)
host_config = {}
host_config['network_mode'] = 'container:test_sandbox'
host_config['ipc_mode'] = 'container:test_sandbox'
host_config['volumes_from'] = 'test_sandbox'
host_config['mem_limit'] = '512m'
host_config['cpu_quota'] = 100000
host_config['cpu_period'] = 100000
@ -119,7 +123,7 @@ class TestDockerDriver(base.DriverTestCase):
def test_delete_success(self):
self.mock_docker.remove_container = mock.Mock()
mock_container = mock.MagicMock()
self.driver.delete(mock_container, True)
self.driver.delete(self.context, mock_container, True)
self.mock_docker.remove_container.assert_called_once_with(
mock_container.container_id, force=True)
@ -129,7 +133,7 @@ class TestDockerDriver(base.DriverTestCase):
self.mock_docker.remove_container = mock.Mock(
side_effect=errors.APIError('Error', '', ''))
mock_container = mock.MagicMock()
self.driver.delete(mock_container, True)
self.driver.delete(self.context, mock_container, True)
self.mock_docker.remove_container.assert_called_once_with(
mock_container.container_id, force=True)
self.assertEqual(1, mock_init.call_count)
@ -141,7 +145,7 @@ class TestDockerDriver(base.DriverTestCase):
side_effect=errors.APIError('Error', '', ''))
mock_container = mock.MagicMock()
self.assertRaises(errors.APIError, self.driver.delete,
mock_container,
self.context, mock_container,
True)
self.mock_docker.remove_container.assert_called_once_with(
mock_container.container_id, force=True)
@ -355,8 +359,8 @@ class TestDockerDriver(base.DriverTestCase):
def test_delete_sandbox(self):
self.mock_docker.remove_container = mock.Mock()
mock_container = mock.MagicMock()
self.driver.delete_sandbox(self.context, mock_container,
sandbox_id='test_sandbox_id')
mock_container.get_sandbox_id.return_value = 'test_sandbox_id'
self.driver.delete_sandbox(self.context, mock_container)
self.mock_docker.remove_container.assert_called_once_with(
'test_sandbox_id', force=True)
@ -366,24 +370,6 @@ class TestDockerDriver(base.DriverTestCase):
sandbox_id='test_sandbox_id')
self.mock_docker.stop.assert_called_once_with('test_sandbox_id')
def test_get_sandbox_none_id(self):
mock_container = mock.MagicMock()
mock_container.meta = None
result_sandbox_id = self.driver.get_sandbox_id(mock_container)
self.assertIsNone(result_sandbox_id)
def test_get_sandbox_not_none_id(self):
mock_container = mock.MagicMock()
result_sandbox_id = self.driver.get_sandbox_id(mock_container)
self.assertEqual(result_sandbox_id,
mock_container.meta.get('sandbox_id', None))
def test_set_sandbox_id(self):
mock_container = mock.MagicMock(meta={'sandbox_id': 'test_sandbox_id'})
self.driver.set_sandbox_id(mock_container, 'test_sandbox_id')
self.assertEqual(mock_container.meta['sandbox_id'],
'test_sandbox_id')
def test_get_sandbox_name(self):
mock_container = mock.MagicMock(
uuid='ea8e2a25-2901-438d-8157-de7ffd68d051')
@ -548,19 +534,17 @@ class TestNovaDockerDriver(base.DriverTestCase):
@mock.patch('zun.container.docker.driver.'
'NovaDockerDriver._find_server_by_container_id')
@mock.patch('zun.container.docker.driver.NovaDockerDriver.get_sandbox_id')
@mock.patch('zun.common.nova.NovaClient')
def test_get_addresses(self, mock_nova_client, mock_get_sandbox_id,
def test_get_addresses(self, mock_nova_client,
mock_find_server_by_container_id):
nova_client_instance = mock.MagicMock()
nova_client_instance.get_addresses.return_value = 'test_address'
mock_nova_client.return_value = nova_client_instance
mock_get_sandbox_id.return_value = 'test_sanbox_id'
mock_find_server_by_container_id.return_value = 'test_test_server_name'
mock_container = mock.MagicMock()
mock_container.get_sandbox_id.return_value = 'test_sanbox_id'
result_address = self.driver.get_addresses(self.context,
mock_container)
mock_get_sandbox_id.assert_called_once_with(mock_container)
mock_find_server_by_container_id.assert_called_once_with(
'test_sanbox_id')
nova_client_instance.get_addresses.assert_called_once_with(

View File

@ -18,6 +18,10 @@ from zun.container import driver
class FakeDriver(driver.ContainerDriver):
"""Fake driver for testing."""
capabilities = {
"support_sandbox": True,
"support_standalone": True,
}
def __init__(self):
super(FakeDriver, self).__init__()
@ -87,17 +91,11 @@ class FakeDriver(driver.ContainerDriver):
pass
def create_sandbox(self, context, name, **kwargs):
return "fake_sandbox"
pass
def delete_sandbox(self, context, id):
pass
def get_sandbox_id(self, container):
pass
def set_sandbox_id(self, container, id):
pass
def get_addresses(self, context, container):
pass

View File

@ -62,7 +62,7 @@ def get_test_container(**kwargs):
{'Name': 'no', 'MaximumRetryCount': '0'}),
'status_detail': kwargs.get('status_detail', 'up from 5 hours'),
'interactive': kwargs.get('interactive', True),
'image_driver': 'glance',
'image_driver': kwargs.get('image_driver', 'glance'),
'websocket_url': 'ws://127.0.0.1:6784/4c03164962fa/attach/'
'ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1',
'websocket_token': '7878038e-957c-4d52-ae19-1e9561784e7b',