1 Star 0 Fork 20

Song.Gao/openstack-neutron

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0001-Create-executable-for-removing-patch-ports.patch 7.87 KB
一键复制 编辑 原始数据 按行查看 历史
zhangy1317 提交于 2021-01-15 15:46 . add spec and source packages
From 9238592fcb2238bfd34d9c0b414573cb6f3d9582 Mon Sep 17 00:00:00 2001
From: Jakub Libosvar <[email protected]>
Date: Thu, 12 Oct 2017 15:19:31 +0000
Subject: [PATCH] Create executable for removing patch ports
Nodes using provider bridges for internal traffic like amqp can cause an
ARP storm when at least two nodes were shutdown ungracefully and are
brought up at once. It's caused by having patch-ports between provider
bridges and integration bridge, hence the integration bridge passes ARP
broadcast packets from one provider bridge to another.
This patch introduces a cleanup script that scans Neutron config and
removes patch ports from integration bridge and bridges defined in
bridge_mappings option. Such script can be executed when node is booted.
Resolves: rhbz#1490281
Closes-bug: #1720766
Change-Id: I774cefac2951343a30f882791abf12598bc99603
---
neutron/cmd/destroy_patch_ports.py | 77 ++++++++++++++++++++
.../functional/cmd/test_destroy_patch_ports.py | 83 ++++++++++++++++++++++
2 files changed, 160 insertions(+)
create mode 100644 neutron/cmd/destroy_patch_ports.py
create mode 100644 neutron/tests/functional/cmd/test_destroy_patch_ports.py
diff --git a/neutron/cmd/destroy_patch_ports.py b/neutron/cmd/destroy_patch_ports.py
new file mode 100644
index 0000000..d6fb4b3
--- /dev/null
+++ b/neutron/cmd/destroy_patch_ports.py
@@ -0,0 +1,77 @@
+# Copyright 2017 Red Hat, Inc.
+# All Rights Reserved.
+#
+# 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.
+
+import sys
+
+from neutron_lib.utils import helpers
+from oslo_config import cfg
+from oslo_log import log as logging
+
+from neutron.agent.common import ovs_lib
+from neutron.common import config as common_config
+from neutron.conf.plugins.ml2.drivers import ovs_conf
+from neutron.plugins.common import utils as p_utils
+from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants
+
+LOG = logging.getLogger(__name__)
+
+
+def get_patch_port_names(bridge_name):
+ int_if_name = p_utils.get_interface_name(
+ bridge_name, prefix=constants.PEER_INTEGRATION_PREFIX)
+ phys_if_name = p_utils.get_interface_name(
+ bridge_name, prefix=constants.PEER_PHYSICAL_PREFIX)
+
+ return int_if_name, phys_if_name
+
+
+class PatchPortCleaner(object):
+ def __init__(self, config):
+ mappings = helpers.parse_mappings(config.OVS.bridge_mappings)
+ self.bridges = [ovs_lib.OVSBridge(bridge)
+ for bridge in mappings.values()]
+ self.int_br = ovs_lib.OVSBridge(config.OVS.integration_bridge)
+
+ def destroy_patch_ports(self):
+ if not self.int_br.bridge_exists(self.int_br.br_name):
+ # integration bridge hasn't been created by agent yet, nothing to
+ # clean
+ return
+ for bridge in self.bridges:
+ try:
+ self._remove_patch_ports_from_int_br(bridge)
+ except Exception as e:
+ LOG.error("Failed to remove patch port from bridge %s: %s",
+ bridge.br_name, e)
+
+ def _remove_patch_ports_from_int_br(self, bridge):
+ int_if_name, phys_if_name = get_patch_port_names(
+ bridge.br_name)
+ int_type = self.int_br.db_get_val(
+ "Interface", int_if_name, "type", log_errors=False)
+ if int_type == 'patch':
+ self.int_br.delete_port(int_if_name)
+ bridge.delete_port(phys_if_name)
+
+
+def main():
+ common_config.init(sys.argv[1:])
+ ovs_conf.register_ovs_agent_opts()
+ port_cleaner = PatchPortCleaner(cfg.CONF)
+ port_cleaner.destroy_patch_ports()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/neutron/tests/functional/cmd/test_destroy_patch_ports.py b/neutron/tests/functional/cmd/test_destroy_patch_ports.py
new file mode 100644
index 0000000..9c92edf
--- /dev/null
+++ b/neutron/tests/functional/cmd/test_destroy_patch_ports.py
@@ -0,0 +1,83 @@
+# Copyright 2017 Red Hat, Inc.
+# All Rights Reserved.
+#
+# 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.
+
+from neutron_lib import constants as n_const
+from oslo_config import cfg
+
+from neutron.cmd import destroy_patch_ports
+from neutron.common import utils
+from neutron.conf.plugins.ml2.drivers import ovs_conf
+from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants
+from neutron.tests.common import net_helpers
+from neutron.tests.functional import base
+
+
+class TestDestroyPatchPorts(base.BaseSudoTestCase):
+ def setUp(self):
+ super(TestDestroyPatchPorts, self).setUp()
+ self.int_br = self.useFixture(net_helpers.OVSBridgeFixture()).bridge
+ bridge_mappings = {}
+ self.bridges = []
+ for network in ('foo', 'bar'):
+ bridge = self.useFixture(net_helpers.OVSBridgeFixture()).bridge
+ self._create_patch_ports_to_int_br(bridge)
+ self.bridges.append(bridge)
+ bridge_mappings[network] = bridge.br_name
+ self.config = self._create_config_file(bridge_mappings)
+
+ def _create_config_file(self, bridge_mappings):
+ config = cfg.ConfigOpts()
+ ovs_conf.register_ovs_agent_opts(config)
+ config.set_override('integration_bridge', self.int_br.br_name, "OVS")
+ config.set_override(
+ 'bridge_mappings',
+ ','.join(["%s:%s" % (net, br)
+ for net, br in bridge_mappings.items()]),
+ "OVS")
+
+ return config
+
+ def _create_patch_ports_to_int_br(self, bridge):
+ int_if_name, phys_if_name = destroy_patch_ports.get_patch_port_names(
+ bridge.br_name)
+ self.int_br.add_patch_port(
+ int_if_name, constants.NONEXISTENT_PEER)
+ bridge.add_patch_port(
+ phys_if_name, constants.NONEXISTENT_PEER)
+ self.int_br.set_db_attribute(
+ 'Interface', int_if_name, 'options', {'peer': phys_if_name})
+ bridge.set_db_attribute(
+ 'Interface', phys_if_name, 'options', {'peer': int_if_name})
+
+ def _has_patch_ports(self, bridge):
+ int_if_name, phys_if_name = destroy_patch_ports.get_patch_port_names(
+ bridge.br_name)
+ return (bridge.port_exists(phys_if_name) and
+ self.int_br.port_exists(int_if_name))
+
+ def test_destroy_patch_ports(self):
+ self.assertTrue(all(self._has_patch_ports(bridge)
+ for bridge in self.bridges))
+ cleaner = destroy_patch_ports.PatchPortCleaner(self.config)
+ cleaner.destroy_patch_ports()
+ self.assertFalse(any(self._has_patch_ports(bridge)
+ for bridge in self.bridges))
+
+ def test_destroy_patch_ports_no_int_br(self):
+ name = utils.get_rand_name(
+ max_length=n_const.DEVICE_NAME_MAX_LEN)
+ self.config.set_override('integration_bridge', name, "OVS")
+ cleaner = destroy_patch_ports.PatchPortCleaner(self.config)
+ cleaner.destroy_patch_ports()
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/the-moon-is-blue/openstack-neutron.git
[email protected]:the-moon-is-blue/openstack-neutron.git
the-moon-is-blue
openstack-neutron
openstack-neutron
master

搜索帮助