NSX|v: Admin Util remove router binding orphaned entries

New utilities to list/delete orphaned router binding entries,
meaning entries that the object behind them (router, loadbalancer
or network) does not exist on neutron.

Change-Id: I8a239b9d33a4900e2e90035111899015d68d30bb
This commit is contained in:
Adit Sarfaty 2017-08-29 09:00:08 +03:00
parent 1401b25294
commit ea782b9066
4 changed files with 146 additions and 0 deletions

View File

@ -87,6 +87,17 @@ Orphaned Edges
nsxadmin -r orphaned-edges -o clean
Orphaned Router bindings
~~~~~~~~~~~~~~~~~~~~~~~~
- List orphaned router bindings entries (exist on the router bindings DB table, but the neutron object behind them (router, network, or loadbalancer) is missing)::
nsxadmin -r orphaned-bindings -o list
- Clean orphaned router bindings entries (delete DB entry)::
nsxadmin -r orphaned-bindings -o clean
Missing Edges
~~~~~~~~~~~~~

View File

@ -48,6 +48,7 @@ EDGES = 'edges'
SPOOFGUARD_POLICY = 'spoofguard-policy'
BACKUP_EDGES = 'backup-edges'
ORPHANED_EDGES = 'orphaned-edges'
ORPHANED_BINDINGS = 'orphaned-bindings'
MISSING_EDGES = 'missing-edges'
METADATA = 'metadata'
MISSING_NETWORKS = 'missing-networks'

View File

@ -19,6 +19,7 @@ import textwrap
from vmware_nsx.common import config
from vmware_nsx.dvs import dvs
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import formatters
@ -27,6 +28,7 @@ import vmware_nsx.shell.admin.plugins.nsxv.resources.utils as utils
import vmware_nsx.shell.resources as shell
from neutron_lib.callbacks import registry
from neutron_lib import context as n_context
from neutron_lib import exceptions
from oslo_config import cfg
from oslo_log import log as logging
@ -80,6 +82,129 @@ def neutron_list_router_edge_bindings(resource, event, trigger, **kwargs):
['edge_id', 'router_id', 'availability_zone', 'status']))
@admin_utils.output_header
def clean_orphaned_router_bindings(resource, event, trigger, **kwargs):
"""Delete nsx router bindings entries without real objects behind them"""
orphaned_list = get_orphaned_router_bindings()
if not len(orphaned_list):
LOG.info("No orphaned Router bindings found.")
return
LOG.info("Before delete; Orphaned Bindings:")
LOG.info(formatters.output_formatter(
constants.ORPHANED_BINDINGS, orphaned_list,
['edge_id', 'router_id', 'availability_zone', 'status']))
if not kwargs.get('force'):
if len(orphaned_list):
user_confirm = admin_utils.query_yes_no("Do you want to delete "
"orphaned bindings",
default="no")
if not user_confirm:
LOG.info("NSXv Router bindings deletion aborted by user")
return
edgeapi = utils.NeutronDbClient()
for binding in orphaned_list:
nsxv_db.delete_nsxv_router_binding(
edgeapi.context.session, binding.router_id)
LOG.info("Deleted %s orphaned router bindings. You may need to check for "
"orphaned edges now.", len(orphaned_list))
@admin_utils.output_header
def list_orphaned_router_bindings(resource, event, trigger, **kwargs):
"""List nsx router bindings entries without real objects behind them"""
orphaned_list = get_orphaned_router_bindings()
LOG.info(formatters.output_formatter(
constants.ORPHANED_BINDINGS, orphaned_list,
['edge_id', 'router_id', 'availability_zone', 'status']))
def get_orphaned_router_bindings():
context = n_context.get_admin_context()
orphaned_list = []
with utils.NsxVPluginWrapper() as plugin:
networks = plugin.get_networks(context, fields=['id'])
net_ids = [x['id'] for x in networks]
routers = plugin.get_routers(context, fields=['id'])
rtr_ids = [x['id'] for x in routers]
for binding in get_router_edge_bindings():
if not router_binding_obj_exist(context, binding,
net_ids, rtr_ids):
orphaned_list.append(binding)
return orphaned_list
def _get_obj_id_from_binding(router_id, prefix):
"""Return the id part of the router-binding router-id field"""
return router_id[len(prefix):]
def _is_id_prefix_in_list(id_prefix, ids):
"""Return True if the id_prefix is the prefix of one of the ids"""
for x in ids:
if x.startswith(id_prefix):
return True
return False
def router_binding_obj_exist(context, binding, net_ids, rtr_ids):
"""Check if the object responsible for the router binding entry exists
Check if the relevant router/network/loadbalancer exists in the neutron DB
"""
router_id = binding.router_id
if router_id.startswith(vcns_const.BACKUP_ROUTER_PREFIX):
# no neutron object that should match backup edges
return True
if router_id.startswith(vcns_const.DHCP_EDGE_PREFIX):
# should have a network starting with this id
# get the id. and look for a network with this id
net_id_prefix = _get_obj_id_from_binding(
router_id, vcns_const.DHCP_EDGE_PREFIX)
if _is_id_prefix_in_list(net_id_prefix, net_ids):
return True
else:
LOG.warning("Network for binding entry %s not found", router_id)
return False
if router_id.startswith(vcns_const.PLR_EDGE_PREFIX):
# should have a distributed router starting with this id
# get the id. and look for a network with this id
rtr_id_prefix = _get_obj_id_from_binding(
router_id, vcns_const.PLR_EDGE_PREFIX)
if _is_id_prefix_in_list(rtr_id_prefix, rtr_ids):
return True
else:
LOG.warning("Router for binding entry %s not found", router_id)
return False
if router_id.startswith(lb_common.RESOURCE_ID_PFX):
# should have a load balancer starting with this id on the same edge
if nsxv_db.get_nsxv_lbaas_loadbalancer_binding_by_edge(
context.session, binding.edge_id):
return True
else:
LOG.warning("Loadbalancer for binding entry %s not found",
router_id)
return False
# regular router
# get the id. and look for a router with this id
if _is_id_prefix_in_list(router_id, rtr_ids):
return True
else:
LOG.warning("Router for binding entry %s not found", router_id)
return False
def get_orphaned_edges():
nsxv_edge_ids = set()
for edge in utils.get_nsxv_backend_edges():
@ -530,3 +655,9 @@ registry.subscribe(nsx_update_edge,
registry.subscribe(nsx_update_edges,
constants.EDGES,
shell.Operations.NSX_UPDATE_ALL.value)
registry.subscribe(list_orphaned_router_bindings,
constants.ORPHANED_BINDINGS,
shell.Operations.LIST.value)
registry.subscribe(clean_orphaned_router_bindings,
constants.ORPHANED_BINDINGS,
shell.Operations.CLEAN.value)

View File

@ -145,6 +145,9 @@ nsxv_resources = {
constants.ORPHANED_EDGES: Resource(constants.ORPHANED_EDGES,
[Operations.LIST.value,
Operations.CLEAN.value]),
constants.ORPHANED_BINDINGS: Resource(constants.ORPHANED_BINDINGS,
[Operations.LIST.value,
Operations.CLEAN.value]),
constants.MISSING_EDGES: Resource(constants.MISSING_EDGES,
[Operations.LIST.value]),
constants.SPOOFGUARD_POLICY: Resource(constants.SPOOFGUARD_POLICY,