diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index 40d6a0a3b2..b63a0af3c4 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -341,6 +341,9 @@ V2T migration nsxadmin -r nsx-migrate-v2t -o validate [--property transit-network=] [--property strict=true] +- Get compute ports vif ids mapping for the migration:: + + nsxadmin -r ports -o list (--property map-file=) Config ~~~~~~ diff --git a/vmware_nsx/api_replay/cli.py b/vmware_nsx/api_replay/cli.py index def847da3e..2984bdd301 100644 --- a/vmware_nsx/api_replay/cli.py +++ b/vmware_nsx/api_replay/cli.py @@ -60,6 +60,7 @@ class ApiReplayCli(object): ext_net_map=args.external_networks_map, net_vni_map=args.networks_vni_map, int_vni_map=args.internal_networks_vni_map, + vif_ids_map=args.vif_ids_map, logfile=args.logfile, max_retry=args.max_retry, cert_file=args.cert_file) @@ -191,6 +192,10 @@ class ApiReplayCli(object): "--internal-networks-vni-map", help="Path to a json file mapping internal network ID " "to its backend vni.") + parser.add_argument( + "--vif-ids-map", + help="Path to a json file mapping compute ports ids to the " + "expected vif ids.") parser.add_argument( "--max-retry", diff --git a/vmware_nsx/api_replay/client.py b/vmware_nsx/api_replay/client.py index 0a6ea848b9..282c396742 100644 --- a/vmware_nsx/api_replay/client.py +++ b/vmware_nsx/api_replay/client.py @@ -57,7 +57,7 @@ class ApiReplayClient(utils.PrepareObjectForMigration): octavia_os_tenant_name, octavia_os_tenant_domain_id, octavia_os_password, octavia_os_auth_url, neutron_conf, ext_net_map, net_vni_map, int_vni_map, - logfile, max_retry, cert_file): + vif_ids_map, logfile, max_retry, cert_file): # Init config and logging if neutron_conf: @@ -154,6 +154,13 @@ class ApiReplayClient(utils.PrepareObjectForMigration): else: self.int_vni_map = None + if vif_ids_map: + with open(vif_ids_map, 'r') as myfile: + data = myfile.read() + self.vif_ids_map = jsonutils.loads(data) + else: + self.vif_ids_map = None + self.n_errors = 0 self.errors = [] @@ -688,7 +695,8 @@ class ApiReplayClient(utils.PrepareObjectForMigration): port['id']) continue - body = self.prepare_port(port, remove_qos=remove_qos) + body = self.prepare_port(port, remove_qos=remove_qos, + vif_ids_map=self.vif_ids_map) # specify the network_id that we just created above port['network_id'] = network['id'] diff --git a/vmware_nsx/api_replay/utils.py b/vmware_nsx/api_replay/utils.py index 874f34f127..994f4f632b 100644 --- a/vmware_nsx/api_replay/utils.py +++ b/vmware_nsx/api_replay/utils.py @@ -268,7 +268,8 @@ class PrepareObjectForMigration(object): body.pop(field) return body - def prepare_port(self, port, remove_qos=False, direct_call=False): + def prepare_port(self, port, remove_qos=False, vif_ids_map=None, + direct_call=False): self.fix_description(port) body = self.drop_fields(port, self.drop_port_fields) if remove_qos: @@ -296,6 +297,9 @@ class PrepareObjectForMigration(object): body['port_security_enabled'] = False body['security_groups'] = [] + if vif_ids_map and body['id'] in vif_ids_map: + body['vif_id'] = vif_ids_map[body['id']] + if direct_call: if 'device_id' not in body: body['device_id'] = "" diff --git a/vmware_nsx/extensions/api_replay.py b/vmware_nsx/extensions/api_replay.py index d631d0b984..ddec2e1766 100644 --- a/vmware_nsx/extensions/api_replay.py +++ b/vmware_nsx/extensions/api_replay.py @@ -35,6 +35,9 @@ ID_WITH_POST = {'allow_post': True, 'allow_put': False, RESOURCE_ATTRIBUTE_MAP = { 'ports': { 'id': ID_WITH_POST, + 'vif_id': {'allow_post': True, 'allow_put': False, + 'default': '', + 'is_visible': True}, }, 'networks': { 'id': ID_WITH_POST, diff --git a/vmware_nsx/plugins/nsx_p/plugin.py b/vmware_nsx/plugins/nsx_p/plugin.py index d8ae2d7e4e..ec40eee29e 100644 --- a/vmware_nsx/plugins/nsx_p/plugin.py +++ b/vmware_nsx/plugins/nsx_p/plugin.py @@ -1713,7 +1713,12 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): context, port_data) device_owner = port_data.get('device_owner') vif_id = None - if not device_owner or device_owner != l3_db.DEVICE_OWNER_ROUTER_INTF: + if (cfg.CONF.api_replay_mode and device_owner and + device_owner.startswith('compute:') and port_data.get('vif_id')): + # During api-replay, migrated vm port should have this vif-id + vif_id = port_data['vif_id'] + elif (not device_owner or + device_owner != l3_db.DEVICE_OWNER_ROUTER_INTF): # Set vif_id even if no device owner so that auto-generated # MP ports won't be created for VMs before neutron sets the vif-id vif_id = port_data['id'] diff --git a/vmware_nsx/shell/admin/plugins/nsxp/resources/migration.py b/vmware_nsx/shell/admin/plugins/nsxp/resources/migration.py index f3bfa6c248..1adb44eeb8 100644 --- a/vmware_nsx/shell/admin/plugins/nsxp/resources/migration.py +++ b/vmware_nsx/shell/admin/plugins/nsxp/resources/migration.py @@ -53,19 +53,6 @@ def post_v2t_migration_cleanups(resource, event, trigger, **kwargs): section['id']) continue - # cleanup migrated DVS ports (belong to the edges that are not in use) - segments = nsxpolicy.segment.list() - for seg in segments: - # skip non-neutron segments - if not p_utils.is_neutron_resource(seg): - continue - ports = nsxpolicy.segment_port.list(seg['id']) - # find the non-neutron ports and delete them - for port in ports: - if not p_utils.is_neutron_resource(port): - nsxpolicy.segment_port.delete(seg['id'], port['id']) - LOG.error("Deleted migrated non-neutron port %s", port['id']) - @admin_utils.output_header def migration_tier0_redistribute(resource, event, trigger, **kwargs): diff --git a/vmware_nsx/shell/admin/plugins/nsxv/resources/migration.py b/vmware_nsx/shell/admin/plugins/nsxv/resources/migration.py index b355fbabdf..7e92520bf2 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv/resources/migration.py +++ b/vmware_nsx/shell/admin/plugins/nsxv/resources/migration.py @@ -15,6 +15,7 @@ import netaddr from oslo_config import cfg from oslo_log import log as logging +from oslo_serialization import jsonutils from networking_l2gw.db.l2gateway import l2gateway_models from neutron.services.qos import qos_plugin @@ -35,6 +36,7 @@ from vmware_nsx.services.lbaas.nsx_v3.implementation import lb_utils from vmware_nsx.services.lbaas.octavia import constants as oct_const from vmware_nsx.services.qos.nsx_v3 import pol_utils as qos_utils 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 utils as admin_utils from vmware_nsx.shell.admin.plugins.nsxv.resources import utils from vmware_nsx.shell import resources as shell @@ -354,6 +356,47 @@ def validate_config_for_migration(resource, event, trigger, **kwargs): "NSX-T.") +@admin_utils.output_header +def list_ports_vif_ids(resource, event, trigger, **kwargs): + filename = None + if kwargs.get('property'): + properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) + filename = properties.get('map-file') + + admin_context = n_context.get_admin_context() + table_results = [] + map_results = {} + + with utils.NsxVPluginWrapper() as plugin: + neutron_ports = plugin.get_ports(admin_context) + for port in neutron_ports: + # skip non compute ports + if (not port.get('device_owner').startswith( + nl_constants.DEVICE_OWNER_COMPUTE_PREFIX)): + continue + device_id = port.get('device_id') + port_id = port['id'] + vnic_index = plugin._get_port_vnic_index(admin_context, port_id) + table_results.append({'neutron_id': port_id, + 'instance_id': device_id, + 'vnic_index': vnic_index}) + if vnic_index is not None: + map_results[port_id] = '%s:%s' % (device_id, 4000 + vnic_index) + + LOG.info(formatters.output_formatter( + "Compute ports VID IDs", table_results, + ['neutron_id', 'instance_id', 'vnic_index'])) + if filename: + f = open(filename, "w") + f.write("%s" % jsonutils.dumps(map_results)) + f.close() + LOG.info("Mapping data saved into %s", filename) + + registry.subscribe(validate_config_for_migration, constants.NSX_MIGRATE_V_T, shell.Operations.VALIDATE.value) + +registry.subscribe(list_ports_vif_ids, + constants.PORTS, + shell.Operations.LIST.value) diff --git a/vmware_nsx/shell/resources.py b/vmware_nsx/shell/resources.py index dacabfd633..d243d55e52 100644 --- a/vmware_nsx/shell/resources.py +++ b/vmware_nsx/shell/resources.py @@ -256,6 +256,8 @@ nsxv_resources = { Operations.DELETE.value]), constants.NSX_MIGRATE_V_T: Resource(constants.NSX_MIGRATE_V_T, [Operations.VALIDATE.value]), + constants.PORTS: Resource(constants.PORTS, + [Operations.LIST.value]), }