Merge "NSX|V3: Support specific IP allocations in IPAM"

This commit is contained in:
Jenkins 2017-05-05 01:13:12 +00:00 committed by Gerrit Code Review
commit 36ca01f552
2 changed files with 35 additions and 100 deletions

View File

@ -163,16 +163,20 @@ class Nsxv3IpamSubnet(common.NsxAbstractIpamSubnet):
'ip': ip_address,
'id': self._subnet_id,
'code': e.error_code})
# Currently the backend does not support allocation of specific IPs
# When this support is added we should handle allocation errors.
if e.error_code == error.ERR_CODE_IPAM_POOL_EXHAUSTED:
# No more IP addresses available on the pool
raise ipam_exc.IpAddressGenerationFailure(
subnet_id=self._subnet_id)
if e.error_code == error.ERR_CODE_IPAM_SPECIFIC_IP:
# The NSX backend does not support allocation of specific IPs
# prior to version 2.0.
msg = (_("NSX-V3 IPAM driver does not support allocation of a "
"specific ip %s for port") % ip_address)
raise NotImplementedError(msg)
if e.error_code == error.ERR_CODE_IPAM_IP_ALLOCATED:
# This IP is already in use
raise ipam_exc.IpAddressAlreadyAllocated(
ip=ip_address, subnet_id=self._subnet_id)
if e.error_code == error.ERR_CODE_OBJECT_NOT_FOUND:
msg = (_("NSX-V3 IPAM failed to allocate: pool %s was not "
"found") % self._nsx_pool_id)
@ -190,15 +194,21 @@ class Nsxv3IpamSubnet(common.NsxAbstractIpamSubnet):
raise ipam_exc.IPAllocationFailed()
return ip_address
def backend_deallocate(self, address):
def backend_deallocate(self, ip_address):
# If this is the subnet gateway IP - no need to allocate it
subnet = self.get_details()
if str(subnet.gateway_ip) == ip_address:
LOG.info("Skip deallocation of gateway-ip for pool %s",
self._nsx_pool_id)
return
try:
self.nsxlib_ipam.release(self._nsx_pool_id, ip_addr=address)
self.nsxlib_ipam.release(self._nsx_pool_id, ip_address)
except nsx_lib_exc.ManagerError as e:
# fail silently
LOG.error("NSX IPAM failed to free ip %(ip)s of subnet "
"%(id)s: %(e)s; code %(code)s",
{'e': e,
'ip': address,
'ip': ip_address,
'id': self._subnet_id,
'code': e.error_code})
@ -225,7 +235,6 @@ class Nsxv3IpamSubnet(common.NsxAbstractIpamSubnet):
for ip_range in subnet.get('allocation_ranges', []):
pools.append(netaddr.IPRange(ip_range.get('start'),
ip_range.get('end')))
return ipam_req.SpecificSubnetRequest(
self._tenant_id, self._subnet_id,
cidr, gateway_ip=gateway_ip, allocation_pools=pools)

View File

