Merge "MP2P migration: manually migrate edge firewall sections" into stable/ussuri

This commit is contained in:
Zuul 2020-07-15 13:29:34 +00:00 committed by Gerrit Code Review
commit 0058b4ad55
6 changed files with 86 additions and 87 deletions

View File

@ -2898,6 +2898,10 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
"as default %(e)s", "as default %(e)s",
{'id': secgroup_db['id'], 'e': e}) {'id': secgroup_db['id'], 'e': e})
def verify_sr_at_backend(self, context, router_id):
"""Should be implemented by each plugin"""
pass
class TagsCallbacks(object): class TagsCallbacks(object):

View File

@ -2466,8 +2466,10 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
return True return True
return False return False
def verify_sr_at_backend(self, router_id): def verify_sr_at_backend(self, context, router_id):
"""Check if the backend Tier1 has a service router or not""" """Check if the backend Tier1 has a service router or not"""
# Note - this method gets the context so it will have the same
# signature as the v3 plugin method
if self.nsxpolicy.tier1.get_edge_cluster_path(router_id): if self.nsxpolicy.tier1.get_edge_cluster_path(router_id):
return True return True
@ -2596,7 +2598,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
new_enable_snat = router.enable_snat new_enable_snat = router.enable_snat
newaddr, newmask, _newnexthop = self._get_external_attachment_info( newaddr, newmask, _newnexthop = self._get_external_attachment_info(
context, router) context, router)
sr_currently_exists = self.verify_sr_at_backend(router_id) sr_currently_exists = self.verify_sr_at_backend(context, router_id)
fw_exist = self._router_has_edge_fw_rules(context, router) fw_exist = self._router_has_edge_fw_rules(context, router)
vpn_exist = self.service_router_has_vpnaas(context, router_id) vpn_exist = self.service_router_has_vpnaas(context, router_id)
lb_exist = False lb_exist = False
@ -3039,7 +3041,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
prefix_len=prefix_len)) prefix_len=prefix_len))
# Service router is mandatory for VLAN interfaces # Service router is mandatory for VLAN interfaces
if not self.verify_sr_at_backend(router_id): if not self.verify_sr_at_backend(context, router_id):
self.create_service_router( self.create_service_router(
context, router_id, router=router_db, context, router_id, router=router_db,
update_firewall=False) update_firewall=False)

View File

@ -378,7 +378,7 @@ class NsxpFwaasCallbacksV2(com_callbacks.NsxCommonv3FwaasCallbacksV2):
self._set_rules_order(fw_rules) self._set_rules_order(fw_rules)
# Update the backend router firewall # Update the backend router firewall
sr_exists_on_backend = plugin.verify_sr_at_backend(router_id) sr_exists_on_backend = plugin.verify_sr_at_backend(context, router_id)
if called_from_fw: if called_from_fw:
# FW action required # FW action required
if router_with_fw: if router_with_fw:

View File

@ -671,7 +671,7 @@ class NSXpIPsecVpnDriver(common_driver.NSXcommonIPsecVpnDriver):
# Make sure this tier1 has service router # Make sure this tier1 has service router
router_id = vpnservice['router_id'] router_id = vpnservice['router_id']
if not self._core_plugin.verify_sr_at_backend(router_id): if not self._core_plugin.verify_sr_at_backend(context, router_id):
self._core_plugin.create_service_router(context, router_id) self._core_plugin.create_service_router(context, router_id)
# create the NSX vpn service # create the NSX vpn service

View File

