Browse Source

T2P migration

This patch will allow moving neutron from using the nsx_v3 plugin to the nsx_p plugin.
This includes:
- admin utility to move all resources to the policy api:
  nsxadmin -r nsx-migrate-t2p -o import (--verbose)
  This utility will:
  -- Migrate all neutron used & created resource using the nsx migration api
  -- roll back all resources in case it failed
  -- post migration fix some of the policy resources to better match the expectation
     of the policy plugin
- admin utility that will cleanup left overs in the nsx_v3 db:
  nsxadmin -r nsx-migrate-t2p -o clean-all
  (can be used, but everything should work without calling it as well)
- Some minor changes to the policy plugin and drivers to allow it to handle migrated resource
  which are a bit different than those created with the policy plugin
  -- Delete DHCP server config once a migrated network is deleted
  -- Update LB L7 rules by their name suffix as their full display name is unknown

Change-Id: Ic17e0de1f4b2a2d95afa61ce33ffb0bc9e667b89
changes/48/737448/1
Adit Sarfaty 8 months ago
committed by asarfaty
parent
commit
b18ff51df6
15 changed files with 1605 additions and 33 deletions
  1. +15
    -0
      doc/source/admin_util.rst
  2. +1
    -0
      lower-constraints.txt
  3. +1
    -0
      requirements.txt
  4. +5
    -0
      vmware_nsx/common/utils.py
  5. +8
    -2
      vmware_nsx/plugins/nsx_p/plugin.py
  6. +27
    -17
      vmware_nsx/plugins/nsx_v3/utils.py
  7. +5
    -3
      vmware_nsx/services/lbaas/nsx_p/implementation/l7policy_mgr.py
  8. +2
    -0
      vmware_nsx/services/lbaas/nsx_p/implementation/l7rule_mgr.py
  9. +1
    -0
      vmware_nsx/shell/admin/plugins/common/constants.py
  10. +31
    -0
      vmware_nsx/shell/admin/plugins/nsxp/migration.py
  11. +26
    -6
      vmware_nsx/shell/admin/plugins/nsxp/resources/utils.py
  12. +1447
    -0
      vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py
  13. +28
    -3
      vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py
  14. +6
    -1
      vmware_nsx/shell/resources.py
  15. +2
    -1
      vmware_nsx/tests/unit/services/lbaas/test_nsxp_driver.py

+ 15
- 0
doc/source/admin_util.rst View File

@@ -604,6 +604,17 @@ Config

nsxadmin -r config -o validate

T2P migration
~~~~~~~~~~~~~

- Migrate NSX resources and neutron DB from NSX-T (MP) to Policy::

nsxadmin -r nsx-migrate-t2p -o import (--verbose)

- Delete DB tables related to the MP plugin after migration::

nsxadmin -r nsx-migrate-t2p -o clean-all

NSXtvd Plugin
-------------

@@ -655,6 +666,10 @@ NSX Policy Plugin
- Update tags on a loadbalancer service
nsxadmin -r lb-services -o nsx-update-tags

- Delete DB tables related to the MP plugin after migration from MP plugin to policy::

nsxadmin -r nsx-migrate-t2p -o clean-all


Client Certificate
~~~~~~~~~~~~~~~~~~


+ 1
- 0
lower-constraints.txt View File

@@ -30,6 +30,7 @@ oslo.utils==3.33.0
oslo.vmware==2.17.0
oslotest==3.2.0
osc-lib==1.14.0
paramiko==2.4.0
pbr==4.0.0
pika-pool==0.1.3
pika==0.10.0


+ 1
- 0
requirements.txt View File

@@ -26,6 +26,7 @@ oslo.serialization>=2.28.1 # Apache-2.0
oslo.service>=1.31.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
oslo.vmware>=2.17.0 # Apache-2.0
paramiko>=2.4.0 # LGPLv2.1+
PrettyTable<0.8,>=0.7.2 # BSD
tooz>=1.58.0 # Apache-2.0
decorator>=4.3.0 # BSD


+ 5
- 0
vmware_nsx/common/utils.py View File

@@ -105,6 +105,11 @@ def is_nsx_version_3_0_0(nsx_version):
version.LooseVersion(v3_const.NSX_VERSION_3_0_0))


def is_nsx_version_3_1_0(nsx_version):
return (version.LooseVersion(nsx_version) >=
version.LooseVersion(v3_const.NSX_VERSION_3_1_0))


def is_nsxv_version_6_2(nsx_version):
return (version.LooseVersion(nsx_version) >=
version.LooseVersion('6.2'))


+ 8
- 2
vmware_nsx/plugins/nsx_p/plugin.py View File

