MP2P migration: misc fixes

- Add elapsed time logging
- Skip irrelevant retries of nsx requests
- retrive only tier0/tier1 logical routers whenever relevant
- Update max number of tier1 logical ports to migrate

Change-Id: If6878e20701312daf66be1a035db4614013c7e47
This commit is contained in:
asarfaty 2020-07-14 13:16:23 +02:00
parent 61611794f9
commit 0f42f01267
4 changed files with 78 additions and 30 deletions

View File

@ -133,7 +133,8 @@ def get_client_cert_provider(conf_path=cfg.CONF.nsx_v3):
def get_nsxlib_wrapper(nsx_username=None, nsx_password=None, basic_auth=False, def get_nsxlib_wrapper(nsx_username=None, nsx_password=None, basic_auth=False,
plugin_conf=None, allow_overwrite_header=False): plugin_conf=None, allow_overwrite_header=False,
retriable_exceptions=None):
if not plugin_conf: if not plugin_conf:
plugin_conf = cfg.CONF.nsx_v3 plugin_conf = cfg.CONF.nsx_v3
@ -142,6 +143,9 @@ def get_nsxlib_wrapper(nsx_username=None, nsx_password=None, basic_auth=False,
# if basic auth requested, dont use cert file even if provided # if basic auth requested, dont use cert file even if provided
client_cert_provider = get_client_cert_provider(conf_path=plugin_conf) client_cert_provider = get_client_cert_provider(conf_path=plugin_conf)
exception_config = config.ExceptionConfig()
if retriable_exceptions:
exception_config.retriables = retriable_exceptions
nsxlib_config = config.NsxLibConfig( nsxlib_config = config.NsxLibConfig(
username=nsx_username or plugin_conf.nsx_api_user, username=nsx_username or plugin_conf.nsx_api_user,
password=nsx_password or plugin_conf.nsx_api_password, password=nsx_password or plugin_conf.nsx_api_password,
@ -161,12 +165,14 @@ def get_nsxlib_wrapper(nsx_username=None, nsx_password=None, basic_auth=False,
plugin_ver=n_version.version_info.release_string(), plugin_ver=n_version.version_info.release_string(),
dns_nameservers=cfg.CONF.nsx_v3.nameservers, dns_nameservers=cfg.CONF.nsx_v3.nameservers,
dns_domain=cfg.CONF.nsx_v3.dns_domain, dns_domain=cfg.CONF.nsx_v3.dns_domain,
allow_overwrite_header=allow_overwrite_header) allow_overwrite_header=allow_overwrite_header,
exception_config=exception_config)
return v3.NsxLib(nsxlib_config) return v3.NsxLib(nsxlib_config)
def get_nsxpolicy_wrapper(nsx_username=None, nsx_password=None, def get_nsxpolicy_wrapper(nsx_username=None, nsx_password=None,
basic_auth=False, conf_path=None): basic_auth=False, conf_path=None,
retriable_exceptions=None):
if not conf_path: if not conf_path:
conf_path = cfg.CONF.nsx_p conf_path = cfg.CONF.nsx_p
client_cert_provider = None client_cert_provider = None
@ -175,6 +181,10 @@ def get_nsxpolicy_wrapper(nsx_username=None, nsx_password=None,
client_cert_provider = get_client_cert_provider( client_cert_provider = get_client_cert_provider(
conf_path=conf_path) conf_path=conf_path)
exception_config = config.ExceptionConfig()
if retriable_exceptions:
exception_config.retriables = retriable_exceptions
nsxlib_config = config.NsxLibConfig( nsxlib_config = config.NsxLibConfig(
username=nsx_username or conf_path.nsx_api_user, username=nsx_username or conf_path.nsx_api_user,
password=nsx_password or conf_path.nsx_api_password, password=nsx_password or conf_path.nsx_api_password,
@ -194,6 +204,7 @@ def get_nsxpolicy_wrapper(nsx_username=None, nsx_password=None,
plugin_ver=n_version.version_info.release_string(), plugin_ver=n_version.version_info.release_string(),
dns_nameservers=conf_path.nameservers, dns_nameservers=conf_path.nameservers,
dns_domain=conf_path.dns_domain, dns_domain=conf_path.dns_domain,
exception_config=exception_config,
allow_passthrough=(conf_path.allow_passthrough allow_passthrough=(conf_path.allow_passthrough
if hasattr(conf_path, 'allow_passthrough') if hasattr(conf_path, 'allow_passthrough')
else False), else False),

View File

@ -42,6 +42,7 @@ def get_nsxp_client(nsx_username=None, nsx_password=None,
def get_connected_nsxpolicy(nsx_username=None, nsx_password=None, def get_connected_nsxpolicy(nsx_username=None, nsx_password=None,
use_basic_auth=False, conf_path=None, use_basic_auth=False, conf_path=None,
retriable_exceptions=None,
verbose=False): verbose=False):
global _NSXPOLICY global _NSXPOLICY
@ -54,12 +55,14 @@ def get_connected_nsxpolicy(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_nsxpolicy_wrapper(nsx_username, return v3_utils.get_nsxpolicy_wrapper(
nsx_password, nsx_username, nsx_password, use_basic_auth,
use_basic_auth, conf_path=conf_path,
conf_path=conf_path) retriable_exceptions=retriable_exceptions)
if _NSXPOLICY is None: if _NSXPOLICY is None:
_NSXPOLICY = v3_utils.get_nsxpolicy_wrapper(conf_path=conf_path) _NSXPOLICY = v3_utils.get_nsxpolicy_wrapper(
conf_path=conf_path,
retriable_exceptions=retriable_exceptions)
if not verbose: if not verbose:
# Return logs to normal # Return logs to normal
logging.disable(logging.NOTSET) logging.disable(logging.NOTSET)

View File

@ -42,6 +42,7 @@ from vmware_nsx.shell import resources as shell
from vmware_nsxlib.v3 import core_resources as nsx_resources from vmware_nsxlib.v3 import core_resources as nsx_resources
from vmware_nsxlib.v3 import exceptions as nsxlib_exc from vmware_nsxlib.v3 import exceptions as nsxlib_exc
from vmware_nsxlib.v3 import load_balancer as nsxlib_lb from vmware_nsxlib.v3 import load_balancer as nsxlib_lb
from vmware_nsxlib.v3 import nsx_constants
from vmware_nsxlib.v3.policy import constants as policy_constants from vmware_nsxlib.v3.policy import constants as policy_constants
from vmware_nsxlib.v3.policy import core_resources as policy_resources from vmware_nsxlib.v3.policy import core_resources as policy_resources
from vmware_nsxlib.v3.policy import utils as policy_utils from vmware_nsxlib.v3.policy import utils as policy_utils
@ -62,8 +63,8 @@ STATUS_ALLOW_MIGRATION_REQ = set([
MIGRATE_LIMIT_NO_LIMIT = 0 MIGRATE_LIMIT_NO_LIMIT = 0
MIGRATE_LIMIT_TIER0 = 1 MIGRATE_LIMIT_TIER0 = 1
MIGRATE_LIMIT_TIER0_PORTS = 1000 MIGRATE_LIMIT_TIER0_PORTS = 1000
MIGRATE_LIMIT_TIER1 = 500 MIGRATE_LIMIT_TIER1 = 1000
MIGRATE_LIMIT_TIER1_PORTS = 5 MIGRATE_LIMIT_TIER1_PORTS = 1000
MIGRATE_LIMIT_NAT = 1500 MIGRATE_LIMIT_NAT = 1500
MIGRATE_LIMIT_DHCP_SERVER = 1500 MIGRATE_LIMIT_DHCP_SERVER = 1500
MIGRATE_LIMIT_MD_PROXY = 1500 MIGRATE_LIMIT_MD_PROXY = 1500
@ -87,6 +88,8 @@ ROLLBACK_DATA = []
EDGE_FW_SEQ = 1 EDGE_FW_SEQ = 1
DFW_SEQ = 1 DFW_SEQ = 1
SERVICE_UP_RETRIES = 30
def start_migration_process(nsxlib): def start_migration_process(nsxlib):
"""Notify the manager that the migration process is starting""" """Notify the manager that the migration process is starting"""
@ -140,27 +143,33 @@ def change_migration_service_status(start=True, nsxlib=None):
if start and nsxlib: if start and nsxlib:
LOG.info("Waiting for the service to be up...") LOG.info("Waiting for the service to be up...")
start_time = time.time()
@tenacity.retry(reraise=True, @tenacity.retry(reraise=True,
retry=tenacity.retry_if_exception_type(Exception), retry=tenacity.retry_if_exception_type(Exception),
wait=tenacity.wait_exponential(multiplier=0.5, max=2), wait=tenacity.wait_exponential(multiplier=0.5, max=2),
stop=tenacity.stop_after_attempt( stop=tenacity.stop_after_attempt(SERVICE_UP_RETRIES))
cfg.CONF.nsx_v3.retries))
def get_migration_status_with_retry(nsxlib): def get_migration_status_with_retry(nsxlib):
get_migration_status(nsxlib, silent=True) get_migration_status(nsxlib, silent=True)
try:
get_migration_status_with_retry(nsxlib) get_migration_status_with_retry(nsxlib)
LOG.info("The service is up") except Exception:
raise Exception("The migration service did not get up after %s "
"retries" % SERVICE_UP_RETRIES)
elapsed_time = time.time() - start_time
LOG.info("The service is up (waited %s seconds)", elapsed_time)
def ensure_migration_state_ready(nsxlib, with_abort=False): def ensure_migration_state_ready(nsxlib, with_abort=False):
try: try:
status = get_migration_status(nsxlib, silent=True) status = get_migration_status(nsxlib, silent=True)
except nsxlib_exc.CannotConnectToServer as e: except Exception as e:
LOG.debug("Failed to get migration status: %s", e)
if with_abort: if with_abort:
change_migration_service_status(start=True, nsxlib=nsxlib) change_migration_service_status(start=True, nsxlib=nsxlib)
return ensure_migration_state_ready(nsxlib) return ensure_migration_state_ready(nsxlib)
LOG.debug("Failed to get migration status: %s", e)
return False return False
if status["overall_migration_status"] not in STATUS_ALLOW_MIGRATION_REQ: if status["overall_migration_status"] not in STATUS_ALLOW_MIGRATION_REQ:
@ -220,11 +229,15 @@ def get_resource_migration_data(nsxlib_resource, neutron_id_tags,
printable_name=None, policy_resource_get=None, printable_name=None, policy_resource_get=None,
policy_id_callback=None, policy_id_callback=None,
metadata_callback=None, metadata_callback=None,
skip_policy_path_check=False): skip_policy_path_check=False,
nsxlib_list_args=None):
if not printable_name: if not printable_name:
printable_name = resource_type printable_name = resource_type
LOG.debug("Getting data for MP %s", printable_name) LOG.debug("Getting data for MP %s", printable_name)
if nsxlib_list_args:
resources = nsxlib_resource.list(**nsxlib_list_args)
else:
resources = nsxlib_resource.list() resources = nsxlib_resource.list()
if not isinstance(resources, list): if not isinstance(resources, list):
# the nsxlib resources list return inconsistent type of result # the nsxlib resources list return inconsistent type of result
@ -422,7 +435,8 @@ def migrate_tier0s(nsxlib, nsxpolicy, plugin):
entries = get_resource_migration_data( entries = get_resource_migration_data(
nsxlib.logical_router, None, nsxlib.logical_router, None,
'TIER0', resource_condition=cond, 'TIER0', resource_condition=cond,
policy_resource_get=nsxpolicy.tier0.get) policy_resource_get=nsxpolicy.tier0.get,
nsxlib_list_args={'router_type': nsx_constants.ROUTER_TYPE_TIER0})
migrate_resource(nsxlib, 'TIER0', entries, MIGRATE_LIMIT_TIER0, migrate_resource(nsxlib, 'TIER0', entries, MIGRATE_LIMIT_TIER0,
use_admin=True) use_admin=True)
migrated_tier0s = [entry['manager_id'] for entry in entries] migrated_tier0s = [entry['manager_id'] for entry in entries]
@ -664,7 +678,8 @@ def migrate_routers(nsxlib, nsxpolicy):
nsxlib.logical_router, nsxlib.logical_router,
['os-neutron-router-id'], ['os-neutron-router-id'],
'TIER1', 'TIER1',
policy_resource_get=nsxpolicy.tier1.get) policy_resource_get=nsxpolicy.tier1.get,
nsxlib_list_args={'router_type': nsx_constants.ROUTER_TYPE_TIER1})
migrate_resource(nsxlib, 'TIER1', entries, MIGRATE_LIMIT_TIER1) migrate_resource(nsxlib, 'TIER1', entries, MIGRATE_LIMIT_TIER1)
migrated_routers = [entry['manager_id'] for entry in entries] migrated_routers = [entry['manager_id'] for entry in entries]
return migrated_routers return migrated_routers
@ -736,13 +751,15 @@ def migrate_routers_config(nsxlib, nsxpolicy, plugin, migrated_routers):
policy_id_callback=get_policy_id, policy_id_callback=get_policy_id,
resource_condition=cond, resource_condition=cond,
metadata_callback=add_metadata, metadata_callback=add_metadata,
skip_policy_path_check=True) skip_policy_path_check=True,
nsxlib_list_args={'router_type': nsx_constants.ROUTER_TYPE_TIER1})
migrate_resource(nsxlib, 'TIER1_LOGICAL_ROUTER_PORT', entries, migrate_resource(nsxlib, 'TIER1_LOGICAL_ROUTER_PORT', entries,
MIGRATE_LIMIT_TIER1_PORTS) MIGRATE_LIMIT_TIER1_PORTS)
# Migrate NAT rules per neutron tier1 # Migrate NAT rules per neutron tier1
entries = [] entries = []
tier1s = nsxlib.logical_router.list()['results'] tier1s = nsxlib.logical_router.list(
router_type=nsx_constants.ROUTER_TYPE_TIER1)['results']
ctx = context.get_admin_context() ctx = context.get_admin_context()
for tier1 in tier1s: for tier1 in tier1s:
# skip routers that were not migrated in this script call # skip routers that were not migrated in this script call
@ -854,7 +871,8 @@ def migrate_tier0_config(nsxlib, nsxpolicy, tier0s):
'TIER0_LOGICAL_ROUTER_CONFIG', 'TIER0_LOGICAL_ROUTER_CONFIG',
policy_id_callback=get_policy_id, policy_id_callback=get_policy_id,
resource_condition=cond, resource_condition=cond,
skip_policy_path_check=True) skip_policy_path_check=True,
nsxlib_list_args={'router_type': nsx_constants.ROUTER_TYPE_TIER0})
migrate_resource(nsxlib, 'TIER0_LOGICAL_ROUTER_CONFIG', entries, migrate_resource(nsxlib, 'TIER0_LOGICAL_ROUTER_CONFIG', entries,
MIGRATE_LIMIT_TIER0, use_admin=True) MIGRATE_LIMIT_TIER0, use_admin=True)
@ -1089,8 +1107,7 @@ def migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin):
return False return False
# Initialize the migration process # Initialize the migration process
if not ensure_migration_state_ready( if not ensure_migration_state_ready(nsxlib, with_abort=True):
nsxlib, with_abort=True):
return False return False
try: try:
@ -1450,34 +1467,47 @@ def t_2_p_migration(resource, event, trigger, **kwargs):
"in the configuration") "in the configuration")
return return
nsxlib = utils.get_connected_nsxlib( retriables = [nsxlib_exc.APITransactionAborted,
verbose=verbose, allow_overwrite_header=True) nsxlib_exc.ServerBusy]
nsxlib = utils.get_connected_nsxlib(verbose=verbose,
allow_overwrite_header=True,
retriable_exceptions=retriables)
nsxpolicy = p_utils.get_connected_nsxpolicy( nsxpolicy = p_utils.get_connected_nsxpolicy(
conf_path=cfg.CONF.nsx_v3) conf_path=cfg.CONF.nsx_v3, retriable_exceptions=retriables)
# Also create a policy manager with admin user to manipulate admin-defined # Also create a policy manager with admin user to manipulate admin-defined
# resources which should not have neutron principal identity # resources which should not have neutron principal identity
nsxpolicy_admin = p_utils.get_connected_nsxpolicy( nsxpolicy_admin = p_utils.get_connected_nsxpolicy(
conf_path=cfg.CONF.nsx_v3, conf_path=cfg.CONF.nsx_v3,
use_basic_auth=True, use_basic_auth=True,
nsx_username=cfg.CONF.nsx_v3.nsx_api_user, nsx_username=cfg.CONF.nsx_v3.nsx_api_user,
nsx_password=cfg.CONF.nsx_v3.nsx_api_password) nsx_password=cfg.CONF.nsx_v3.nsx_api_password,
retriable_exceptions=retriables)
with utils.NsxV3PluginWrapper(verbose=verbose) as plugin: with utils.NsxV3PluginWrapper(verbose=verbose) as plugin:
# Make sure FWaaS was initialized # Make sure FWaaS was initialized
plugin.init_fwaas_for_admin_utils() plugin.init_fwaas_for_admin_utils()
start_time = time.time()
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 "
"and try again\n\n") "and try again\n\n")
return return
elapsed_time = time.time() - start_time
LOG.debug("Pre-migration took %s seconds", elapsed_time)
start_time = time.time()
if not migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin): if not migrate_t_resources_2_p(nsxlib, nsxpolicy, plugin):
# Failed # Failed
LOG.error("T2P migration failed. Aborting\n\n") LOG.error("T2P migration failed. Aborting\n\n")
return return
elapsed_time = time.time() - start_time
LOG.debug("Migration took %s seconds", elapsed_time)
start_time = time.time()
post_migration_actions(nsxlib, nsxpolicy, nsxpolicy_admin, plugin) post_migration_actions(nsxlib, nsxpolicy, nsxpolicy_admin, plugin)
elapsed_time = time.time() - start_time
LOG.debug("Post-migration took %s seconds", elapsed_time)
LOG.info("T2P migration completed successfully\n\n") LOG.info("T2P migration completed successfully\n\n")

View File

@ -49,6 +49,7 @@ 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, allow_overwrite_header=False,
retriable_exceptions=None,
verbose=False): verbose=False):
global _NSXLIB global _NSXLIB
@ -64,11 +65,14 @@ def get_connected_nsxlib(nsx_username=None, nsx_password=None,
return v3_utils.get_nsxlib_wrapper( return v3_utils.get_nsxlib_wrapper(
nsx_username, nsx_password, use_basic_auth, nsx_username, nsx_password, use_basic_auth,
plugin_conf=plugin_conf, plugin_conf=plugin_conf,
retriable_exceptions=retriable_exceptions,
allow_overwrite_header=allow_overwrite_header) allow_overwrite_header=allow_overwrite_header)
if _NSXLIB is None: if _NSXLIB is None:
_NSXLIB = v3_utils.get_nsxlib_wrapper( _NSXLIB = v3_utils.get_nsxlib_wrapper(
plugin_conf=plugin_conf, plugin_conf=plugin_conf,
allow_overwrite_header=allow_overwrite_header) allow_overwrite_header=allow_overwrite_header,
retriable_exceptions=retriable_exceptions)
if not verbose: if not verbose:
# Return logs to normal # Return logs to normal