diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index 2c4a35ec19..ec7350f276 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -595,6 +595,10 @@ Config T2P migration ~~~~~~~~~~~~~ +- Verify the current configuration can be migrated to Policy:: + + nsxadmin -r nsx-migrate-t2p -o validate + - Migrate NSX resources and neutron DB from NSX-T (MP) to Policy:: nsxadmin -r nsx-migrate-t2p -o import --property logfile=<> (--verbose) diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py index 0cca731fd4..73b8cb7ef4 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py @@ -1101,11 +1101,6 @@ def migrate_lb_services(nsxlib, nsxpolicy): def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin): """Create policy resources for all MP resources used by neutron""" - nsx_version = nsxlib.get_version() - if not nsx_utils.is_nsx_version_3_1_0(nsx_version): - LOG.error("Migration not supported for NSX %s", nsx_version) - return False - # Initialize the migration process if not ensure_migration_state_ready(nsxlib, with_abort=True): return False @@ -1376,8 +1371,12 @@ def edge_firewall_migration_cond(resource): def pre_migration_checks(nsxlib, plugin): - """Check for unsupported configuration that will block the migration - """ + """Check for unsupported configuration that will fail the migration""" + nsx_version = nsxlib.get_version() + if not nsx_utils.is_nsx_version_3_1_0(nsx_version): + LOG.error("Pre migration check failed: Migration not supported for " + "NSX %s", nsx_version) + return False # Cannot migrate with unsupported services service_plugins = cfg.CONF.service_plugins @@ -1420,11 +1419,31 @@ def pre_migration_checks(nsxlib, plugin): MIGRATE_LIMIT_SECTION_AND_RULES) return False + # DHCP relay is unsupported + if plugin._availability_zones_data.dhcp_relay_configured(): + LOG.error("Pre migration check failed: DHCP relay configuration " + "cannot be migrated. Please remove it from the plugin " + "configuration and from all NSX logical router ports and " + "try again.") + return False + return True @admin_utils.output_header -def t_2_p_migration(resource, event, trigger, **kwargs): +def MP2Policy_pre_migration_check(resource, event, trigger, **kwargs): + """Verify if the current configuration can be migrated to Policy""" + nsxlib = utils.get_connected_nsxlib() + with utils.NsxV3PluginWrapper() as plugin: + if not pre_migration_checks(nsxlib, plugin): + # Failed + LOG.error("T2P migration cannot run. Please fix the configuration " + "and try again\n\n") + exit(1) + + +@admin_utils.output_header +def MP2Policy_migration(resource, event, trigger, **kwargs): """Migrate NSX resources and neutron DB from NSX-T (MP) to Policy""" verbose = kwargs.get('verbose', False) @@ -1452,20 +1471,21 @@ def t_2_p_migration(resource, event, trigger, **kwargs): 'nsx_api_managers', [cfg.CONF.nsx_v3.nsx_api_managers[0]], 'nsx_v3') - if (len(cfg.CONF.nsx_v3.nsx_api_user) and - len(cfg.CONF.nsx_v3.nsx_api_password)): - cfg.CONF.set_override( - 'nsx_api_user', - [cfg.CONF.nsx_v3.nsx_api_user[0]], - 'nsx_v3') - cfg.CONF.set_override( - 'nsx_api_password', - [cfg.CONF.nsx_v3.nsx_api_password[0]], - 'nsx_v3') - else: - LOG.error("Please provide nsx_api_user and nsx_api_password " - "in the configuration") - return + # Make sure user & password are set in the config + if (len(cfg.CONF.nsx_v3.nsx_api_user) and + len(cfg.CONF.nsx_v3.nsx_api_password)): + cfg.CONF.set_override( + 'nsx_api_user', + [cfg.CONF.nsx_v3.nsx_api_user[0]], + 'nsx_v3') + cfg.CONF.set_override( + 'nsx_api_password', + [cfg.CONF.nsx_v3.nsx_api_password[0]], + 'nsx_v3') + else: + LOG.error("Please provide nsx_api_user and nsx_api_password " + "in the configuration") + exit(1) retriables = [nsxlib_exc.APITransactionAborted, nsxlib_exc.ServerBusy] @@ -1492,7 +1512,7 @@ def t_2_p_migration(resource, event, trigger, **kwargs): # Failed LOG.error("T2P migration cannot run. Please fix the configuration " "and try again\n\n") - return + exit(1) elapsed_time = time.time() - start_time LOG.debug("Pre-migration took %s seconds", elapsed_time) @@ -1500,7 +1520,7 @@ def t_2_p_migration(resource, event, trigger, **kwargs): if not migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin): # Failed LOG.error("T2P migration failed. Aborting\n\n") - return + exit(1) elapsed_time = time.time() - start_time LOG.debug("Migration took %s seconds", elapsed_time) @@ -1513,7 +1533,7 @@ def t_2_p_migration(resource, event, trigger, **kwargs): @admin_utils.output_header -def cleanup_db_mappings(resource, event, trigger, **kwargs): +def MP2Policy_cleanup_db_mappings(resource, event, trigger, **kwargs): """Delete all entries from nsx-t mapping tables in DB""" confirm = admin_utils.query_yes_no( "Are you sure you want to delete all MP plugin mapping DB tables?", @@ -1543,10 +1563,14 @@ def cleanup_db_mappings(resource, event, trigger, **kwargs): LOG.info("Deleted all MP plugin mapping DB tables.") -registry.subscribe(t_2_p_migration, +registry.subscribe(MP2Policy_migration, constants.NSX_MIGRATE_T_P, shell.Operations.IMPORT.value) -registry.subscribe(cleanup_db_mappings, +registry.subscribe(MP2Policy_pre_migration_check, + constants.NSX_MIGRATE_T_P, + shell.Operations.VALIDATE.value) + +registry.subscribe(MP2Policy_cleanup_db_mappings, constants.NSX_MIGRATE_T_P, shell.Operations.CLEAN_ALL.value) diff --git a/vmware_nsx/shell/resources.py b/vmware_nsx/shell/resources.py index 9ddbe56fae..7ed642df1a 100644 --- a/vmware_nsx/shell/resources.py +++ b/vmware_nsx/shell/resources.py @@ -157,7 +157,8 @@ nsxv3_resources = { [Operations.SHOW.value]), constants.NSX_MIGRATE_T_P: Resource(constants.NSX_MIGRATE_T_P, [Operations.IMPORT.value, - Operations.CLEAN_ALL.value]), + Operations.CLEAN_ALL.value, + Operations.VALIDATE.value]), } # Add supported NSX-V resources in this dictionary diff --git a/vmware_nsx/tests/unit/shell/test_admin_utils.py b/vmware_nsx/tests/unit/shell/test_admin_utils.py index 58bfe75bd6..de4638a72c 100644 --- a/vmware_nsx/tests/unit/shell/test_admin_utils.py +++ b/vmware_nsx/tests/unit/shell/test_admin_utils.py @@ -42,6 +42,7 @@ from vmware_nsx.tests import unit as vmware from vmware_nsx.tests.unit.nsx_p import test_plugin as test_p_plugin from vmware_nsx.tests.unit.nsx_v import test_plugin as test_v_plugin from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_v3_plugin +from vmware_nsxlib.v3 import client as v3_client from vmware_nsxlib.v3 import core_resources from vmware_nsxlib.v3 import resources as nsx_v3_resources from vmware_nsxlib.v3 import security as nsx_v3_security @@ -306,8 +307,8 @@ class TestNsxv3AdminUtils(AbstractTestAdminUtils, for cls in (nsx_v3_resources.LogicalPort, nsx_v3_resources.LogicalDhcpServer, core_resources.NsxLibLogicalRouter, - core_resources.NsxLibSwitchingProfile): - + core_resources.NsxLibSwitchingProfile, + v3_client.RESTClient): self._patch_object(cls, 'list', return_value={'results': []}) self._patch_object(cls, 'get', return_value={'id': uuidutils.generate_uuid()}) @@ -321,6 +322,19 @@ class TestNsxv3AdminUtils(AbstractTestAdminUtils, return_value={'members': [{ 'target_type': 'LogicalPort', 'target_id': 'port_id'}]}) + + # Mocks for MP2P migration + mock.patch("vmware_nsxlib.v3.NsxLib.get_version", + return_value='3.1.0').start() + mock.patch("vmware_nsx.shell.admin.plugins.nsxv3.resources.migration." + "ensure_migration_state_ready", return_value=True).start() + mock.patch("vmware_nsx.shell.admin.plugins.nsxv3.resources.migration." + "change_migration_service_status").start() + + cfg.CONF.set_override('nsx_api_managers', ['1.1.1.1'], 'nsx_v3') + cfg.CONF.set_override('nsx_api_user', ['admin'], 'nsx_v3') + cfg.CONF.set_override('nsx_api_password', ['dummy'], 'nsx_v3') + super(TestNsxv3AdminUtils, self)._init_mock_plugin() self._plugin = nsxv3_utils.NsxV3PluginWrapper()