NSX|V3+P: Admin utility to replace tier0

Replace an old tier0 (that might have been deleted) with a new one
Usage:
nsxadmin -r routers -o  update-tier0  --property old-tier0=<id>
                                      --property new-tier0=<id>

Change-Id: I83200508b827586cb0a404f43ac7ec23966d1675
This commit is contained in:
Adit Sarfaty 2019-07-14 11:03:05 +03:00
parent e7914520ba
commit e2a5007884
4 changed files with 178 additions and 13 deletions

View File

@ -364,6 +364,10 @@ Routers
nsxadmin -r routers -o nsx-enable-standby-relocation nsxadmin -r routers -o nsx-enable-standby-relocation
- Replace an old tier0 (that might have been deleted) with a new one::
nsxadmin -r routers -o update-tier0 --property old-tier0=<id> --property new-tier0=<id>
Orphaned Routers Orphaned Routers
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
@ -623,6 +627,10 @@ NSX Policy Plugin
nsxadmin -r system -o set -p realization_interval=1 nsxadmin -r system -o set -p realization_interval=1
- Replace an old tier0 (that might have been deleted) with a new one::
nsxadmin -r routers -o update-tier0 --property old-tier0=<id> --property new-tier0=<id>
Client Certificate Client Certificate
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~

View File

@ -12,11 +12,24 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from neutron.db import db_base_plugin_v2
from neutron.db import l3_db
from neutron_lib.callbacks import registry
from neutron_lib import context from neutron_lib import context
from oslo_log import log as logging
from vmware_nsx.db import nsx_models
from vmware_nsx.shell.admin.plugins.common import constants from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
from vmware_nsx.shell.admin.plugins.nsxp.resources import utils as p_utils from vmware_nsx.shell.admin.plugins.nsxp.resources import utils as p_utils
from vmware_nsx.shell import resources as shell
LOG = logging.getLogger(__name__)
class RoutersPlugin(db_base_plugin_v2.NeutronDbPluginV2,
l3_db.L3_NAT_db_mixin):
pass
@admin_utils.list_handler(constants.ROUTERS) @admin_utils.list_handler(constants.ROUTERS)
@ -42,3 +55,65 @@ def list_routers(resource, event, trigger, **kwargs):
mappings, mappings,
attrs=['Project', 'Name', 'ID', 'NSX status']) attrs=['Project', 'Name', 'ID', 'NSX status'])
return bool(mappings) return bool(mappings)
@admin_utils.output_header
def update_tier0(resource, event, trigger, **kwargs):
"""Replace old tier0 with a new one on the neutron DB and NSX backend"""
errmsg = ("Need to specify old and new tier0 ID. Add --property "
"old-tier0=<id> --property new-tier0=<id>")
if not kwargs.get('property'):
LOG.error("%s", errmsg)
return
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
old_tier0 = properties.get('old-tier0')
new_tier0 = properties.get('new-tier0')
if not old_tier0 or not new_tier0:
LOG.error("%s", errmsg)
return
# Verify the id of the new tier0 (old one might not exist any more)
nsxpolicy = p_utils.get_connected_nsxpolicy()
try:
nsxpolicy.tier0.get(new_tier0)
except Exception:
LOG.error("Tier0 logical router %s was not found", new_tier0)
return
# update all neutron DB entries
old_tier0_networks = []
ctx = context.get_admin_context()
with ctx.session.begin(subtransactions=True):
bindings = ctx.session.query(
nsx_models.TzNetworkBinding).filter_by(phy_uuid=old_tier0).all()
for bind in bindings:
old_tier0_networks.append(bind.network_id)
bind.phy_uuid = new_tier0
if not old_tier0_networks:
LOG.info("Did not find any provider networks using tier0 %s",
old_tier0)
return
LOG.info("Updated provider networks in DB: %s", old_tier0_networks)
# Update tier1 routers GW to point to the new tier0 in the backend
plugin = RoutersPlugin()
neutron_routers = plugin.get_routers(ctx)
for router in neutron_routers:
router_gw_net = (router.get('external_gateway_info') and
router['external_gateway_info'].get('network_id'))
if router_gw_net and router_gw_net in old_tier0_networks:
try:
nsxpolicy.tier1.update(router['id'], tier0=new_tier0)
except Exception as e:
LOG.error("Failed to update router %s linked port: %s",
router['id'], e)
else:
LOG.info("Updated router %s uplink port", router['id'])
LOG.info("Done.")
registry.subscribe(update_tier0,
constants.ROUTERS,
shell.Operations.UPDATE_TIER0.value)

