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
This commit is contained in:
asarfaty 2021-02-10 13:07:18 +02:00 committed by Adit Sarfaty
parent 2a58c7b8bc
commit 64a729ec17
4 changed files with 74 additions and 11 deletions

View File

@ -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=<filename>)
nsxadmin -r nsx-virtualwires -o list (--property map-file=<filename>) (--property internal=true)
Security Groups, Firewall and Spoofguard
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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",

View File

@ -58,8 +58,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:
@ -140,6 +140,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()
@ -408,6 +415,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)

View File

@ -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
@ -306,14 +307,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()
@ -331,6 +348,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']))