@@ -834,13 +834,19 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
# MP MD proxy when this network is created.
# If not - the port will not be found, and it is ok.
# Note(asarfaty): In the future this code can be removed.
if not is_external_net and cfg.CONF.nsx_p.allow_passthrough:
# TODO(asarfaty): For migrated networks when the DB was not cleaned up
# This may actually delete a port the policy now control
if (not is_external_net and not is_nsx_net and
cfg.CONF.nsx_p.allow_passthrough):
self._delete_nsx_port_by_network(network_id)

# Delete the network segment from the backend
if not is_external_net and not is_nsx_net:
try:
self.nsxpolicy.segment.delete(network_id)
# In case of migrated network, a dhcp server config with
# the same id should also be deleted
self.nsxpolicy.dhcp_server_config.delete(network_id)
except nsx_lib_exc.ResourceNotFound:
# If the resource was not found on the backend do not worry
# about it. The conditions has already been logged, so there
@@ -3934,7 +3940,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
rule_entry = self._create_security_group_backend_rule(
context, sg_id, rule, secgroup_logging,
is_provider_sg=is_provider_sg,
create_related_resource=False)
create_related_resource=True)
backend_rules.append(rule_entry)

# Update the policy with all the rules.


+ 27
- 17
vmware_nsx/plugins/nsx_v3/utils.py View File

@@ -175,34 +175,44 @@ def get_nsxlib_wrapper(nsx_username=None, nsx_password=None, basic_auth=False,


def get_nsxpolicy_wrapper(nsx_username=None, nsx_password=None,
basic_auth=False):
#TODO(asarfaty) move to a different file? (under common_v3)
basic_auth=False, conf_path=None):
if not conf_path:
conf_path = cfg.CONF.nsx_p
client_cert_provider = None
if not basic_auth:
# if basic auth requested, dont use cert file even if provided
client_cert_provider = get_client_cert_provider(
conf_path=cfg.CONF.nsx_p)
conf_path=conf_path)

nsxlib_config = config.NsxLibConfig(
username=nsx_username or cfg.CONF.nsx_p.nsx_api_user,
password=nsx_password or cfg.CONF.nsx_p.nsx_api_password,
username=nsx_username or conf_path.nsx_api_user,
password=nsx_password or conf_path.nsx_api_password,
client_cert_provider=client_cert_provider,
retries=cfg.CONF.nsx_p.http_retries,
insecure=cfg.CONF.nsx_p.insecure,
ca_file=cfg.CONF.nsx_p.ca_file,
concurrent_connections=cfg.CONF.nsx_p.concurrent_connections,
http_timeout=cfg.CONF.nsx_p.http_timeout,
http_read_timeout=cfg.CONF.nsx_p.http_read_timeout,
conn_idle_timeout=cfg.CONF.nsx_p.conn_idle_timeout,
retries=conf_path.http_retries,
insecure=conf_path.insecure,
ca_file=conf_path.ca_file,
concurrent_connections=conf_path.concurrent_connections,
http_timeout=conf_path.http_timeout,
http_read_timeout=conf_path.http_read_timeout,
conn_idle_timeout=conf_path.conn_idle_timeout,
http_provider=None,
max_attempts=cfg.CONF.nsx_p.retries,
nsx_api_managers=cfg.CONF.nsx_p.nsx_api_managers,
max_attempts=conf_path.retries,
nsx_api_managers=conf_path.nsx_api_managers,
plugin_scope=OS_NEUTRON_ID_SCOPE,
plugin_tag=NSX_NEUTRON_PLUGIN,
plugin_ver=n_version.version_info.release_string(),
allow_passthrough=cfg.CONF.nsx_p.allow_passthrough,
realization_max_attempts=cfg.CONF.nsx_p.realization_max_attempts,
realization_wait_sec=cfg.CONF.nsx_p.realization_wait_sec)
dns_nameservers=conf_path.nameservers,
dns_domain=conf_path.dns_domain,
allow_passthrough=(conf_path.allow_passthrough
if hasattr(conf_path, 'allow_passthrough')
else False),
realization_max_attempts=(conf_path.realization_max_attempts
if hasattr(conf_path,
'realization_max_attempts')
else 50),
realization_wait_sec=(conf_path.realization_wait_sec
if hasattr(conf_path, 'realization_wait_sec')
else 1))
return policy.NsxPolicyLib(nsxlib_config)




+ 5
- 3
vmware_nsx/services/lbaas/nsx_p/implementation/l7policy_mgr.py View File

@@ -52,6 +52,7 @@ class EdgeL7PolicyManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
vs_client = self.core_plugin.nsxpolicy.load_balancer.virtual_server
policy_name = utils.get_name_and_uuid(old_policy['name'] or 'policy',
old_policy['id'])
short_name = utils.get_name_short_uuid(old_policy['id'])
rule_body = lb_utils.convert_l7policy_to_lb_rule(
self.core_plugin.nsxpolicy, new_policy)
try:
@@ -59,6 +60,7 @@ class EdgeL7PolicyManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
new_policy['listener_id'],
policy_name,
position=new_policy.get('position', 0) - 1,
compare_name_suffix=short_name,
**rule_body)

