asarfaty 50afa71853 Fix broken Victoria branch
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
2020-09-21 15:31:18 +02:00

195 lines
7.9 KiB
Python

# Copyright 2016 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 xml.etree.ElementTree as et
import netaddr
from neutron.ipam import exceptions as ipam_exc
from neutron.ipam import requests as ipam_req
from neutron_lib.api.definitions import external_net as extnet_apidef
from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef
from neutron_lib.api.definitions import provider_net as pnet
from neutron_lib.api import validators
from oslo_log import log as logging
from vmware_nsx._i18n import _
from vmware_nsx.plugins.nsx_v.vshield.common import constants
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vc_exc
from vmware_nsx.services.ipam.common import driver as common
LOG = logging.getLogger(__name__)
class NsxvIpamDriver(common.NsxAbstractIpamDriver, common.NsxIpamBase):
"""IPAM Driver For NSX-V external & provider networks."""
def _is_ext_or_provider_net(self, subnet_request):
"""Return True if the network of the request is external or
provider network
"""
network_id = subnet_request.network_id
if network_id:
network = self._fetch_network(self._context, network_id)
if network.get(extnet_apidef.EXTERNAL):
# external network
return True
if (validators.is_attr_set(network.get(mpnet_apidef.SEGMENTS)) or
validators.is_attr_set(network.get(pnet.NETWORK_TYPE))):
# provider network
return True
return False
def _is_ipv6_subnet(self, subnet_request):
"""Return True if the network of the request is an ipv6 network"""
if isinstance(subnet_request, ipam_req.SpecificSubnetRequest):
return subnet_request.subnet_cidr.version == 6
else:
if subnet_request.allocation_pools:
for pool in subnet_request.allocation_pools:
if pool.version == 6:
return True
return False
def _is_supported_net(self, subnet_request):
"""This driver supports only ipv4 external/provider networks"""
return (self._is_ext_or_provider_net(subnet_request) and
not self._is_ipv6_subnet(subnet_request))
@property
def _subnet_class(self):
return NsxvIpamSubnet
def allocate_backend_pool(self, subnet_request):
"""Create a pool on the NSX backend and return its ID"""
if subnet_request.allocation_pools:
ranges = [
{'ipRangeDto':
{'startAddress': netaddr.IPAddress(pool.first),
'endAddress': netaddr.IPAddress(pool.last)}}
for pool in subnet_request.allocation_pools]
else:
ranges = []
request = {'ipamAddressPool':
# max name length on backend is 255, so there is no problem here
{'name': 'subnet_' + subnet_request.subnet_id,
'prefixLength': subnet_request.prefixlen,
'gateway': subnet_request.gateway_ip,
'ipRanges': ranges}}
try:
response = self._vcns.create_ipam_ip_pool(request)
nsx_pool_id = response[1]
except vc_exc.VcnsApiException as e:
msg = _('Failed to create subnet IPAM: %s') % e
raise ipam_exc.IpamValueInvalid(message=msg)
return nsx_pool_id
def delete_backend_pool(self, nsx_pool_id):
try:
self._vcns.delete_ipam_ip_pool(nsx_pool_id)
except vc_exc.VcnsApiException as e:
LOG.error("Failed to delete IPAM from backend: %s", e)
# Continue anyway, since this subnet was already removed
def update_backend_pool(self, subnet_request):
# The NSX-v backend does not support changing the ip pool cidr
# or gateway.
# If this function is called - there is no need to update the backend
pass
class NsxvIpamSubnet(common.NsxAbstractIpamSubnet, common.NsxIpamBase):
"""Manage IP addresses for the NSX-V IPAM driver."""
def _get_vcns_error_code(self, e):
"""Get the error code out of VcnsApiException"""
try:
desc = et.fromstring(e.response)
return int(desc.find('errorCode').text)
except Exception:
LOG.error('IPAM pool: Error code not present. %s',
e.response)
def backend_allocate(self, address_request):
try:
# allocate a specific IP
if isinstance(address_request, ipam_req.SpecificAddressRequest):
# This handles both specific and automatic address requests
ip_address = str(address_request.address)
self._vcns.allocate_ipam_ip_from_pool(self._nsx_pool_id,
ip_addr=ip_address)
else:
# Allocate any free IP
response = self._vcns.allocate_ipam_ip_from_pool(
self._nsx_pool_id)[1]
# get the ip from the response
root = et.fromstring(response)
ip_address = root.find('ipAddress').text
except vc_exc.VcnsApiException as e:
# handle backend failures
error_code = self._get_vcns_error_code(e)
if error_code == constants.NSX_ERROR_IPAM_ALLOCATE_IP_USED:
# This IP is already in use
raise ipam_exc.IpAddressAlreadyAllocated(
ip=ip_address, subnet_id=self._subnet_id)
if error_code == constants.NSX_ERROR_IPAM_ALLOCATE_ALL_USED:
# No more IP addresses available on the pool
raise ipam_exc.IpAddressGenerationFailure(
subnet_id=self._subnet_id)
raise ipam_exc.IPAllocationFailed()
return ip_address
def backend_deallocate(self, address):
try:
self._vcns.release_ipam_ip_to_pool(self._nsx_pool_id, address)
except vc_exc.VcnsApiException as e:
LOG.error("NSX IPAM failed to free ip %(ip)s of subnet %(id)s:"
" %(e)s",
{'e': e.response,
'ip': address,
'id': self._subnet_id})
raise ipam_exc.IpAddressAllocationNotFound(
subnet_id=self._subnet_id,
ip_address=address)
def _get_pool_cidr(self, pool):
# rebuild the cidr from the pool range & prefix using the first
# range in the pool, because they all should belong to the same cidr
cidr = '%s/%s' % (pool['ipRanges'][0]['startAddress'],
pool['prefixLength'])
# convert to a proper cidr
cidr = netaddr.IPNetwork(cidr).cidr
return str(cidr)
def get_details(self):
"""Return subnet data as a SpecificSubnetRequest"""
# get the pool from the backend
pool_details = self._vcns.get_ipam_ip_pool(self._nsx_pool_id)[1]
gateway_ip = pool_details['gateway']
# rebuild the cidr from the range & prefix
cidr = self._get_pool_cidr(pool_details)
pools = []
for ip_range in pool_details['ipRanges']:
pools.append(netaddr.IPRange(ip_range['startAddress'],
ip_range['endAddress']))
return ipam_req.SpecificSubnetRequest(
self._tenant_id, self._subnet_id,
cidr, gateway_ip=gateway_ip, allocation_pools=pools)