neutron/neutron/cmd/destroy_patch_ports.py
Slawek Kaplonski 86f6ea347a Add script which can clean patch ports between bridges
Once provider bridges are brought up, they should not send any traffic
to the integration bridge until ovs-agent configures the bridges.
When node is rebooted, patch ports to br-int are preserved because they
are stored in ovsdb.

This patch adds script which can removes such patch ports. This script can
be used e.g. in some systemd unit files or ifcfg scripts and be run
during the node boot process.

Co-authored-by: Jakub Libosvar <jlibosva@redhat.com>
Co-authored-by: Yatin Karel <ykarel@redhat.com>
Co-authored-by: Bogdan Dobrelya <bdobreli@redhat.com>
Change-Id: I99e33e8c9a5146dcae3ac9d98aae0284d4d80f20
2020-12-10 10:08:02 +00:00

91 lines
3.3 KiB
Python

# Copyright 2020 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.plugins import utils as p_utils
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.agent import common as agent_config
from neutron.conf.plugins.ml2.drivers import ovs_conf
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):
LOG.debug("Get OVS bridge mappings")
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) or
self.flows_configured()):
# integration bridge hasn't been created by agent yet or it's been
# already configured by the agent
return
for bridge in self.bridges:
try:
LOG.debug("Remove patch port from bridge %s", bridge.br_name)
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 flows_configured(self):
"""Return True if the integration bridge has flows already configured.
"""
LOG.debug("Get configured flows for integration bridge %s",
self.int_br.br_name)
return bool(self.int_br.dump_flows_for(table=constants.CANARY_TABLE))
def main():
common_config.init(sys.argv[1:])
ovs_conf.register_ovs_agent_opts()
common_config.setup_logging()
agent_config.setup_privsep()
port_cleaner = PatchPortCleaner(cfg.CONF)
port_cleaner.destroy_patch_ports()
if __name__ == "__main__":
main()