View File

@ -14,8 +14,15 @@
import sys import sys
from neutron.db import db_base_plugin_v2
from neutron.db import l3_db
from neutron_lib.callbacks import registry
from neutron_lib import context as neutron_context
from oslo_log import log as logging
from vmware_nsx.common import utils as nsx_utils from vmware_nsx.common import utils as nsx_utils
from vmware_nsx.db import db as nsx_db from vmware_nsx.db import db as nsx_db
from vmware_nsx.db import nsx_models
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.shell.admin.plugins.common import constants from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import formatters from vmware_nsx.shell.admin.plugins.common import formatters
@ -25,12 +32,6 @@ from vmware_nsx.shell import resources as shell
from vmware_nsxlib.v3 import exceptions as nsx_exc from vmware_nsxlib.v3 import exceptions as nsx_exc
from vmware_nsxlib.v3 import nsx_constants from vmware_nsxlib.v3 import nsx_constants
from neutron.db import db_base_plugin_v2
from neutron.db import l3_db
from neutron_lib.callbacks import registry
from neutron_lib import context as neutron_context
from oslo_log import log as logging
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
neutron_client = utils.NeutronDbClient() neutron_client = utils.NeutronDbClient()
@ -247,6 +248,79 @@ def update_dhcp_relay(resource, event, trigger, **kwargs):
LOG.info("Done.") LOG.info("Done.")
@admin_utils.output_header
def update_tier0(resource, event, trigger, **kwargs):
"""Replace old tier0 with a new one on the neutron DB and NSX backend"""
errmsg = ("Need to specify old and new tier0 ID. Add --property "
"old-tier0=<id> --property new-tier0=<id>")
if not kwargs.get('property'):
LOG.error("%s", errmsg)
return
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
old_tier0 = properties.get('old-tier0')
new_tier0 = properties.get('new-tier0')
if not old_tier0 or not new_tier0:
LOG.error("%s", errmsg)
return
# Verify the id of the new tier0 (old one might not exist any more)
nsxlib = utils.get_connected_nsxlib()
try:
tier0_obj = nsxlib.logical_router.get(new_tier0)
except Exception:
LOG.error("Tier0 logical router %s was not found", new_tier0)
return
if tier0_obj.get('router_type') != 'TIER0':
LOG.error("Logical router %s is not a tier0 router", new_tier0)
return
# update all neutron DB entries
old_tier0_networks = []
admin_cxt = neutron_context.get_admin_context()
with admin_cxt.session.begin(subtransactions=True):
bindings = admin_cxt.session.query(
nsx_models.TzNetworkBinding).filter_by(phy_uuid=old_tier0).all()
for bind in bindings:
old_tier0_networks.append(bind.network_id)
bind.phy_uuid = new_tier0
if not old_tier0_networks:
LOG.info("Did not find any provider networks using tier0 %s",
old_tier0)
return
LOG.info("Updated provider networks in DB: %s", old_tier0_networks)
# Update tier1 routers GW to point to the new tier0 in the backend
plugin = RoutersPlugin()
filters = utils.get_plugin_filters(admin_cxt)
neutron_routers = plugin.get_routers(admin_cxt, filters=filters)
for router in neutron_routers:
router_gw_net = (router.get('external_gateway_info') and
router['external_gateway_info'].get('network_id'))
if router_gw_net and router_gw_net in old_tier0_networks:
nsx_router_id = nsx_db.get_nsx_router_id(
admin_cxt.session, router['id'])
try:
nsxlib.router.remove_router_link_port(nsx_router_id)
except Exception as e:
LOG.info("Could not delete router %s linked port: %s",
router['id'], e)
tags = nsxlib.build_v3_tags_payload(
router, resource_type='os-neutron-rport',
project_name=admin_cxt.tenant_name)
try:
nsxlib.router.add_router_link_port(nsx_router_id,
new_tier0,
tags=tags)
except Exception as e:
LOG.error("Failed to create router %s linked port: %s",
router['id'], e)
else:
LOG.info("Updated router %s uplink port", router['id'])
LOG.info("Done.")
registry.subscribe(list_missing_routers, registry.subscribe(list_missing_routers,
constants.ROUTERS, constants.ROUTERS,
shell.Operations.LIST_MISMATCHES.value) shell.Operations.LIST_MISMATCHES.value)
@ -266,6 +340,11 @@ registry.subscribe(delete_backend_router,
registry.subscribe(update_dhcp_relay, registry.subscribe(update_dhcp_relay,
constants.ROUTERS, constants.ROUTERS,
shell.Operations.NSX_UPDATE_DHCP_RELAY.value) shell.Operations.NSX_UPDATE_DHCP_RELAY.value)
registry.subscribe(update_enable_standby_relocation, registry.subscribe(update_enable_standby_relocation,
constants.ROUTERS, constants.ROUTERS,
shell.Operations.NSX_ENABLE_STANDBY_RELOCATION.value) shell.Operations.NSX_ENABLE_STANDBY_RELOCATION.value)
registry.subscribe(update_tier0,
constants.ROUTERS,
shell.Operations.UPDATE_TIER0.value)

View File

@ -71,6 +71,7 @@ class Operations(enum.Enum):
SHOW = 'show' SHOW = 'show'
VALIDATE = 'validate' VALIDATE = 'validate'
REUSE = 'reuse' REUSE = 'reuse'
UPDATE_TIER0 = 'update-tier0'
ops = [op.value for op in Operations] ops = [op.value for op in Operations]
@ -108,12 +109,13 @@ nsxv3_resources = {
Operations.NSX_TAG_DEFAULT.value, Operations.NSX_TAG_DEFAULT.value,
Operations.NSX_MIGRATE_V_V3.value, Operations.NSX_MIGRATE_V_V3.value,
Operations.NSX_MIGRATE_EXCLUDE_PORTS.value]), Operations.NSX_MIGRATE_EXCLUDE_PORTS.value]),
constants.ROUTERS: Resource(constants.ROUTERS, constants.ROUTERS: Resource(
[Operations.LIST_MISMATCHES.value, constants.ROUTERS, [
Operations.NSX_UPDATE_RULES.value, Operations.LIST_MISMATCHES.value,
Operations.NSX_UPDATE_DHCP_RELAY.value, Operations.NSX_UPDATE_RULES.value,
Operations.NSX_ENABLE_STANDBY_RELOCATION.value Operations.NSX_UPDATE_DHCP_RELAY.value,
]), Operations.NSX_ENABLE_STANDBY_RELOCATION.value,
Operations.UPDATE_TIER0.value]),
constants.DHCP_BINDING: Resource(constants.DHCP_BINDING, constants.DHCP_BINDING: Resource(constants.DHCP_BINDING,
[Operations.LIST.value, [Operations.LIST.value,
Operations.NSX_UPDATE.value, Operations.NSX_UPDATE.value,
@ -257,7 +259,8 @@ nsxp_resources = {
constants.NETWORKS: Resource(constants.NETWORKS, constants.NETWORKS: Resource(constants.NETWORKS,
[Operations.LIST.value]), [Operations.LIST.value]),
constants.ROUTERS: Resource(constants.ROUTERS, constants.ROUTERS: Resource(constants.ROUTERS,
[Operations.LIST.value]), [Operations.LIST.value,
Operations.UPDATE_TIER0.value]),
constants.CERTIFICATE: Resource(constants.CERTIFICATE, constants.CERTIFICATE: Resource(constants.CERTIFICATE,
[Operations.GENERATE.value, [Operations.GENERATE.value,
Operations.SHOW.value, Operations.SHOW.value,