V2T migration: Set expected VIF id to compute ports
- Add an udmin utility to provide the mapping between compute ports and vif-ids - Add extension to the api replay mode to support setting it by the plugin - Add the mapping file as a parameter to teh api replay and use it in the ports migration - Remove post migration cleanup of ports Change-Id: Icfd3ef9f8056ee9c602ac5e85345daa59309f602
This commit is contained in:
parent
1748e7cb4b
commit
7b9fb7b6eb
@ -341,6 +341,9 @@ V2T migration
|
|||||||
|
|
||||||
nsxadmin -r nsx-migrate-v2t -o validate [--property transit-network=<cidr>] [--property strict=true]
|
nsxadmin -r nsx-migrate-v2t -o validate [--property transit-network=<cidr>] [--property strict=true]
|
||||||
|
|
||||||
|
- Get compute ports vif ids mapping for the migration::
|
||||||
|
|
||||||
|
nsxadmin -r ports -o list (--property map-file=<filename>)
|
||||||
Config
|
Config
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ class ApiReplayCli(object):
|
|||||||
ext_net_map=args.external_networks_map,
|
ext_net_map=args.external_networks_map,
|
||||||
net_vni_map=args.networks_vni_map,
|
net_vni_map=args.networks_vni_map,
|
||||||
int_vni_map=args.internal_networks_vni_map,
|
int_vni_map=args.internal_networks_vni_map,
|
||||||
|
vif_ids_map=args.vif_ids_map,
|
||||||
logfile=args.logfile,
|
logfile=args.logfile,
|
||||||
max_retry=args.max_retry,
|
max_retry=args.max_retry,
|
||||||
cert_file=args.cert_file)
|
cert_file=args.cert_file)
|
||||||
@ -191,6 +192,10 @@ class ApiReplayCli(object):
|
|||||||
"--internal-networks-vni-map",
|
"--internal-networks-vni-map",
|
||||||
help="Path to a json file mapping internal network ID "
|
help="Path to a json file mapping internal network ID "
|
||||||
"to its backend vni.")
|
"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(
|
parser.add_argument(
|
||||||
"--max-retry",
|
"--max-retry",
|
||||||
|
@ -56,7 +56,7 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
|||||||
octavia_os_tenant_name, octavia_os_tenant_domain_id,
|
octavia_os_tenant_name, octavia_os_tenant_domain_id,
|
||||||
octavia_os_password, octavia_os_auth_url,
|
octavia_os_password, octavia_os_auth_url,
|
||||||
neutron_conf, ext_net_map, net_vni_map, int_vni_map,
|
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
|
# Init config and logging
|
||||||
if neutron_conf:
|
if neutron_conf:
|
||||||
@ -153,6 +153,13 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
|||||||
else:
|
else:
|
||||||
self.int_vni_map = None
|
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.n_errors = 0
|
||||||
self.errors = []
|
self.errors = []
|
||||||
|
|
||||||
@ -687,7 +694,8 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
|||||||
port['id'])
|
port['id'])
|
||||||
continue
|
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
|
# specify the network_id that we just created above
|
||||||
port['network_id'] = network['id']
|
port['network_id'] = network['id']
|
||||||
|
@ -268,7 +268,8 @@ class PrepareObjectForMigration(object):
|
|||||||
body.pop(field)
|
body.pop(field)
|
||||||
return body
|
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)
|
self.fix_description(port)
|
||||||
body = self.drop_fields(port, self.drop_port_fields)
|
body = self.drop_fields(port, self.drop_port_fields)
|
||||||
if remove_qos:
|
if remove_qos:
|
||||||
@ -296,6 +297,9 @@ class PrepareObjectForMigration(object):
|
|||||||
body['port_security_enabled'] = False
|
body['port_security_enabled'] = False
|
||||||
body['security_groups'] = []
|
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 direct_call:
|
||||||
if 'device_id' not in body:
|
if 'device_id' not in body:
|
||||||
body['device_id'] = ""
|
body['device_id'] = ""
|
||||||
|
@ -35,6 +35,9 @@ ID_WITH_POST = {'allow_post': True, 'allow_put': False,
|
|||||||
RESOURCE_ATTRIBUTE_MAP = {
|
RESOURCE_ATTRIBUTE_MAP = {
|
||||||
'ports': {
|
'ports': {
|
||||||
'id': ID_WITH_POST,
|
'id': ID_WITH_POST,
|
||||||
|
'vif_id': {'allow_post': True, 'allow_put': False,
|
||||||
|
'default': '',
|
||||||
|
'is_visible': True},
|
||||||
},
|
},
|
||||||
'networks': {
|
'networks': {
|
||||||
'id': ID_WITH_POST,
|
'id': ID_WITH_POST,
|
||||||
|
@ -1716,7 +1716,12 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||||||
context, port_data)
|
context, port_data)
|
||||||
device_owner = port_data.get('device_owner')
|
device_owner = port_data.get('device_owner')
|
||||||
vif_id = None
|
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
|
# 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
|
# MP ports won't be created for VMs before neutron sets the vif-id
|
||||||
vif_id = port_data['id']
|
vif_id = port_data['id']
|
||||||
|
@ -53,19 +53,6 @@ def post_v2t_migration_cleanups(resource, event, trigger, **kwargs):
|
|||||||
section['id'])
|
section['id'])
|
||||||
continue
|
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
|
@admin_utils.output_header
|
||||||
def migration_tier0_redistribute(resource, event, trigger, **kwargs):
|
def migration_tier0_redistribute(resource, event, trigger, **kwargs):
|
||||||
|
@ -17,6 +17,7 @@ import sys
|
|||||||
import netaddr
|
import netaddr
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
from networking_l2gw.db.l2gateway import l2gateway_models
|
from networking_l2gw.db.l2gateway import l2gateway_models
|
||||||
from neutron.services.qos import qos_plugin
|
from neutron.services.qos import qos_plugin
|
||||||
@ -37,6 +38,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.lbaas.octavia import constants as oct_const
|
||||||
from vmware_nsx.services.qos.nsx_v3 import pol_utils as qos_utils
|
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 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.common import utils as admin_utils
|
||||||
from vmware_nsx.shell.admin.plugins.nsxv.resources import utils
|
from vmware_nsx.shell.admin.plugins.nsxv.resources import utils
|
||||||
from vmware_nsx.shell import resources as shell
|
from vmware_nsx.shell import resources as shell
|
||||||
@ -356,6 +358,47 @@ def validate_config_for_migration(resource, event, trigger, **kwargs):
|
|||||||
"NSX-T.")
|
"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,
|
registry.subscribe(validate_config_for_migration,
|
||||||
constants.NSX_MIGRATE_V_T,
|
constants.NSX_MIGRATE_V_T,
|
||||||
shell.Operations.VALIDATE.value)
|
shell.Operations.VALIDATE.value)
|
||||||
|
|
||||||
|
registry.subscribe(list_ports_vif_ids,
|
||||||
|
constants.PORTS,
|
||||||
|
shell.Operations.LIST.value)
|
||||||
|
@ -256,6 +256,8 @@ nsxv_resources = {
|
|||||||
Operations.DELETE.value]),
|
Operations.DELETE.value]),
|
||||||
constants.NSX_MIGRATE_V_T: Resource(constants.NSX_MIGRATE_V_T,
|
constants.NSX_MIGRATE_V_T: Resource(constants.NSX_MIGRATE_V_T,
|
||||||
[Operations.VALIDATE.value]),
|
[Operations.VALIDATE.value]),
|
||||||
|
constants.PORTS: Resource(constants.PORTS,
|
||||||
|
[Operations.LIST.value]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user