Fix migration of DHCP to NSX policy
Ensure DHCP bindings are properly created for existing Neutron ports when DHCP is enabled on NSX Policy. Enhance output to report list of skipped and failed networks. Also, add an utility for regenerating bindings post-migration. Finally, this change removes some debug log statements, and makes some changes to satisfy pylint checks for error E0601. Change-Id: Idc6870d5a7896f9b9aeda2ea2f102a59b13eb523
This commit is contained in:
parent
c8919cdbaf
commit
85e77c2377
@ -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(
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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=<id>")
|
||||
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=<id>")
|
||||
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=<id>")
|
||||
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)
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user