text: # 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)
  