@ -63,14 +63,18 @@ class MockIPPools(object):
return self.nsx_pools[pool_id]['pool']
def _allocate_ip(*args, **kwargs):
#TODO(asarfaty): add support for specific ip allocation
if kwargs.get('ip_addr'):
raise nsx_lib_exc.ManagerError(
manager='dummy', operation='allocate',
details='allocating specific IP is not supported',
error_code=error.ERR_CODE_IPAM_SPECIFIC_IP)
nsx_pool = self.nsx_pools[args[0]]
if kwargs.get('ip_addr'):
ip_addr = netaddr.IPAddress(kwargs['ip_addr'])
# verify that this ip was not yet allocated
if ip_addr in nsx_pool['allocated']:
raise nsx_lib_exc.ManagerError(
manager='dummy', operation='allocate',
details='IP already allocated',
error_code=error.ERR_CODE_IPAM_IP_ALLOCATED)
# skip ip validation for this mock.
nsx_pool['allocated'].append(ip_addr)
return {'allocation_id': str(ip_addr)}
# get an unused ip from the pool
ranges = nsx_pool['pool']['subnets'][0]['allocation_ranges']
for ip_range in ranges:
@ -85,6 +89,11 @@ class MockIPPools(object):
details='All IPs in the pool are allocated',
error_code=error.ERR_CODE_IPAM_POOL_EXHAUSTED)
def _release_ip(*args, **kwargs):
nsx_pool = self.nsx_pools[args[0]]
ip_addr = netaddr.IPAddress(args[1])
nsx_pool['allocated'].remove(ip_addr)
mock.patch(
"vmware_nsxlib.v3.resources.IpPool.get",
side_effect=_get_pool).start()
@ -101,7 +110,8 @@ class MockIPPools(object):
"vmware_nsxlib.v3.resources.IpPool.allocate",
side_effect=_allocate_ip).start()
mock.patch(
"vmware_nsxlib.v3.resources.IpPool.release").start()
"vmware_nsxlib.v3.resources.IpPool.release",
side_effect=_release_ip).start()
class TestNsxv3IpamSubnets(test_plugin.TestSubnetsV2, MockIPPools):
@ -113,35 +123,11 @@ class TestNsxv3IpamSubnets(test_plugin.TestSubnetsV2, MockIPPools):
super(TestNsxv3IpamSubnets, self).setUp()
self.patch_nsxlib_ipam()
def test_update_subnet_gw_ip_in_use_by_router_returns_409(self):
self.skipTest('Allocating a specific IP is not supported')
def test_subnet_with_allocation_range(self):
self.skipTest('Allocating a specific IP is not supported')
def test_delete_subnet_ipv6_slaac_port_exists(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_subnet_ipv6_slaac_with_port_on_network(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_subnet_ipv6_slaac_with_dhcp_port_on_network(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_subnet_dhcpv6_stateless_with_port_on_network(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_subnet_ipv6_slaac_with_port_not_found(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_subnet_ipv6_slaac_with_db_reference_error(self):
self.skipTest('Allocating a specific IP is not supported')
def test_subnet_update_ipv4_and_ipv6_pd_slaac_subnets(self):
self.skipTest('Allocating a specific IP is not supported')
self.skipTest('Update ipam subnet is not supported')
def test_subnet_update_ipv4_and_ipv6_pd_v6stateless_subnets(self):
self.skipTest('Allocating a specific IP is not supported')
self.skipTest('Update ipam subnet is not supported')
class TestNsxv3IpamPorts(test_plugin.TestPortsV2, MockIPPools):
@ -153,66 +139,6 @@ class TestNsxv3IpamPorts(test_plugin.TestPortsV2, MockIPPools):
super(TestNsxv3IpamPorts, self).setUp()
self.patch_nsxlib_ipam()
def test_update_port_mac_v6_slaac(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_port_with_multiple_ipv4_and_ipv6_subnets(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_port_with_ipv6_slaac_subnet_in_fixed_ips(self):
self.skipTest('Allocating a specific IP is not supported')
def test_update_port_with_new_ipv6_slaac_subnet_in_fixed_ips(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_port_with_ipv6_pd_subnet_in_fixed_ips(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_port_anticipating_allocation(self):
self.skipTest('Allocating a specific IP is not supported')
def test_update_port_with_ipv6_slaac_subnet_in_fixed_ips(self):
self.skipTest('Allocating a specific IP is not supported')
def test_update_port_mac_ip(self):
self.skipTest('Allocating a specific IP is not supported')
def test_update_port_update_ips(self):
self.skipTest('Allocating a specific IP is not supported')
def test_update_port_excluding_ipv6_slaac_subnet_from_fixed_ips(self):
self.skipTest('Allocating a specific IP is not supported')
def test_update_port_update_ip(self):
self.skipTest('Allocating a specific IP is not supported')
def test_requested_subnet_id_v6_slaac(self):
self.skipTest('Allocating a specific IP is not supported')
def test_update_port_invalid_fixed_ip_address_v6_slaac(self):
self.skipTest('Allocating a specific IP is not supported')
def test_update_dhcp_port_with_exceeding_fixed_ips(self):
self.skipTest('Allocating a specific IP is not supported')
def test_requested_subnet_id_v4_and_v6_slaac(self):
self.skipTest('Allocating a specific IP is not supported')
def test_requested_ips_only(self):
self.skipTest('Allocating a specific IP is not supported')
def test_ip_allocation_for_ipv6_subnet_slaac_address_mode(self):
self.skipTest('Allocating a specific IP is not supported')
def test_ip_allocation_for_ipv6_2_subnet_slaac_mode(self):
self.skipTest('Allocating a specific IP is not supported')
def test_delete_port_with_ipv6_slaac_address(self):
self.skipTest('Allocating a specific IP is not supported')
def test_requested_duplicate_ip(self):
self.skipTest('Allocating a specific IP is not supported')
def test_create_port_invalid_fixed_ip_address_v6_pd_slaac(self):
self.skipTest('Update ipam subnet is not supported')