Add binding_deactivate method to Linux bridge agent
This commit adds a binding_deactivate method to the Linux bridge agent to receive messages from the ML2 plugin when a binding is de-activated for a port. After receiving that message, the agent un-plugs the corresponding tap interface from the port's network bridge. To support this, a binding_deactivate method is also added to the agents notifier. Finally, the activate method in the ML2 plugin is updated to use the binding_deactivate method in the agents notifier. Change-Id: I3f4e34766791c472a2c81842190094f697baa05c Partial-Bug: #1580880
This commit is contained in:
parent
390b6a531f
commit
f374697760
neutron
agent
plugins/ml2
tests/unit/plugins/ml2/drivers/linuxbridge/agent
24
neutron/agent/_topics.py
Normal file
24
neutron/agent/_topics.py
Normal file
@ -0,0 +1,24 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
TODO(mlavalle): This module should be deleted once neutron-lib containing
|
||||
https://review.openstack.org/#/c/564381/ change is released.
|
||||
"""
|
||||
|
||||
from neutron_lib.api.definitions import portbindings_extended
|
||||
|
||||
|
||||
PORT_BINDING = portbindings_extended.RESOURCE_NAME
|
||||
|
||||
ACTIVATE = 'activate'
|
||||
DEACTIVATE = 'deactivate'
|
@ -33,6 +33,7 @@ from oslo_service import service
|
||||
from oslo_utils import excutils
|
||||
from six import moves
|
||||
|
||||
from neutron.agent import _topics as n_topics
|
||||
from neutron.agent.linux import bridge_lib
|
||||
from neutron.agent.linux import ip_lib
|
||||
from neutron.api.rpc.handlers import securitygroups_rpc as sg_rpc
|
||||
@ -833,7 +834,8 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase):
|
||||
consumers = [[topics.PORT, topics.UPDATE],
|
||||
[topics.NETWORK, topics.DELETE],
|
||||
[topics.NETWORK, topics.UPDATE],
|
||||
[topics.SECURITY_GROUP, topics.UPDATE]]
|
||||
[topics.SECURITY_GROUP, topics.UPDATE],
|
||||
[n_topics.PORT_BINDING, n_topics.DEACTIVATE]]
|
||||
if cfg.CONF.VXLAN.l2_population:
|
||||
consumers.append([topics.L2POPULATION, topics.UPDATE])
|
||||
return consumers
|
||||
@ -869,7 +871,8 @@ class LinuxBridgeRpcCallbacks(
|
||||
# 1.1 Support Security Group RPC
|
||||
# 1.3 Added param devices_to_update to security_groups_provider_updated
|
||||
# 1.4 Added support for network_update
|
||||
target = oslo_messaging.Target(version='1.4')
|
||||
# 1.5 Added binding_deactivate
|
||||
target = oslo_messaging.Target(version='1.5')
|
||||
|
||||
def network_delete(self, context, **kwargs):
|
||||
LOG.debug("network_delete received")
|
||||
@ -899,6 +902,18 @@ class LinuxBridgeRpcCallbacks(
|
||||
self.updated_devices.add(device_name)
|
||||
LOG.debug("port_update RPC received for port: %s", port_id)
|
||||
|
||||
def binding_deactivate(self, context, **kwargs):
|
||||
if kwargs.get('host') != cfg.CONF.host:
|
||||
return
|
||||
interface_name = self.agent.mgr.get_tap_device_name(
|
||||
kwargs.get('port_id'))
|
||||
bridge_name = self.agent.mgr.get_bridge_name(kwargs.get('network_id'))
|
||||
LOG.debug("Removing device %(interface_name)s from bridge "
|
||||
"%(bridge_name)s due to binding being de-activated",
|
||||
{'interface_name': interface_name,
|
||||
'bridge_name': bridge_name})
|
||||
self.agent.mgr.remove_interface(bridge_name, interface_name)
|
||||
|
||||
def network_update(self, context, **kwargs):
|
||||
network_id = kwargs['network']['id']
|
||||
LOG.debug("network_update message processed for network "
|
||||
|
@ -2199,7 +2199,9 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
original_context, bind_context, need_notify=True,
|
||||
try_again=True)
|
||||
if not try_again:
|
||||
self.notifier.port_delete(context, port_id)
|
||||
self.notifier.binding_deactivate(context, port_id,
|
||||
active_binding.host,
|
||||
network['id'])
|
||||
return self._make_port_binding_dict(cur_context._binding)
|
||||
raise n_exc.PortBindingError(port_id=port_id, host=host)
|
||||
|
||||
|
@ -25,6 +25,7 @@ from oslo_log import log
|
||||
import oslo_messaging
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
from neutron.agent import _topics as n_topics
|
||||
from neutron.api.rpc.handlers import dvr_rpc
|
||||
from neutron.api.rpc.handlers import securitygroups_rpc as sg_rpc
|
||||
from neutron.common import rpc as n_rpc
|
||||
@ -383,6 +384,7 @@ class AgentNotifierApi(dvr_rpc.DVRAgentRpcApiMixin,
|
||||
1.1 - Added get_active_networks_info, create_dhcp_port,
|
||||
update_dhcp_port, and removed get_dhcp_port methods.
|
||||
1.4 - Added network_update
|
||||
1.5 - Added binding_deactivate
|
||||
"""
|
||||
|
||||
def __init__(self, topic):
|
||||
@ -399,6 +401,8 @@ class AgentNotifierApi(dvr_rpc.DVRAgentRpcApiMixin,
|
||||
self.topic_network_update = topics.get_topic_name(topic,
|
||||
topics.NETWORK,
|
||||
topics.UPDATE)
|
||||
self.topic_port_binding_deactivate = topics.get_topic_name(
|
||||
topic, n_topics.PORT_BINDING, n_topics.DEACTIVATE)
|
||||
|
||||
target = oslo_messaging.Target(topic=topic, version='1.0')
|
||||
self.client = n_rpc.get_client(target)
|
||||
@ -425,3 +429,9 @@ class AgentNotifierApi(dvr_rpc.DVRAgentRpcApiMixin,
|
||||
cctxt = self.client.prepare(topic=self.topic_network_update,
|
||||
fanout=True, version='1.4')
|
||||
cctxt.cast(context, 'network_update', network=network)
|
||||
|
||||
def binding_deactivate(self, context, port_id, host, network_id):
|
||||
cctxt = self.client.prepare(topic=self.topic_port_binding_deactivate,
|
||||
fanout=True, version='1.5')
|
||||
cctxt.cast(context, 'binding_deactivate', port_id=port_id, host=host,
|
||||
network_id=network_id)
|
||||
|
@ -975,6 +975,7 @@ class TestLinuxBridgeRpcCallbacks(base.BaseTestCase):
|
||||
segment.network_type = 'vxlan'
|
||||
segment.segmentation_id = 1
|
||||
self.lb_rpc.network_map['net_id'] = segment
|
||||
cfg.CONF.set_default('host', 'host')
|
||||
|
||||
def test_network_delete_mapped_net(self):
|
||||
mock_net = mock.Mock()
|
||||
@ -1022,6 +1023,34 @@ class TestLinuxBridgeRpcCallbacks(base.BaseTestCase):
|
||||
self.assertEqual(0, del_fn.call_count)
|
||||
self.assertEqual(1, log.call_count)
|
||||
|
||||
def test_binding_deactivate(self):
|
||||
with mock.patch.object(self.lb_rpc.agent.mgr,
|
||||
"get_bridge_name") as get_br_fn,\
|
||||
mock.patch.object(self.lb_rpc.agent.mgr,
|
||||
"get_tap_device_name") as get_tap_fn,\
|
||||
mock.patch.object(self.lb_rpc.agent.mgr,
|
||||
"remove_interface") as rem_intf:
|
||||
get_br_fn.return_value = "br0"
|
||||
get_tap_fn.return_value = "tap456"
|
||||
self.lb_rpc.binding_deactivate(mock.ANY, host="host",
|
||||
network_id="123", port_id="456")
|
||||
get_br_fn.assert_called_once_with("123")
|
||||
get_tap_fn.assert_called_once_with("456")
|
||||
rem_intf.assert_called_once_with("br0", "tap456")
|
||||
|
||||
def test_binding_deactivate_not_for_host(self):
|
||||
with mock.patch.object(self.lb_rpc.agent.mgr,
|
||||
"get_bridge_name") as get_br_fn,\
|
||||
mock.patch.object(self.lb_rpc.agent.mgr,
|
||||
"get_tap_device_name") as get_tap_fn,\
|
||||
mock.patch.object(self.lb_rpc.agent.mgr,
|
||||
"remove_interface") as rem_intf:
|
||||
self.lb_rpc.binding_deactivate(mock.ANY, host="other_host",
|
||||
network_id="123", port_id="456")
|
||||
get_br_fn.assert_not_called()
|
||||
get_tap_fn.assert_not_called()
|
||||
rem_intf.assert_not_called()
|
||||
|
||||
def _test_fdb_add(self, proxy_enabled=False):
|
||||
fdb_entries = {'net_id':
|
||||
{'ports':
|
||||
|
Loading…
x
Reference in New Issue
Block a user