代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/openstack-neutron 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
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()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。