
1.Upgrade pylint to 2.4.4, add exclusions to the tests, and fix some lint errors in the code 2. Fix user creation with GRANT in MySQL 8.0(Ubuntu Focal) In Ubuntu Bionic (18.04) mysql 5.7 version used to create the user implicitly when using using the GRANT. Ubuntu Focal (20.04) has mysql 8.0 and with mysql 8.0 there is no implicit user creation with GRANT. We need to create the user first before using GRANT command. See also commit I97b0dcbb88c6ef7c22e3c55970211bed792bbd0d 3. Remove fwaas from the zuul.yaml 4. Remove DB migration test which is failing ue to FWaaS migration with py38 5. Fix cover tests python version in .tox 6. fix requirememnts Change-Id: I22654a5d5ccaad3185ae3365a90afba1ce870695
214 lines
9.2 KiB
Python
214 lines
9.2 KiB
Python
# Copyright 2019 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.
|
|
|
|
import sys
|
|
|
|
import netaddr
|
|
from oslo_log import log as logging
|
|
|
|
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
|
from neutron_lib.api.definitions import provider_net as pnet
|
|
from neutron_lib.api import validators
|
|
from neutron_lib.callbacks import registry
|
|
from neutron_lib import constants as nl_constants
|
|
from neutron_lib import context as n_context
|
|
|
|
from vmware_nsx.common import nsxv_constants
|
|
from vmware_nsx.common import utils as c_utils
|
|
from vmware_nsx.services.lbaas.nsx_v3.implementation import lb_utils
|
|
from vmware_nsx.services.lbaas.octavia import constants as oct_const
|
|
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.nsxv.resources import utils
|
|
from vmware_nsx.shell import resources as shell
|
|
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
@admin_utils.output_header
|
|
def validate_config_for_migration(resource, event, trigger, **kwargs):
|
|
"""Validate the nsxv configuration before migration to nsx-t"""
|
|
|
|
transit_networks = ["100.64.0.0/16"]
|
|
if kwargs.get('property'):
|
|
# input validation
|
|
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
|
|
transit_network = properties.get('transit-network')
|
|
if transit_network:
|
|
transit_networks = [transit_network]
|
|
|
|
# Max number of allowed address pairs (allowing 3 for fixed ips)
|
|
num_allowed_addr_pairs = nsxlib_consts.NUM_ALLOWED_IP_ADDRESSES - 3
|
|
|
|
admin_context = n_context.get_admin_context()
|
|
n_errors = 0
|
|
|
|
with utils.NsxVPluginWrapper() as plugin:
|
|
# Ports validations:
|
|
ports = plugin.get_ports(admin_context)
|
|
for port in ports:
|
|
net_id = port['network_id']
|
|
# Too many address pairs in a port
|
|
address_pairs = port.get(addr_apidef.ADDRESS_PAIRS)
|
|
if len(address_pairs) > num_allowed_addr_pairs:
|
|
n_errors = n_errors + 1
|
|
LOG.error("%s allowed address pairs for port %s. Only %s are "
|
|
"allowed.",
|
|
len(address_pairs), port['id'],
|
|
num_allowed_addr_pairs)
|
|
|
|
# Compute port on external network
|
|
if (port.get('device_owner', '').startswith(
|
|
nl_constants.DEVICE_OWNER_COMPUTE_PREFIX) and
|
|
plugin._network_is_external(admin_context, net_id)):
|
|
n_errors = n_errors + 1
|
|
LOG.error("Compute port %s on external network %s is not "
|
|
"allowed.", port['id'], net_id)
|
|
|
|
# Networks & subnets validations:
|
|
networks = plugin.get_networks(admin_context)
|
|
for net in networks:
|
|
# skip internal networks
|
|
if net['project_id'] == nsxv_constants.INTERNAL_TENANT_ID:
|
|
continue
|
|
|
|
# VXLAN or portgroup provider networks
|
|
net_type = net.get(pnet.NETWORK_TYPE)
|
|
if (net_type == c_utils.NsxVNetworkTypes.VXLAN or
|
|
net_type == c_utils.NsxVNetworkTypes.PORTGROUP):
|
|
n_errors = n_errors + 1
|
|
LOG.error("Network %s of type %s is not supported.",
|
|
net['id'], net_type)
|
|
|
|
subnets = plugin._get_subnets_by_network(admin_context, net['id'])
|
|
n_dhcp_subnets = 0
|
|
|
|
# Multiple DHCP subnets per network
|
|
for subnet in subnets:
|
|
if subnet['enable_dhcp']:
|
|
n_dhcp_subnets = n_dhcp_subnets + 1
|
|
if n_dhcp_subnets > 1:
|
|
n_errors = n_errors + 1
|
|
LOG.error("Network %s has %s dhcp subnets. Only 1 is allowed.",
|
|
net['id'], n_dhcp_subnets)
|
|
|
|
# Subnets overlapping with the transit network
|
|
for subnet in subnets:
|
|
# get the subnet IPs
|
|
if ('allocation_pools' in subnet and
|
|
validators.is_attr_set(subnet['allocation_pools'])):
|
|
# use the pools instead of the cidr
|
|
subnet_networks = [
|
|
netaddr.IPRange(pool.get('start'), pool.get('end'))
|
|
for pool in subnet.get('allocation_pools')]
|
|
else:
|
|
cidr = subnet.get('cidr')
|
|
if not validators.is_attr_set(cidr):
|
|
return
|
|
subnet_networks = [netaddr.IPNetwork(subnet['cidr'])]
|
|
|
|
for subnet_net in subnet_networks:
|
|
if (netaddr.IPSet(subnet_net) &
|
|
netaddr.IPSet(transit_networks)):
|
|
n_errors = n_errors + 1
|
|
LOG.error("Subnet %s overlaps with the transit "
|
|
"network ips: %s.",
|
|
subnet['id'], transit_networks)
|
|
|
|
# Network attached to multiple routers
|
|
intf_ports = plugin._get_network_interface_ports(
|
|
admin_context, net['id'])
|
|
if len(intf_ports) > 1:
|
|
n_errors = n_errors + 1
|
|
LOG.error("Network %s has interfaces on multiple routers. "
|
|
"Only 1 is allowed.", net['id'])
|
|
|
|
# Routers validations:
|
|
routers = plugin.get_routers(admin_context)
|
|
for router in routers:
|
|
# Interface subnets overlap with the GW subnet
|
|
gw_subnets = plugin._find_router_gw_subnets(admin_context, router)
|
|
gw_cidrs = [subnet['cidr'] for subnet in gw_subnets]
|
|
gw_ip_set = netaddr.IPSet(gw_cidrs)
|
|
|
|
if_cidrs = plugin._find_router_subnets_cidrs(
|
|
admin_context, router['id'])
|
|
if_ip_set = netaddr.IPSet(if_cidrs)
|
|
|
|
if gw_ip_set & if_ip_set:
|
|
n_errors = n_errors + 1
|
|
LOG.error("Interface network of router %s cannot overlap with "
|
|
"router GW network", router['id'])
|
|
|
|
# TODO(asarfaty): missing validations:
|
|
# - Vlan provider network with the same VLAN tag as the uplink
|
|
# profile tag used in the relevant transport node
|
|
# (cannot check this without access to the T manager)
|
|
|
|
# Octavia loadbalancers validation:
|
|
filters = {'device_owner': [nl_constants.DEVICE_OWNER_LOADBALANCERV2,
|
|
oct_const.DEVICE_OWNER_OCTAVIA]}
|
|
lb_ports = plugin.get_ports(admin_context, filters=filters)
|
|
lb_routers = []
|
|
for port in lb_ports:
|
|
fixed_ips = port.get('fixed_ips', [])
|
|
if fixed_ips:
|
|
subnet_id = fixed_ips[0]['subnet_id']
|
|
network = lb_utils.get_network_from_subnet(
|
|
admin_context, plugin, subnet_id)
|
|
router_id = lb_utils.get_router_from_network(
|
|
admin_context, plugin, subnet_id)
|
|
# Loadbalancer vip subnet must be connected to a router or
|
|
# belong to an external network
|
|
if (not router_id and network and
|
|
not network.get('router:external')):
|
|
n_errors = n_errors + 1
|
|
LOG.error("Loadbalancer %s subnet %s is not external "
|
|
"nor connected to a router.",
|
|
port.get('device_id'), subnet_id)
|
|
# Multiple loadbalancers on the same router cannot be supported
|
|
if router_id in lb_routers:
|
|
n_errors = n_errors + 1
|
|
LOG.error("Router %s has multiple loadbalancers which is "
|
|
"not supported.", router_id)
|
|
else:
|
|
lb_routers.append(router_id)
|
|
|
|
# TODO(asarfaty): Multiple listeners on the same pool is not
|
|
# supported, but currently the admin utility has no access to this
|
|
# information from octavia
|
|
|
|
# TODO(asarfaty): Member on external subnet must have fip as ip,
|
|
# but currently the admin utility has no access to this information
|
|
# from octavia
|
|
|
|
# General validations:
|
|
# TODO(asarfaty): multiple transport zones (migrator limitation)?
|
|
|
|
if n_errors > 0:
|
|
plural = n_errors > 1
|
|
LOG.error("The NSX-V plugin configuration is not ready to be "
|
|
"migrated to NSX-T. %s error%s found.", n_errors,
|
|
's were' if plural else ' was')
|
|
sys.exit(n_errors)
|
|
|
|
LOG.info("The NSX-V plugin configuration is ready to be migrated to "
|
|
"NSX-T.")
|
|
|
|
|
|
registry.subscribe(validate_config_for_migration,
|
|
constants.NSX_MIGRATE_V_T,
|
|
shell.Operations.VALIDATE.value)
|