ADD API tests for network ip availability

This patch is intended to add api tests for network ip availability.
Right now only tests for list is added in later revisions tests for
show will also be added

Change-Id: I8c1568d097525c43576e516bd86d820c6b0a78fb
This commit is contained in:
Manjeet Singh Bhatia 2016-02-23 02:34:17 +00:00 committed by Armando Migliaccio
parent dc68662a0b
commit 594f6f2023
3 changed files with 171 additions and 2 deletions

View File

@ -43,6 +43,7 @@ DEFAULT_SERVICE_PLUGINS = {
'auto_allocate': 'auto-allocated-topology', 'auto_allocate': 'auto-allocated-topology',
'tag': 'tag', 'tag': 'tag',
'timestamp_core': 'timestamp_core', 'timestamp_core': 'timestamp_core',
'network_ip_availability': 'network-ip-availability'
} }
# Service operation status constants # Service operation status constants

View File

@ -0,0 +1,168 @@
# Copyright 2016 OpenStack Foundation
# 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 netaddr
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest import test
from neutron.tests.api import base
from neutron.tests.tempest import config
from neutron_lib import constants as lib_constants
CONF = config.CONF
# 3 IP addresses are taken from every total for IPv4 these are reserved
DEFAULT_IP4_RESERVED = 3
# 2 IP addresses are taken from every total for IPv6 these are reserved
# I assume the reason for having one less than IPv4 is it does not have
# broadcast address
DEFAULT_IP6_RESERVED = 2
DELETE_TIMEOUT = 10
DELETE_SLEEP = 2
class NetworksIpAvailabilityTest(base.BaseAdminNetworkTest):
"""
Tests the following operations in the Neutron API using the REST client for
Neutron:
test total and used ips for net create
test total and ips for net after subnet create
test total and used ips for net after subnet and port create
"""
@classmethod
def resource_setup(cls):
super(NetworksIpAvailabilityTest, cls).resource_setup()
if not test.is_extension_enabled('network-ip-availability', 'network'):
msg = "network-ip-availability extension not enabled."
raise cls.skipException(msg)
def _get_used_ips(self, network, net_availability):
if network:
for availability in net_availability['network_ip_availabilities']:
if availability['network_id'] == network['id']:
return availability['used_ips']
def _cleanUp_port(self, port_id):
# delete port, any way to avoid race
try:
self.client.delete_port(port_id)
# if port is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
def _assert_total_and_used_ips(self, expected_used, expected_total,
network, net_availability):
if network:
for availability in net_availability['network_ip_availabilities']:
if availability['network_id'] == network['id']:
self.assertEqual(expected_total, availability['total_ips'])
self.assertEqual(expected_used, availability['used_ips'])
def _create_subnet(self, network, ip_version):
if ip_version == lib_constants.IP_VERSION_4:
cidr = netaddr.IPNetwork('20.0.0.0/24')
mask_bits = CONF.network.tenant_network_mask_bits
elif ip_version == lib_constants.IP_VERSION_6:
cidr = netaddr.IPNetwork('20:db8::/64')
mask_bits = CONF.network.tenant_network_v6_mask_bits
subnet_cidr = cidr.subnet(mask_bits).next()
prefix_len = subnet_cidr.prefixlen
subnet = self.create_subnet(network,
cidr=subnet_cidr,
mask_bits=mask_bits,
ip_version=ip_version)
return subnet, prefix_len
def calc_total_ips(prefix, ip_version):
# will calculate total ips after removing reserved.
if ip_version == lib_constants.IP_VERSION_4:
total_ips = 2 ** (32 - prefix) - DEFAULT_IP4_RESERVED
elif ip_version == lib_constants.IP_VERSION_6:
total_ips = 2 ** (128 - prefix) - DEFAULT_IP6_RESERVED
return total_ips
class NetworksIpAvailabilityIPv4Test(NetworksIpAvailabilityTest):
ip_version = lib_constants.IP_VERSION_4
@test.attr(type='smoke')
@test.idempotent_id('0f33cc8c-1bf6-47d1-9ce1-010618240599')
def test_admin_network_availability_before_subnet(self):
net_name = data_utils.rand_name('network-')
network = self.create_network(network_name=net_name)
self.addCleanup(self.client.delete_network, network['id'])
net_availability = self.admin_client.list_network_ip_availabilities()
self._assert_total_and_used_ips(0, 0, network, net_availability)
@test.attr(type='smoke')
@test.idempotent_id('3aecd3b2-16ed-4b87-a54a-91d7b3c2986b')
def test_net_ip_availability_after_subnet_and_ports(self):
net_name = data_utils.rand_name('network-')
network = self.create_network(network_name=net_name)
self.addCleanup(self.client.delete_network, network['id'])
subnet, prefix = self._create_subnet(network, self.ip_version)
self.addCleanup(self.client.delete_subnet, subnet['id'])
body = self.admin_client.list_network_ip_availabilities()
used_ip = self._get_used_ips(network, body)
port1 = self.client.create_port(network_id=network['id'])
self.addCleanup(self.client.delete_port, port1['port']['id'])
port2 = self.client.create_port(network_id=network['id'])
self.addCleanup(self.client.delete_port, port2['port']['id'])
net_availability = self.admin_client.list_network_ip_availabilities()
self._assert_total_and_used_ips(
used_ip + 2,
calc_total_ips(prefix, self.ip_version),
network, net_availability)
@test.attr(type='smoke')
@test.idempotent_id('9f11254d-757b-492e-b14b-f52144e4ee7b')
def test_net_ip_availability_after_port_delete(self):
net_name = data_utils.rand_name('network-')
network = self.create_network(network_name=net_name)
self.addCleanup(self.client.delete_network, network['id'])
subnet, prefix = self._create_subnet(network, self.ip_version)
self.addCleanup(self.client.delete_subnet, subnet['id'])
port = self.client.create_port(network_id=network['id'])
self.addCleanup(self._cleanUp_port, port['port']['id'])
net_availability = self.admin_client.list_network_ip_availabilities()
used_ip = self._get_used_ips(network, net_availability)
self.client.delete_port(port['port']['id'])
def get_net_availability():
availabilities = self.admin_client.list_network_ip_availabilities()
used_ip_after_port_delete = self._get_used_ips(network,
availabilities)
return used_ip - 1 == used_ip_after_port_delete
self.assertTrue(
test.call_until_true(
get_net_availability, DELETE_TIMEOUT, DELETE_SLEEP),
msg="IP address did not become available after port delete")
class NetworksIpAvailabilityIPv6Test(NetworksIpAvailabilityIPv4Test):
ip_version = lib_constants.IP_VERSION_6

View File

@ -3,7 +3,7 @@ prelude: >
Neutron now provides network IP availability information. Neutron now provides network IP availability information.
features: features:
- A new API endpoint /v2.0/network-ip-availabilities that allows an admin - A new API endpoint /v2.0/network-ip-availabilities that allows an admin
to quickly get counts of used_ips and total_ips for network(s). New to quickly get counts of used_ips and total_ips for network(s) is available.
endpoint allows filtering by network_id, network_name, tenant_id, and New endpoint allows filtering by network_id, network_name, tenant_id, and
ip_version. Response returns network and nested subnet data that includes ip_version. Response returns network and nested subnet data that includes
used and total IPs. used and total IPs.