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
bf62f6b953
commit
c4818bcc31
|
@ -3018,8 +3018,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||||
context, router_id, router)
|
context, router_id, router)
|
||||||
|
|
||||||
# Update the policy backend
|
# Update the policy backend
|
||||||
|
added_routes = removed_routes = False
|
||||||
try:
|
try:
|
||||||
added_routes = removed_routes = False
|
|
||||||
# Updating name & description
|
# Updating name & description
|
||||||
if 'name' in router_data or 'description' in router_data:
|
if 'name' in router_data or 'description' in router_data:
|
||||||
router_name = utils.get_name_and_uuid(
|
router_name = utils.get_name_and_uuid(
|
||||||
|
|
|
@ -1356,6 +1356,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||||
dvs_pg_mappings):
|
dvs_pg_mappings):
|
||||||
self._delete_backend_network(
|
self._delete_backend_network(
|
||||||
netmoref, dvsmoref)
|
netmoref, dvsmoref)
|
||||||
|
# Define variable to satisfy pylint check (E0601)
|
||||||
|
predefined = None
|
||||||
try:
|
try:
|
||||||
net_data[psec.PORTSECURITY] = net_data.get(psec.PORTSECURITY, True)
|
net_data[psec.PORTSECURITY] = net_data.get(psec.PORTSECURITY, True)
|
||||||
if not cfg.CONF.nsxv.spoofguard_enabled:
|
if not cfg.CONF.nsxv.spoofguard_enabled:
|
||||||
|
|
|
@ -903,8 +903,9 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||||
vlt))
|
vlt))
|
||||||
is_backend_network = True
|
is_backend_network = True
|
||||||
|
|
||||||
|
# Define variable here to avoid pylint E0601
|
||||||
|
rollback_network = False
|
||||||
try:
|
try:
|
||||||
rollback_network = False
|
|
||||||
with db_api.CONTEXT_WRITER.using(context):
|
with db_api.CONTEXT_WRITER.using(context):
|
||||||
# Create network in Neutron
|
# Create network in Neutron
|
||||||
created_net = super(NsxV3Plugin, self).create_network(context,
|
created_net = super(NsxV3Plugin, self).create_network(context,
|
||||||
|
|
|
@ -54,14 +54,7 @@ def list_networks(resource, event, trigger, **kwargs):
|
||||||
return bool(mappings)
|
return bool(mappings)
|
||||||
|
|
||||||
|
|
||||||
@admin_utils.output_header
|
def _validate_dhcp_operation(properties, nsxpolicy, errmsg):
|
||||||
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'])
|
|
||||||
dhcp_config_id = properties.get('dhcp-config')
|
dhcp_config_id = properties.get('dhcp-config')
|
||||||
if not dhcp_config_id:
|
if not dhcp_config_id:
|
||||||
LOG.error("%s", errmsg)
|
LOG.error("%s", errmsg)
|
||||||
|
@ -79,11 +72,115 @@ def migrate_dhcp_to_policy(resource, event, trigger, **kwargs):
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.error("%s", errmsg)
|
LOG.error("%s", errmsg)
|
||||||
return
|
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()
|
ctx = context.get_admin_context()
|
||||||
migrate_count = 0
|
migrate_count = 0
|
||||||
with p_utils.NsxPolicyPluginWrapper() as plugin:
|
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:
|
for net in nets:
|
||||||
# skip non-dhcp networks
|
# skip non-dhcp networks
|
||||||
dhcp_port = plugin._get_net_dhcp_port(ctx, net['id'])
|
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
|
az._policy_dhcp_server_config = dhcp_config_id
|
||||||
dhcp_subnet = plugin.get_subnet(ctx, dhcp_subnet_id)
|
dhcp_subnet = plugin.get_subnet(ctx, dhcp_subnet_id)
|
||||||
|
|
||||||
# Verify that this network does not use policy DHCP already
|
LOG.info("Attempting to restore DHCP on network %s", net['id'])
|
||||||
segment_id = plugin._get_network_nsx_segment_id(ctx, net['id'])
|
# Enable Policy DHCP, restore bindings
|
||||||
segment = nsxpolicy.segment.get(segment_id)
|
plugin._update_nsx_net_dhcp(ctx, net, az, dhcp_subnet)
|
||||||
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)
|
|
||||||
migrate_count = migrate_count + 1
|
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
|
@admin_utils.output_header
|
||||||
|
@ -150,3 +237,7 @@ registry.subscribe(update_admin_state,
|
||||||
registry.subscribe(migrate_dhcp_to_policy,
|
registry.subscribe(migrate_dhcp_to_policy,
|
||||||
constants.DHCP_BINDING,
|
constants.DHCP_BINDING,
|
||||||
shell.Operations.MIGRATE_TO_POLICY.value)
|
shell.Operations.MIGRATE_TO_POLICY.value)
|
||||||
|
|
||||||
|
registry.subscribe(restore_dhcp_to_policy,
|
||||||
|
constants.DHCP_BINDING,
|
||||||
|
shell.Operations.RESTORE_POLICY_DHCP.value)
|
||||||
|
|
|
@ -1378,8 +1378,8 @@ def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin,
|
||||||
LOG.info("Aborting the current request")
|
LOG.info("Aborting the current request")
|
||||||
try:
|
try:
|
||||||
send_migration_plan_action(nsxlib, 'abort')
|
send_migration_plan_action(nsxlib, 'abort')
|
||||||
except Exception as e:
|
except Exception as e2:
|
||||||
LOG.error("Abort migration failed: %s", e)
|
LOG.error("Abort migration failed: %s", e2)
|
||||||
|
|
||||||
if ROLLBACK_DATA:
|
if ROLLBACK_DATA:
|
||||||
LOG.info("Rolling migration back %s", ROLLBACK_DATA)
|
LOG.info("Rolling migration back %s", ROLLBACK_DATA)
|
||||||
|
@ -1390,8 +1390,8 @@ def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin,
|
||||||
# Stop the migration service
|
# Stop the migration service
|
||||||
if start_migration_service:
|
if start_migration_service:
|
||||||
change_migration_service_status(start=False)
|
change_migration_service_status(start=False)
|
||||||
except Exception as e:
|
except Exception as e2:
|
||||||
LOG.error("Rollback failed: %s", e)
|
LOG.error("Rollback failed: %s", e2)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ class Operations(enum.Enum):
|
||||||
NSX_TAG_DEFAULT = 'nsx-tag-default'
|
NSX_TAG_DEFAULT = 'nsx-tag-default'
|
||||||
NSX_MIGRATE_V_V3 = 'nsx-migrate-v-v3'
|
NSX_MIGRATE_V_V3 = 'nsx-migrate-v-v3'
|
||||||
MIGRATE_TO_POLICY = 'migrate-to-policy'
|
MIGRATE_TO_POLICY = 'migrate-to-policy'
|
||||||
|
RESTORE_POLICY_DHCP = 'restore-policy-dhcp'
|
||||||
LIST_POLICIES = 'list-policies'
|
LIST_POLICIES = 'list-policies'
|
||||||
UPDATE_LOGGING = 'update-logging'
|
UPDATE_LOGGING = 'update-logging'
|
||||||
NSX_MIGRATE_EXCLUDE_PORTS = 'migrate-exclude-ports'
|
NSX_MIGRATE_EXCLUDE_PORTS = 'migrate-exclude-ports'
|
||||||
|
@ -286,7 +287,8 @@ nsxp_resources = {
|
||||||
[Operations.LIST.value,
|
[Operations.LIST.value,
|
||||||
Operations.NSX_UPDATE_STATE.value]),
|
Operations.NSX_UPDATE_STATE.value]),
|
||||||
constants.DHCP_BINDING: Resource(constants.DHCP_BINDING,
|
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,
|
constants.ROUTERS: Resource(constants.ROUTERS,
|
||||||
[Operations.LIST.value,
|
[Operations.LIST.value,
|
||||||
Operations.UPDATE_TIER0.value,
|
Operations.UPDATE_TIER0.value,
|
||||||
|
|
|
@ -995,6 +995,9 @@ class TestSubnetsV2(common_v3.NsxV3TestSubnets, NsxV3PluginTestCaseMixin):
|
||||||
def test_create_subnet_ipv6_slaac_with_db_reference_error(self):
|
def test_create_subnet_ipv6_slaac_with_db_reference_error(self):
|
||||||
self.skipTest('No DHCP v6 Support yet')
|
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,
|
class TestPortsV2(common_v3.NsxV3SubnetMixin,
|
||||||
common_v3.NsxV3TestPorts, NsxV3PluginTestCaseMixin,
|
common_v3.NsxV3TestPorts, NsxV3PluginTestCaseMixin,
|
||||||
|
|
Loading…
Reference in New Issue