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:
parent
1401b25294
commit
ea782b9066
@ -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
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user