From a226237a4ed21e400bd73decc674db2b771e2ab2 Mon Sep 17 00:00:00 2001 From: asarfaty Date: Wed, 10 Feb 2021 13:07:18 +0200 Subject: [PATCH] V2T migration: distributed routers support For the distributed router edges to be migrated, we need to created their internal virtualwire network on the nsx-t as well. For that we added an admin utility to list the necessary networks ans their vni, and also updated the api-replay to create those networks. Change-Id: I183e48a0ab8fcbe04810fec94e5cce584abcec15 --- doc/source/admin_util.rst | 4 +- vmware_nsx/api_replay/cli.py | 5 ++ vmware_nsx/api_replay/client.py | 27 +++++++++- .../admin/plugins/nsxv/resources/networks.py | 49 ++++++++++++++++--- 4 files changed, 74 insertions(+), 11 deletions(-) diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index ea25c60eb6..40d6a0a3b2 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -239,9 +239,9 @@ Portgroups VirtualWires ~~~~~~~~~~~~ -- List all NSX virtual wires with their neutron id and vni:: +- List all NSX virtual wires with their neutron id and vni. Adding map-fole property will also save the results as a json file. Adding the internal flag will instead log only internal plr-dlr networks with their neutron router id:: - nsxadmin -r nsx-virtualwires -o list (--property map-file=) + nsxadmin -r nsx-virtualwires -o list (--property map-file=) (--property internal=true) Security Groups, Firewall and Spoofguard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/vmware_nsx/api_replay/cli.py b/vmware_nsx/api_replay/cli.py index f449e1d749..def847da3e 100644 --- a/vmware_nsx/api_replay/cli.py +++ b/vmware_nsx/api_replay/cli.py @@ -59,6 +59,7 @@ class ApiReplayCli(object): neutron_conf=args.neutron_conf, ext_net_map=args.external_networks_map, net_vni_map=args.networks_vni_map, + int_vni_map=args.internal_networks_vni_map, logfile=args.logfile, max_retry=args.max_retry, cert_file=args.cert_file) @@ -186,6 +187,10 @@ class ApiReplayCli(object): "--networks-vni-map", help="Path to a json file mapping neutron network ID to its " "backend vni.") + parser.add_argument( + "--internal-networks-vni-map", + help="Path to a json file mapping internal network ID " + "to its backend vni.") parser.add_argument( "--max-retry", diff --git a/vmware_nsx/api_replay/client.py b/vmware_nsx/api_replay/client.py index 0b737916ee..f8a1129307 100644 --- a/vmware_nsx/api_replay/client.py +++ b/vmware_nsx/api_replay/client.py @@ -57,8 +57,8 @@ class ApiReplayClient(utils.PrepareObjectForMigration): octavia_os_username, octavia_os_user_domain_id, octavia_os_tenant_name, octavia_os_tenant_domain_id, octavia_os_password, octavia_os_auth_url, - neutron_conf, ext_net_map, net_vni_map, logfile, max_retry, - cert_file): + neutron_conf, ext_net_map, net_vni_map, int_vni_map, + logfile, max_retry, cert_file): # Init config and logging if neutron_conf: @@ -139,6 +139,13 @@ class ApiReplayClient(utils.PrepareObjectForMigration): else: self.net_vni_map = None + if int_vni_map: + with open(int_vni_map, 'r') as myfile: + data = myfile.read() + self.int_vni_map = jsonutils.loads(data) + else: + self.int_vni_map = None + LOG.info("Starting NSX migration to %s.", self.dest_plugin) # Migrate all the objects self.migrate_security_groups() @@ -407,6 +414,22 @@ class ApiReplayClient(utils.PrepareObjectForMigration): router['id']) continue + # If its a distributed router, we may also need to create its + # internal network + if self.int_vni_map and router['id'] in self.int_vni_map: + net_name = ("Internal network for distributed router %s" % + router['id']) + net_body = {'tenant_id': nsxv_constants.INTERNAL_TENANT_ID, + 'id': router['id'], + 'name': net_name, + 'vni': self.int_vni_map[router['id']]} + try: + self.dest_neutron.create_network({'network': net_body}) + except Exception as e: + LOG.error("Failed to create internal network for router " + "%(rtr)s: %(e)s", + {'rtr': router['id'], 'e': e}) + n_errors = n_errors + 1 dest_router = self.have_id(router['id'], dest_routers) if dest_router is False: body = self.prepare_router(router, dest_azs=dest_azs) diff --git a/vmware_nsx/shell/admin/plugins/nsxv/resources/networks.py b/vmware_nsx/shell/admin/plugins/nsxv/resources/networks.py index 7e3741c840..831afd50e3 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv/resources/networks.py +++ b/vmware_nsx/shell/admin/plugins/nsxv/resources/networks.py @@ -23,6 +23,7 @@ from oslo_serialization import jsonutils from oslo_vmware import vim_util from vmware_nsx.db import db as nsx_db +from vmware_nsx.db import nsxv_db from vmware_nsx.dvs import dvs from vmware_nsx.plugins.nsx_v.vshield.common import exceptions from vmware_nsx.shell.admin.plugins.common import constants @@ -305,14 +306,30 @@ def get_dvs_id_from_backend_name(backend_name): return reg.group(0) -@admin_utils.output_header -def list_nsx_virtual_wires(resource, event, trigger, **kwargs): - filename = None - if kwargs.get('property'): - properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) - filename = properties.get('map-file') +def list_intenrnal_virtual_wires(vws): + # List the virtualwires matching plr-dlr connection with their vni + table_results = [] + map_results = {} + admin_context = context.get_admin_context() - vws = get_virtual_wires() + # Get all the plr-dlr virtual wires + like_filters = {'lswitch_id': 'virtualwire-%'} + edge_bindings = nsxv_db.get_nsxv_router_bindings( + admin_context.session, like_filters=like_filters) + + for binding in edge_bindings: + # get the nsx id: + moref = binding.lswitch_id + vni = vws.get(moref, {}).get('vdnId') + table_results.append({'neutron_id': binding['router_id'], + 'nsx_id': moref, + 'vni': vni}) + map_results[binding['router_id']] = vni + return table_results, map_results + + +def list_neutron_virtual_wires(vws): + # List the virtualwires matching neutron networks with their vni table_results = [] map_results = {} admin_context = context.get_admin_context() @@ -330,6 +347,24 @@ def list_nsx_virtual_wires(resource, event, trigger, **kwargs): 'nsx_id': moref, 'vni': vni}) map_results[net['id']] = vni + return table_results, map_results + + +@admin_utils.output_header +def list_nsx_virtual_wires(resource, event, trigger, **kwargs): + filename = None + internal = False + if kwargs.get('property'): + properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) + filename = properties.get('map-file') + internal = bool(properties.get('internal', 'false').lower() == 'true') + + vws = get_virtual_wires() + if internal: + table_results, map_results = list_intenrnal_virtual_wires(vws) + else: + table_results, map_results = list_neutron_virtual_wires(vws) + LOG.info(formatters.output_formatter(constants.NSX_VIRTUALWIRES, table_results, ['neutron_id', 'nsx_id', 'vni']))