except Exception as e:
@@ -70,11 +72,11 @@ class EdgeL7PolicyManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):

def delete(self, context, policy, completor):
vs_client = self.core_plugin.nsxpolicy.load_balancer.virtual_server
policy_name = utils.get_name_and_uuid(policy['name'] or 'policy',
policy['id'])
policy_name = utils.get_name_short_uuid(policy['id'])
try:
vs_client.remove_lb_rule(policy['listener_id'],
policy_name)
policy_name,
check_name_suffix=True)
except nsxlib_exc.ResourceNotFound:
pass
except nsxlib_exc.ManagerError:


+ 2
- 0
vmware_nsx/services/lbaas/nsx_p/implementation/l7rule_mgr.py View File

@@ -29,6 +29,7 @@ class EdgeL7RuleManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
policy = rule['policy']
policy_name = utils.get_name_and_uuid(policy['name'] or 'policy',
policy['id'])
short_name = utils.get_name_short_uuid(policy['id'])
if delete:
lb_utils.remove_rule_from_policy(rule)
else:
@@ -39,6 +40,7 @@ class EdgeL7RuleManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
vs_client.update_lb_rule(policy['listener_id'],
policy_name,
position=policy.get('position', 0) - 1,
compare_name_suffix=short_name,
**rule_body)
except Exception as e:
with excutils.save_and_reraise_exception():


+ 1
- 0
vmware_nsx/shell/admin/plugins/common/constants.py View File

@@ -51,6 +51,7 @@ LB_ADVERTISEMENT = 'lb-advertisement'
RATE_LIMIT = 'rate-limit'
CLUSTER = 'cluster'
ORPHANED_FIREWALL_SECTIONS = 'orphaned-firewall-sections'
NSX_MIGRATE_T_P = 'nsx-migrate-t2p'

# NSXV only Resource Constants
EDGES = 'edges'


+ 31
- 0
vmware_nsx/shell/admin/plugins/nsxp/migration.py View File

@@ -0,0 +1,31 @@
# Copyright 2020 VMware, Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from neutron_lib.callbacks import registry

from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
from vmware_nsx.shell.admin.plugins.nsxv3.resources import migration
from vmware_nsx.shell import resources as shell


@admin_utils.output_header
def cleanup_db_mappings(resource, event, trigger, **kwargs):
"""Delete all entries from nsx-t mapping tables in DB"""
return migration.cleanup_db_mappings(resource, event, trigger, **kwargs)


registry.subscribe(cleanup_db_mappings,
constants.NSX_MIGRATE_T_P,
shell.Operations.CLEAN_ALL.value)

+ 26
- 6
vmware_nsx/shell/admin/plugins/nsxp/resources/utils.py View File

@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.

import logging
from oslo_config import cfg

from neutron.db import l3_dvr_db # noqa
@@ -19,7 +20,6 @@ from neutron import manager
from neutron_lib import context
from neutron_lib.plugins import constants as const
from neutron_lib.plugins import directory
from oslo_log import log as logging

from vmware_nsx.common import config
from vmware_nsx.plugins.nsx_p import plugin
@@ -41,16 +41,28 @@ def get_nsxp_client(nsx_username=None, nsx_password=None,


def get_connected_nsxpolicy(nsx_username=None, nsx_password=None,
use_basic_auth=False):
use_basic_auth=False, conf_path=None,
verbose=False):
global _NSXPOLICY

# for non-default agruments, initiate new lib
if not verbose:
# Suppress logs for nsxpolicy init
logging.disable(logging.INFO)

# for non-default arguments, initiate new lib
if nsx_username or use_basic_auth:
if not verbose:
# Return logs to normal
logging.disable(logging.NOTSET)
return v3_utils.get_nsxpolicy_wrapper(nsx_username,
nsx_password,
use_basic_auth)
use_basic_auth,
conf_path=conf_path)
if _NSXPOLICY is None:
_NSXPOLICY = v3_utils.get_nsxpolicy_wrapper()
_NSXPOLICY = v3_utils.get_nsxpolicy_wrapper(conf_path=conf_path)
if not verbose:
# Return logs to normal
logging.disable(logging.NOTSET)
return _NSXPOLICY


@@ -76,13 +88,21 @@ def get_realization_info(resource, *realization_args):


class NsxPolicyPluginWrapper(plugin.NsxPolicyPlugin):
def __init__(self):
def __init__(self, verbose=False):
if not verbose:
# Suppress logs for plugin init
logging.disable(logging.INFO)