@ -18,6 +18,7 @@ import logging
import paramiko import paramiko
import tenacity import tenacity
from neutron_fwaas.db.firewall.v2 import firewall_db_v2
from neutron_lib.callbacks import registry from neutron_lib.callbacks import registry
from neutron_lib import context from neutron_lib import context
from oslo_config import cfg from oslo_config import cfg
@ -29,6 +30,7 @@ from vmware_nsx.plugins.nsx_p import plugin as p_plugin
from vmware_nsx.plugins.nsx_v3 import cert_utils from vmware_nsx.plugins.nsx_v3 import cert_utils
from vmware_nsx.plugins.nsx_v3 import plugin as v3_plugin from vmware_nsx.plugins.nsx_v3 import plugin as v3_plugin
from vmware_nsx.plugins.nsx_v3 import utils as v3_plugin_utils from vmware_nsx.plugins.nsx_v3 import utils as v3_plugin_utils
from vmware_nsx.services.fwaas.nsx_p import fwaas_callbacks_v2
from vmware_nsx.services.lbaas import lb_const from vmware_nsx.services.lbaas import lb_const
from vmware_nsx.services.lbaas.nsx_p.implementation import lb_utils from vmware_nsx.services.lbaas.nsx_p.implementation import lb_utils
from vmware_nsx.shell.admin.plugins.common import constants from vmware_nsx.shell.admin.plugins.common import constants
@ -1078,62 +1080,6 @@ def migrate_lb_services(nsxlib, nsxpolicy):
MIGRATE_LIMIT_LB_SERVICE) MIGRATE_LIMIT_LB_SERVICE)
def edge_firewall_migration_cond(resource):
return (resource.get('display_name') == 'Default LR Layer3 Section' and
resource.get('enforced_on') == 'LOGICALROUTER' and
resource.get('category') == 'Default' and
resource.get('section_type') == 'LAYER3')
def migrate_fwaas_resources(nsxlib, nsxpolicy, migrated_routers):
def get_policy_id_callback(res, policy_id):
# Policy id should be the Policy tier1 id (=neutron id)
ctx = context.get_admin_context()
nsx_id = res['applied_tos'][0]['target_id']
return db.get_neutron_from_nsx_router_id(
ctx.session, nsx_id)
def cond(resource):
# Migrate only Edge firewalls related to the migrated tier1s
return (edge_firewall_migration_cond(resource) and
resource['applied_tos'][0].get(
'target_id', '') in migrated_routers)
def add_metadata(entry, policy_id, resource):
# Add category, sequence and rule ids
global EDGE_FW_SEQ
metadata = [{'key': 'category',
'value': policy_constants.CATEGORY_LOCAL_GW},
{'key': 'sequence', 'value': str(EDGE_FW_SEQ)}]
EDGE_FW_SEQ = EDGE_FW_SEQ + 1
# Add the rules
rules = nsxlib.firewall_section.get_rules(resource['id'])['results']
linked_ids = []
seq = 1
for rule in rules:
linked_ids.append({'key': rule['id'], 'value': str(seq)})
# The id of the policy rule will be random
seq = seq + 1
entry['metadata'] = metadata
entry['linked_ids'] = linked_ids
def get_policy_section(sec_id, silent=False):
return nsxpolicy.gateway_policy.get(
policy_constants.DEFAULT_DOMAIN, sec_id, silent=silent)
entries = get_resource_migration_data(
nsxlib.firewall_section, None,
'EDGE_FIREWALL_SECTION', resource_condition=cond,
policy_resource_get=get_policy_section,
policy_id_callback=get_policy_id_callback,
metadata_callback=add_metadata)
# Edge firewall migration is not supported yet
migrate_resource(nsxlib, 'EDGE_FIREWALL_SECTION', entries,
MIGRATE_LIMIT_SECTION_AND_RULES,
count_internals=True)
def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin): def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin):
"""Create policy resources for all MP resources used by neutron""" """Create policy resources for all MP resources used by neutron"""
@ -1168,7 +1114,6 @@ def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin):
# Migrate firewall sections last as those take the longest to rollback # Migrate firewall sections last as those take the longest to rollback
# in case of error # in case of error
migrate_dfw_sections(nsxlib, nsxpolicy, plugin) migrate_dfw_sections(nsxlib, nsxpolicy, plugin)
migrate_fwaas_resources(nsxlib, nsxpolicy, mp_routers)
# Finalize the migration (cause policy realization) # Finalize the migration (cause policy realization)
end_migration_process(nsxlib) end_migration_process(nsxlib)
@ -1347,31 +1292,72 @@ def post_migration_actions(nsxlib, nsxpolicy, nsxpolicy_admin, plugin):
LOG.debug("Updated gateway of network %s", net['id']) LOG.debug("Updated gateway of network %s", net['id'])
break break
# Update tags on DFW sections # -- Migrate edge firewall sections:
# The MP plugin uses the default MP edge firewall section, while the policy
# plugin uses a non default one, so regular migration cannot be used.
# Instead, create new edge firewall sections, and remove rules from the MP
# default sections
# This is a hack to use the v3 plugin with the policy fwaas driver
class MigrationNsxpFwaasCallbacks(fwaas_callbacks_v2.NsxpFwaasCallbacksV2):
def __init__(self, with_rpc):
super(MigrationNsxpFwaasCallbacks, self).__init__(with_rpc)
# Make sure fwaas is considered as enabled
self.fwaas_enabled = True
def _get_port_firewall_group_id(self, context, port_id):
# Override this api because directory.get_plugin does not work from
# admin utils context.
driver_db = firewall_db_v2.FirewallPluginDb()
return driver_db.get_fwg_attached_to_port(context, port_id)
fwaas_callbacks = MigrationNsxpFwaasCallbacks(False)
plugin.nsxpolicy = nsxpolicy
routers = plugin.get_routers(ctx) routers = plugin.get_routers(ctx)
nsx_router_sections = []
for rtr in routers: for rtr in routers:
try: nsx_router_id = db.get_nsx_router_id(ctx.session, rtr['id'])
# Check if the edge firewall section exists nsx_rtr = nsxlib.logical_router.get(nsx_router_id)
nsxpolicy.gateway_policy.get( for sec in nsx_rtr.get('firewall_sections', []):
policy_constants.DEFAULT_DOMAIN, map_id=rtr['id'], section_id = sec['target_id']
silent=True) section = nsxlib.firewall_section.get(section_id)
except nsxlib_exc.ResourceNotFound: if section['display_name'] != 'Default LR Layer3 Section':
pass continue
else: rules = nsxlib.firewall_section.get_rules(section_id)['results']
# Update section tags if len(rules) <= 1:
tags = nsxpolicy.build_v3_tags_payload( continue
rtr, resource_type='os-neutron-router-id', # Non default rules exist. need to migrate this section
project_name=ctx.tenant_name) router_db = plugin._get_router(ctx, rtr['id'])
nsxpolicy.gateway_policy.update( ports = plugin._get_router_interfaces(ctx, rtr['id'])
policy_constants.DEFAULT_DOMAIN, fwaas_callbacks.update_router_firewall(
map_id=rtr['id'], ctx, rtr['id'], router_db, ports)
tags=tags) LOG.debug("Created GW policy for router %s", rtr['id'])
LOG.debug("Updated tags of gateway policy for router %s",
rtr['id']) # delete rule from the default mp section at the end of the loop
# so the new section will have time to realize
nsx_router_sections.append({'id': section_id,
'default_rule': rules[-1],
'router_id': rtr['id']})
# Remove old rules from the default sections
for section in nsx_router_sections:
# make sure the policy section was already realized
nsxpolicy.gateway_policy.wait_until_realized(
policy_constants.DEFAULT_DOMAIN, section['router_id'])
nsxlib.firewall_section.update(
section['id'], rules=[section['default_rule']])
LOG.debug("Deleted MP edge FW section %s rules", section['id'])
LOG.info("Post-migration actions done.") LOG.info("Post-migration actions done.")
def edge_firewall_migration_cond(resource):
return (resource.get('display_name') == 'Default LR Layer3 Section' and
resource.get('enforced_on') == 'LOGICALROUTER' and
resource.get('category') == 'Default' and
resource.get('section_type') == 'LAYER3')
def pre_migration_checks(nsxlib, plugin): def pre_migration_checks(nsxlib, plugin):
"""Check for unsupported configuration that will block the migration """Check for unsupported configuration that will block the migration
""" """
@ -1464,7 +1450,8 @@ def t_2_p_migration(resource, event, trigger, **kwargs):
"in the configuration") "in the configuration")
return return
nsxlib = utils.get_connected_nsxlib(verbose=verbose) nsxlib = utils.get_connected_nsxlib(
verbose=verbose, allow_overwrite_header=True)
nsxpolicy = p_utils.get_connected_nsxpolicy( nsxpolicy = p_utils.get_connected_nsxpolicy(
conf_path=cfg.CONF.nsx_v3) conf_path=cfg.CONF.nsx_v3)
# Also create a policy manager with admin user to manipulate admin-defined # Also create a policy manager with admin user to manipulate admin-defined
@ -1476,6 +1463,9 @@ def t_2_p_migration(resource, event, trigger, **kwargs):
nsx_password=cfg.CONF.nsx_v3.nsx_api_password) nsx_password=cfg.CONF.nsx_v3.nsx_api_password)
with utils.NsxV3PluginWrapper(verbose=verbose) as plugin: with utils.NsxV3PluginWrapper(verbose=verbose) as plugin:
# Make sure FWaaS was initialized
plugin.init_fwaas_for_admin_utils()
if not pre_migration_checks(nsxlib, plugin): if not pre_migration_checks(nsxlib, plugin):
# Failed # Failed
LOG.error("T2P migration cannot run. Please fix the configuration " LOG.error("T2P migration cannot run. Please fix the configuration "

View File

@ -48,6 +48,7 @@ def get_nsxv3_client(nsx_username=None, nsx_password=None,
def get_connected_nsxlib(nsx_username=None, nsx_password=None, def get_connected_nsxlib(nsx_username=None, nsx_password=None,
use_basic_auth=False, use_basic_auth=False,
plugin_conf=None, plugin_conf=None,
allow_overwrite_header=False,
verbose=False): verbose=False):
global _NSXLIB global _NSXLIB
@ -60,12 +61,14 @@ def get_connected_nsxlib(nsx_username=None, nsx_password=None,
if not verbose: if not verbose:
# Return logs to normal # Return logs to normal
logging.disable(logging.NOTSET) logging.disable(logging.NOTSET)
return v3_utils.get_nsxlib_wrapper(nsx_username, return v3_utils.get_nsxlib_wrapper(
nsx_password, nsx_username, nsx_password, use_basic_auth,
use_basic_auth, plugin_conf=plugin_conf,
plugin_conf) allow_overwrite_header=allow_overwrite_header)
if _NSXLIB is None: if _NSXLIB is None:
_NSXLIB = v3_utils.get_nsxlib_wrapper(plugin_conf=plugin_conf) _NSXLIB = v3_utils.get_nsxlib_wrapper(
plugin_conf=plugin_conf,
allow_overwrite_header=allow_overwrite_header)
if not verbose: if not verbose:
# Return logs to normal # Return logs to normal