Optimize disconnection of container from network
The disconnection of container from network needs to delete all the neutron ports of the container. In before, we searched neutron ports by device_id/EndpointID. The problem is EndpointID is not available if the container is not running. This commit retrieves neutron ports from the 'addresses' field of the container instead. Partial-Implements: blueprint make-sandbox-optional Change-Id: Ibe9383d735640d66cc9f24ce3caccd281a64b4e7
This commit is contained in:
@@ -62,9 +62,9 @@ class Manager(object):
|
||||
if created_container:
|
||||
self._do_container_start(context, created_container)
|
||||
|
||||
def _do_sandbox_cleanup(self, context, sandbox_id):
|
||||
def _do_sandbox_cleanup(self, context, container, sandbox_id):
|
||||
try:
|
||||
self.driver.delete_sandbox(context, sandbox_id)
|
||||
self.driver.delete_sandbox(context, container, sandbox_id)
|
||||
except Exception as e:
|
||||
LOG.error("Error occurred while deleting sandbox: %s",
|
||||
six.text_type(e))
|
||||
@@ -118,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, sandbox_id)
|
||||
self._do_sandbox_cleanup(context, container, sandbox_id)
|
||||
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, sandbox_id)
|
||||
self._do_sandbox_cleanup(context, container, sandbox_id)
|
||||
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, sandbox_id)
|
||||
self._do_sandbox_cleanup(context, container, sandbox_id)
|
||||
self._fail_container(context, container, six.text_type(e))
|
||||
return
|
||||
|
||||
@@ -153,7 +153,7 @@ class Manager(object):
|
||||
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, sandbox_id)
|
||||
self._do_sandbox_cleanup(context, container, sandbox_id)
|
||||
self._fail_container(context, container, six.text_type(e),
|
||||
unset_host=True)
|
||||
return
|
||||
@@ -161,7 +161,7 @@ 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, sandbox_id)
|
||||
self._do_sandbox_cleanup(context, container, sandbox_id)
|
||||
self._fail_container(context, container, six.text_type(e),
|
||||
unset_host=True)
|
||||
return
|
||||
@@ -209,7 +209,7 @@ class Manager(object):
|
||||
container.task_state = consts.SANDBOX_DELETING
|
||||
container.save(context)
|
||||
try:
|
||||
self.driver.delete_sandbox(context, sandbox_id)
|
||||
self.driver.delete_sandbox(context, container, sandbox_id)
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception(reraise=reraise):
|
||||
LOG.exception("Unexpected exception: %s",
|
||||
|
||||
@@ -534,7 +534,8 @@ class DockerDriver(driver.ContainerDriver):
|
||||
# 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(sandbox, 'bridge')
|
||||
network_api.disconnect_container_from_network(
|
||||
container, 'bridge', sandbox_id=sandbox['Id'])
|
||||
addresses = {}
|
||||
for network in networks:
|
||||
addrs = network_api.connect_container_to_network(
|
||||
@@ -587,12 +588,13 @@ class DockerDriver(driver.ContainerDriver):
|
||||
|
||||
return docker_networks[0]
|
||||
|
||||
def delete_sandbox(self, context, sandbox_id):
|
||||
def delete_sandbox(self, context, container, sandbox_id):
|
||||
with docker_utils.docker_client() as docker:
|
||||
network_api = zun_network.api(context=context, docker_api=docker)
|
||||
sandbox = docker.inspect_container(sandbox_id)
|
||||
for network in sandbox["NetworkSettings"]["Networks"]:
|
||||
network_api.disconnect_container_from_network(sandbox, network)
|
||||
network_api.disconnect_container_from_network(
|
||||
container, network, sandbox_id=sandbox['Id'])
|
||||
try:
|
||||
docker.remove_container(sandbox_id, force=True)
|
||||
except errors.APIError as api_error:
|
||||
|
||||
@@ -153,7 +153,7 @@ class ContainerDriver(object):
|
||||
"""Create a sandbox."""
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_sandbox(self, context, sandbox_id):
|
||||
def delete_sandbox(self, context, container, sandbox_id):
|
||||
"""Delete a sandbox."""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@@ -158,25 +158,23 @@ class KuryrNetwork(network.Network):
|
||||
container['Id'], network_name, **kwargs)
|
||||
return addresses
|
||||
|
||||
def disconnect_container_from_network(self, container, network_name):
|
||||
container_id = container['Id']
|
||||
neutron_ports = None
|
||||
# TODO(hongbin): Use objects instead of an ad hoc dict.
|
||||
if "NetworkSettings" in container:
|
||||
network = container["NetworkSettings"]["Networks"][network_name]
|
||||
endpoint_id = network["EndpointID"]
|
||||
# Kuryr set the port's device_id as endpoint_id so we leverge it
|
||||
neutron_ports = self.neutron.list_ports(device_id=endpoint_id)
|
||||
neutron_ports = neutron_ports.get('ports', [])
|
||||
if not neutron_ports:
|
||||
LOG.warning("Cannot find the neutron port that bind container "
|
||||
"%s to network %s", container_id, network_name)
|
||||
def disconnect_container_from_network(self, container, network_name,
|
||||
sandbox_id=None):
|
||||
container_id = container.container_id
|
||||
if sandbox_id:
|
||||
container_id = sandbox_id
|
||||
|
||||
neutron_ports = set()
|
||||
if container.addresses:
|
||||
addrs_list = container.addresses.get(network_name, [])
|
||||
for addr in addrs_list:
|
||||
port_id = addr['port']
|
||||
neutron_ports.add(port_id)
|
||||
|
||||
self.docker.disconnect_container_from_network(container_id,
|
||||
network_name)
|
||||
if neutron_ports:
|
||||
for port_id in neutron_ports:
|
||||
try:
|
||||
port_id = neutron_ports[0]['id']
|
||||
self.neutron.delete_port(port_id)
|
||||
except exceptions.PortNotFoundClient:
|
||||
LOG.warning('Maybe your libnetwork distribution do not have'
|
||||
|
||||
@@ -348,7 +348,8 @@ class TestDockerDriver(base.DriverTestCase):
|
||||
|
||||
def test_delete_sandbox(self):
|
||||
self.mock_docker.remove_container = mock.Mock()
|
||||
self.driver.delete_sandbox(context=self.context,
|
||||
mock_container = mock.MagicMock()
|
||||
self.driver.delete_sandbox(self.context, mock_container,
|
||||
sandbox_id='test_sandbox_id')
|
||||
self.mock_docker.remove_container.assert_called_once_with(
|
||||
'test_sandbox_id', force=True)
|
||||
|
||||
Reference in New Issue
Block a user