# initialize the availability zones
config.register_nsxp_azs(cfg.CONF, cfg.CONF.nsx_p.availability_zones)
super(NsxPolicyPluginWrapper, self).__init__()
self.context = context.get_admin_context()
admin_utils._init_plugin_mock_quota()

if not verbose:
# Return logs to normal
logging.disable(logging.NOTSET)

def __enter__(self):
directory.add_plugin(const.CORE, self)
return self


+ 1447
- 0
vmware_nsx/shell/admin/plugins/nsxv3/resources/migration.py
File diff suppressed because it is too large
View File


+ 28
- 3
vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py View File

@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.

import logging

from oslo_config import cfg

@@ -46,17 +47,29 @@ def get_nsxv3_client(nsx_username=None, nsx_password=None,

def get_connected_nsxlib(nsx_username=None, nsx_password=None,
use_basic_auth=False,
plugin_conf=None):
plugin_conf=None,
verbose=False):
global _NSXLIB

# for non-default agruments, initiate new lib
if not verbose:
# Suppress logs for nsxlib init
logging.disable(logging.INFO)

# for non-default arguments, initiate new lib
if nsx_username or use_basic_auth:
if not verbose:
# Return logs to normal
logging.disable(logging.NOTSET)
return v3_utils.get_nsxlib_wrapper(nsx_username,
nsx_password,
use_basic_auth,
plugin_conf)
if _NSXLIB is None:
_NSXLIB = v3_utils.get_nsxlib_wrapper(plugin_conf=plugin_conf)

if not verbose:
# Return logs to normal
logging.disable(logging.NOTSET)
return _NSXLIB


@@ -117,13 +130,21 @@ class NeutronDbClient(db_base_plugin_v2.NeutronDbPluginV2):


class NsxV3PluginWrapper(plugin.NsxV3Plugin):
def __init__(self):
def __init__(self, verbose=False):
if not verbose:
# Suppress logs for plugin init
logging.disable(logging.INFO)

# initialize the availability zones
config.register_nsxv3_azs(cfg.CONF, cfg.CONF.nsx_v3.availability_zones)
super(NsxV3PluginWrapper, self).__init__()
self.context = context.get_admin_context()
admin_utils._init_plugin_mock_quota()

if not verbose:
# Return logs to normal
logging.disable(logging.NOTSET)

def __enter__(self):
directory.add_plugin(const.CORE, self)
return self
@@ -131,6 +152,10 @@ class NsxV3PluginWrapper(plugin.NsxV3Plugin):
def __exit__(self, exc_type, exc_value, traceback):
directory.add_plugin(const.CORE, None)

def _cleanup_duplicates(self, ns_group_id, section_id):
# Do not remove DFW sections during dummy plugin initialization
pass

def _init_fwaas_plugin(self, provider, callbacks_class, plugin_callbacks):
fwaas_plugin_class = manager.NeutronManager.load_class_for_provider(
'neutron.service_plugins', provider)


+ 6
- 1
vmware_nsx/shell/resources.py View File

@@ -158,7 +158,10 @@ nsxv3_resources = {
constants.LB_ADVERTISEMENT: Resource(constants.LB_ADVERTISEMENT,
[Operations.NSX_UPDATE.value]),
constants.CLUSTER: Resource(constants.CLUSTER,
[Operations.SHOW.value])
[Operations.SHOW.value]),
constants.NSX_MIGRATE_T_P: Resource(constants.NSX_MIGRATE_T_P,
[Operations.IMPORT.value,
Operations.CLEAN_ALL.value]),
}

# Add supported NSX-V resources in this dictionary
@@ -280,6 +283,8 @@ nsxp_resources = {
Operations.NSX_LIST.value]),
constants.SYSTEM: Resource(constants.SYSTEM,
[Operations.SET.value]),
constants.NSX_MIGRATE_T_P: Resource(constants.NSX_MIGRATE_T_P,
[Operations.CLEAN_ALL.value]),
}

nsxv3_resources_names = list(nsxv3_resources.keys())


+ 2
- 1
vmware_nsx/tests/unit/services/lbaas/test_nsxp_driver.py View File

@@ -1757,7 +1757,8 @@ class TestEdgeLbaasV2L7Policy(BaseTestEdgeLbaasV2):
) as mock_vs_remove_rule:
self.edge_driver.l7policy.delete(
self.context, self.l7policy_dict, self.completor)
mock_vs_remove_rule.assert_called_with(LB_VS_ID, mock.ANY)
mock_vs_remove_rule.assert_called_with(LB_VS_ID, mock.ANY,
check_name_suffix=True)
self.assertTrue(self.last_completor_called)
self.assertTrue(self.last_completor_succees)



Loading…
Cancel
Save