neutron/neutron/cmd/ipset_cleanup.py
Jakub Libosvar 4d3a274765 Don't register config options on imports
Importing some modules lead to registering config options that may
collide with config options from a project that calls the import. This
patch wraps the side effect that registers config options into a
function that needs to be called in case the caller wants to register
the options.

This solution is also not perfect as it guards the common options to be
registered only once even if the function is called multiple times. This
is to solve problems in unittests, ideally we should always call the
function just once even in our testing suites.

Resolves-Bug: #1968606
Change-Id: Ic1532eb8de887ff1b1085206df11f53e22f7f524
Signed-off-by: Jakub Libosvar <libosvar@redhat.com>
2022-04-13 05:49:15 +00:00

104 lines
3.5 KiB
Python

# Copyright (c) 2015 OpenStack Foundation.
# 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 oslo_config import cfg
from oslo_log import log as logging
from neutron.agent.linux import utils
from neutron.common import config
from neutron.conf.agent import cmd as command
from neutron.conf.agent import common as agent_config
LOG = logging.getLogger(__name__)
def setup_conf():
"""Setup the cfg for the clean up utility.
Use separate setup_conf for the utility because there are many options
from the main config that do not apply during clean-up.
"""
conf = cfg.CONF
config.register_common_config_options()
agent_config.register_root_helper(conf=conf)
agent_config.setup_privsep()
command.register_cmd_opts(command.ip_opts, conf)
return conf
def remove_iptables_reference(ipset):
# Remove any iptables reference to this IPset
cmd = ['iptables-save'] if 'IPv4' in ipset else ['ip6tables-save']
iptables_save = utils.execute(cmd, run_as_root=True, privsep_exec=True)
if ipset in iptables_save:
cmd = ['iptables'] if 'IPv4' in ipset else ['ip6tables']
cmd += ['-w', '10'] # wait for xlock release
LOG.info("Removing iptables rule for IPset: %s", ipset)
for rule in iptables_save.splitlines():
if '--match-set %s ' % ipset in rule and rule.startswith('-A'):
# change to delete
params = rule.split()
params[0] = '-D'
try:
utils.execute(cmd + params, run_as_root=True,
privsep_exec=True)
except Exception:
LOG.exception('Error, unable to remove iptables rule '
'for IPset: %s', ipset)
def destroy_ipset(conf, ipset):
# If there is an iptables reference and we don't remove it, the
# IPset removal will fail below
if conf.force:
remove_iptables_reference(ipset)
LOG.info("Destroying IPset: %s", ipset)
cmd = ['ipset', 'destroy', ipset]
try:
utils.execute(cmd, run_as_root=True, privsep_exec=True)
except Exception:
LOG.exception('Error, unable to destroy IPset: %s', ipset)
def cleanup_ipsets(conf):
# Identify ipsets for destruction.
LOG.info("Destroying IPsets with prefix: %s", conf.prefix)
cmd = ['ipset', '-L', '-n']
ipsets = utils.execute(cmd, run_as_root=True, privsep_exec=True)
for ipset in ipsets.split('\n'):
if conf.allsets or ipset.startswith(conf.prefix):
destroy_ipset(conf, ipset)
LOG.info("IPset cleanup completed successfully")
def main():
"""Main method for cleaning up IPsets.
The utility is designed to clean-up after the forced or unexpected
termination of Neutron agents.
The --allsets flag should only be used as part of the cleanup of a devstack
installation as it will blindly destroy all IPsets.
"""
conf = setup_conf()
conf()
config.setup_logging()
cleanup_ipsets(conf)