diff --git a/vmware_nsx/plugins/nsx_p/plugin.py b/vmware_nsx/plugins/nsx_p/plugin.py index f8855ef790..ba801f5448 100644 --- a/vmware_nsx/plugins/nsx_p/plugin.py +++ b/vmware_nsx/plugins/nsx_p/plugin.py @@ -3029,8 +3029,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): context, router_id, router) # Update the policy backend + added_routes = removed_routes = False try: - added_routes = removed_routes = False # Updating name & description if 'name' in router_data or 'description' in router_data: router_name = utils.get_name_and_uuid( diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py index 2d377012b4..35ddc17bab 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -1356,6 +1356,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, dvs_pg_mappings): self._delete_backend_network( netmoref, dvsmoref) + # Define variable to satisfy pylint check (E0601) + predefined = None try: net_data[psec.PORTSECURITY] = net_data.get(psec.PORTSECURITY, True) if not cfg.CONF.nsxv.spoofguard_enabled: diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index 98a717a63a..51c9e6d05d 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -935,8 +935,9 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base, vlt)) is_backend_network = True + # Define variable here to avoid pylint E0601 + rollback_network = False try: - rollback_network = False with db_api.CONTEXT_WRITER.using(context): # Create network in Neutron created_net = super(NsxV3Plugin, self).create_network(context, diff --git a/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py b/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py index caf3015cf4..c1d597ff57 100644 --- a/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py +++ b/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py @@ -54,14 +54,7 @@ def list_networks(resource, event, trigger, **kwargs): return bool(mappings) -@admin_utils.output_header -def migrate_dhcp_to_policy(resource, event, trigger, **kwargs): - errmsg = ("Need to specify policy dhcp config id. Add " - "--property dhcp-config=") - if not kwargs.get('property'): - LOG.error("%s", errmsg) - return - properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) +def _validate_dhcp_operation(properties, nsxpolicy, errmsg): dhcp_config_id = properties.get('dhcp-config') if not dhcp_config_id: LOG.error("%s", errmsg) @@ -79,11 +72,115 @@ def migrate_dhcp_to_policy(resource, event, trigger, **kwargs): except Exception: LOG.error("%s", errmsg) return + return dhcp_config_id + +@admin_utils.output_header +def migrate_dhcp_to_policy(resource, event, trigger, **kwargs): + errmsg = ("Need to specify policy dhcp profile id. Add " + "--property dhcp-config=") + if not kwargs.get('property'): + LOG.error("%s", errmsg) + return + properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) + nsxpolicy = p_utils.get_connected_nsxpolicy() + dhcp_config_id = _validate_dhcp_operation(properties, nsxpolicy, errmsg) + if not dhcp_config_id: + LOG.error("Unable to proceed. Please address errors and retry.") + return + + ctx = context.get_admin_context() + migrated_networks = [] + skipped_networks = [] + failed_networks = {} + with p_utils.NsxPolicyPluginWrapper() as plugin: + nets = plugin.get_networks(ctx) + for net in nets: + # skip non-dhcp networks + subnets = plugin._get_subnets_by_network(ctx, net['id']) + dhcp_subnet_id = None + for subnet in subnets: + if subnet['enable_dhcp']: + dhcp_subnet_id = subnet['id'] + break + if not dhcp_subnet_id: + LOG.info("Skipping network %s: No DHCP subnet found", + net['id']) + skipped_networks.append(net['id']) + continue + az = plugin.get_network_az_by_net_id(ctx, net['id']) + az._policy_dhcp_server_config = dhcp_config_id + dhcp_subnet = plugin.get_subnet(ctx, dhcp_subnet_id) + + # Verify that this network does not use policy DHCP already + segment_id = plugin._get_network_nsx_segment_id(ctx, net['id']) + segment = nsxpolicy.segment.get(segment_id) + if segment.get('dhcp_config_path'): + LOG.info("Skipping network %s: Already using policy DHCP", + net['id']) + skipped_networks.append(net['id']) + continue + + LOG.info("Migrating network %s", net['id']) + try: + # Disable MP DHCP + plugin._disable_native_dhcp(ctx, net['id']) + # Enable Policy DHCP, restore bindings + plugin._update_nsx_net_dhcp(ctx, net, az, dhcp_subnet) + LOG.info("Successfully migrated network %s", net['id']) + except Exception as e: + LOG.error("Failure while migrating network %s: %s", + net['id'], e) + failed_networks[net['id']] = e + migrated_networks.append(net['id']) + + if not failed_networks and not skipped_networks: + LOG.info("DHCP for %s networks has been migrated to policy", + len(migrated_networks)) + return + # Some networks were skipped or failed. Log everything + mappings = [] + for net_id in migrated_networks: + mappings.append({ + 'net': net_id, + 'status': 'MIGRATED', + 'details': ''}) + for net_id in skipped_networks: + mappings.append({ + 'net': net_id, + 'status': 'SKIPPED', + 'details': ''}) + for net_id, exc in failed_networks.items(): + mappings.append({ + 'net': net_id, + 'status': 'FAILED', + 'details': str(exc)}) + p_utils.log_info(constants.NETWORKS, + mappings, + attrs=['net', 'status', 'details']) + + +@admin_utils.output_header +def restore_dhcp_to_policy(resource, event, trigger, **kwargs): + errmsg = ("Need to specify policy dhcp config id. Add " + "--property dhcp-config=") + if not kwargs.get('property'): + LOG.error("%s", errmsg) + return + properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) + nsxpolicy = p_utils.get_connected_nsxpolicy() + dhcp_config_id = _validate_dhcp_operation(properties, nsxpolicy, errmsg) + if not dhcp_config_id: + LOG.error("Unable to proceed. Please address errors and retry.") + return + network_id = properties.get('network-id') ctx = context.get_admin_context() migrate_count = 0 with p_utils.NsxPolicyPluginWrapper() as plugin: - nets = plugin.get_networks(ctx) + if network_id: + nets = [plugin.get_network(ctx, network_id)] + else: + nets = plugin.get_networks(ctx) for net in nets: # skip non-dhcp networks dhcp_port = plugin._get_net_dhcp_port(ctx, net['id']) @@ -97,22 +194,12 @@ def migrate_dhcp_to_policy(resource, event, trigger, **kwargs): az._policy_dhcp_server_config = dhcp_config_id dhcp_subnet = plugin.get_subnet(ctx, dhcp_subnet_id) - # Verify that this network does not use policy DHCP already - segment_id = plugin._get_network_nsx_segment_id(ctx, net['id']) - segment = nsxpolicy.segment.get(segment_id) - if segment.get('dhcp_config_path'): - LOG.info("Skipping network %s: Already using policy DHCP", - net['id']) - continue - - LOG.info("Migrating network %s", net['id']) - # Disable MP DHCP - plugin._disable_native_dhcp(ctx, net['id']) - # Enable Policy DHCP - plugin._enable_subnet_dhcp(ctx, net, dhcp_subnet, az) + LOG.info("Attempting to restore DHCP on network %s", net['id']) + # Enable Policy DHCP, restore bindings + plugin._update_nsx_net_dhcp(ctx, net, az, dhcp_subnet) migrate_count = migrate_count + 1 - LOG.info("Finished migrating %s networks", migrate_count) + LOG.info("Finished processing %s networks", migrate_count) @admin_utils.output_header @@ -150,3 +237,7 @@ registry.subscribe(update_admin_state, registry.subscribe(migrate_dhcp_to_policy, constants.DHCP_BINDING, shell.Operations.MIGRATE_TO_POLICY.value) + +registry.subscribe(restore_dhcp_to_policy, + constants.DHCP_BINDING, + shell.Operations.RESTORE_POLICY_DHCP.value) diff --git a/vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py b/vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py index 8d26765d8f..d6f6104020 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py +++ b/vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py @@ -1380,8 +1380,8 @@ def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin, LOG.info("Aborting the current request") try: send_migration_plan_action(nsxlib, 'abort') - except Exception as e: - LOG.error("Abort migration failed: %s", e) + except Exception as e2: + LOG.error("Abort migration failed: %s", e2) if ROLLBACK_DATA: LOG.info("Rolling migration back %s", ROLLBACK_DATA) @@ -1392,8 +1392,8 @@ def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin, # Stop the migration service if start_migration_service: change_migration_service_status(start=False) - except Exception as e: - LOG.error("Rollback failed: %s", e) + except Exception as e2: + LOG.error("Rollback failed: %s", e2) return False diff --git a/vmware_nsx/shell/resources.py b/vmware_nsx/shell/resources.py index ecf2baa87f..369e6149f6 100644 --- a/vmware_nsx/shell/resources.py +++ b/vmware_nsx/shell/resources.py @@ -68,6 +68,7 @@ class Operations(enum.Enum): MIGRATE_TO_DYNAMIC_CRITERIA = 'migrate-to-dynamic-criteria' NSX_MIGRATE_V_V3 = 'nsx-migrate-v-v3' MIGRATE_TO_POLICY = 'migrate-to-policy' + RESTORE_POLICY_DHCP = 'restore-policy-dhcp' LIST_POLICIES = 'list-policies' UPDATE_LOGGING = 'update-logging' NSX_MIGRATE_EXCLUDE_PORTS = 'migrate-exclude-ports' @@ -296,7 +297,8 @@ nsxp_resources = { [Operations.LIST.value, Operations.NSX_UPDATE_STATE.value]), constants.DHCP_BINDING: Resource(constants.DHCP_BINDING, - [Operations.MIGRATE_TO_POLICY.value]), + [Operations.MIGRATE_TO_POLICY.value, + Operations.RESTORE_POLICY_DHCP.value]), constants.ROUTERS: Resource(constants.ROUTERS, [Operations.LIST.value, Operations.UPDATE_TIER0.value, diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index be5b05dd86..9dc5465f3a 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -1036,6 +1036,9 @@ class TestSubnetsV2(common_v3.NsxV3TestSubnets, NsxV3PluginTestCaseMixin): def test_create_subnet_ipv6_slaac_with_db_reference_error(self): self.skipTest('No DHCP v6 Support yet') + def test_update_subnet_the_same_gw_as_in_use_by_router_ipv6(self): + self.skipTest('No DHCP v6 Support yet') + class TestPortsV2(common_v3.NsxV3SubnetMixin, common_v3.NsxV3TestPorts, NsxV3PluginTestCaseMixin,