Merge "Add ndp proxy API tests"
This commit is contained in:
commit
318ec127c5
|
@ -142,6 +142,7 @@ class BaseNetworkTest(test.BaseTestCase):
|
|||
cls.trunks = []
|
||||
cls.network_segment_ranges = []
|
||||
cls.conntrack_helpers = []
|
||||
cls.ndp_proxies = []
|
||||
|
||||
@classmethod
|
||||
def reserve_external_subnet_cidrs(cls):
|
||||
|
@ -161,6 +162,10 @@ class BaseNetworkTest(test.BaseTestCase):
|
|||
for trunk in cls.trunks:
|
||||
cls._try_delete_resource(cls.delete_trunk, trunk)
|
||||
|
||||
# Clean up ndp proxy
|
||||
for ndp_proxy in cls.ndp_proxies:
|
||||
cls._try_delete_resource(cls.delete_ndp_proxy, ndp_proxy)
|
||||
|
||||
# Clean up port forwardings
|
||||
for pf in cls.port_forwardings:
|
||||
cls._try_delete_resource(cls.delete_port_forwarding, pf)
|
||||
|
@ -1132,6 +1137,47 @@ class BaseNetworkTest(test.BaseTestCase):
|
|||
client = client or cth.get('client') or cls.client
|
||||
client.delete_conntrack_helper(cth['router_id'], cth['id'])
|
||||
|
||||
@classmethod
|
||||
def create_ndp_proxy(cls, router_id, port_id, client=None, **kwargs):
|
||||
"""Creates a ndp proxy.
|
||||
|
||||
Create a ndp proxy and schedule it for later deletion.
|
||||
If a client is passed, then it is used for deleting the NDP proxy too.
|
||||
|
||||
:param router_id: router ID where to create the ndp proxy.
|
||||
|
||||
:param port_id: port ID which the ndp proxy associate with
|
||||
|
||||
:param client: network client to be used for creating and cleaning up
|
||||
the ndp proxy.
|
||||
|
||||
:param **kwargs: additional creation parameters to be forwarded to
|
||||
networking server.
|
||||
"""
|
||||
client = client or cls.client
|
||||
|
||||
data = {'router_id': router_id, 'port_id': port_id}
|
||||
if kwargs:
|
||||
data.update(kwargs)
|
||||
ndp_proxy = client.create_ndp_proxy(**data)['ndp_proxy']
|
||||
|
||||
# save client to be used later in cls.delete_ndp_proxy
|
||||
# for final cleanup
|
||||
ndp_proxy['client'] = client
|
||||
cls.ndp_proxies.append(ndp_proxy)
|
||||
return ndp_proxy
|
||||
|
||||
@classmethod
|
||||
def delete_ndp_proxy(cls, ndp_proxy, client=None):
|
||||
"""Delete ndp proxy
|
||||
|
||||
:param client: Client to be used
|
||||
If client is not given it will use the client used to create
|
||||
the ndp proxy, or cls.client if unknown.
|
||||
"""
|
||||
client = client or ndp_proxy.get('client') or cls.client
|
||||
client.delete_ndp_proxy(ndp_proxy['id'])
|
||||
|
||||
|
||||
class BaseAdminNetworkTest(BaseNetworkTest):
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
# Copyright 2022 Troila
|
||||
# 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 import constants
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from neutron_tempest_plugin.api import base
|
||||
from neutron_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class NDPProxyTestJSON(base.BaseNetworkTest):
|
||||
|
||||
credentials = ['primary', 'admin']
|
||||
required_extensions = ['router', 'l3-ndp-proxy']
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(NDPProxyTestJSON, cls).resource_setup()
|
||||
cls.ext_net_id = CONF.network.public_network_id
|
||||
|
||||
# Create network, subnet, router and add interface
|
||||
cls.network = cls.create_network()
|
||||
cls.subnet = cls.create_subnet(
|
||||
cls.network, ip_version=constants.IP_VERSION_6,
|
||||
cidr='2002::abcd:0/112')
|
||||
cls.router = cls.create_router(data_utils.rand_name('router'),
|
||||
external_network_id=cls.ext_net_id,
|
||||
enable_ndp_proxy=True)
|
||||
cls.create_router_interface(cls.router['id'], cls.subnet['id'])
|
||||
|
||||
@decorators.idempotent_id('481bc712-d504-4128-bffb-62d98b88886b')
|
||||
def test_ndp_proxy_lifecycle(self):
|
||||
port = self.create_port(self.network)
|
||||
np_description = 'Test ndp proxy description'
|
||||
np_name = 'test-ndp-proxy'
|
||||
|
||||
# Create ndp proxy
|
||||
created_ndp_proxy = self.create_ndp_proxy(
|
||||
name=np_name,
|
||||
description=np_description,
|
||||
router_id=self.router['id'],
|
||||
port_id=port['id'])
|
||||
self.assertEqual(self.router['id'], created_ndp_proxy['router_id'])
|
||||
self.assertEqual(port['id'], created_ndp_proxy['port_id'])
|
||||
self.assertEqual(np_description, created_ndp_proxy['description'])
|
||||
self.assertEqual(np_name, created_ndp_proxy['name'])
|
||||
self.assertEqual(port['fixed_ips'][0]['ip_address'],
|
||||
created_ndp_proxy['ip_address'])
|
||||
|
||||
# Show created ndp_proxy
|
||||
body = self.client.get_ndp_proxy(created_ndp_proxy['id'])
|
||||
ndp_proxy = body['ndp_proxy']
|
||||
self.assertEqual(np_description, ndp_proxy['description'])
|
||||
self.assertEqual(self.router['id'], ndp_proxy['router_id'])
|
||||
self.assertEqual(port['id'], ndp_proxy['port_id'])
|
||||
self.assertEqual(np_name, ndp_proxy['name'])
|
||||
self.assertEqual(port['fixed_ips'][0]['ip_address'],
|
||||
ndp_proxy['ip_address'])
|
||||
|
||||
# List ndp proxies
|
||||
body = self.client.list_ndp_proxies()
|
||||
ndp_proxy_ids = [np['id'] for np in body['ndp_proxies']]
|
||||
self.assertIn(created_ndp_proxy['id'], ndp_proxy_ids)
|
||||
|
||||
# Update ndp proxy
|
||||
updated_ndp_proxy = self.client.update_ndp_proxy(
|
||||
created_ndp_proxy['id'],
|
||||
name='updated_ndp_proxy')
|
||||
self.assertEqual('updated_ndp_proxy',
|
||||
updated_ndp_proxy['ndp_proxy']['name'])
|
||||
self.assertEqual(
|
||||
np_description, updated_ndp_proxy['ndp_proxy']['description'])
|
||||
self.assertEqual(self.router['id'],
|
||||
updated_ndp_proxy['ndp_proxy']['router_id'])
|
||||
self.assertEqual(port['id'], updated_ndp_proxy['ndp_proxy']['port_id'])
|
||||
self.assertEqual(port['fixed_ips'][0]['ip_address'],
|
||||
updated_ndp_proxy['ndp_proxy']['ip_address'])
|
||||
|
||||
# Delete ndp proxy
|
||||
self.delete_ndp_proxy(created_ndp_proxy)
|
||||
self.assertRaises(exceptions.NotFound,
|
||||
self.client.get_ndp_proxy, created_ndp_proxy['id'])
|
|
@ -0,0 +1,104 @@
|
|||
# Copyright 2022 Troila
|
||||
# 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 import constants
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from neutron_tempest_plugin.api import base
|
||||
from neutron_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class NDPProxyNegativeTestJSON(base.BaseNetworkTest):
|
||||
|
||||
credentials = ['primary', 'admin']
|
||||
required_extensions = ['router', 'l3-ndp-proxy']
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(NDPProxyNegativeTestJSON, cls).resource_setup()
|
||||
cls.ext_net_id = CONF.network.public_network_id
|
||||
|
||||
# Create network, subnet, router and add interface
|
||||
cls.network = cls.create_network()
|
||||
cls.subnet = cls.create_subnet(
|
||||
cls.network, ip_version=constants.IP_VERSION_6,
|
||||
cidr='2002::abcd:0/112')
|
||||
cls.router = cls.create_router(
|
||||
data_utils.rand_name('router'),
|
||||
external_network_id=cls.ext_net_id)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a0897204-bb85-41cc-a5fd-5d0ab8116a07')
|
||||
def test_enable_ndp_proxy_without_external_gw(self):
|
||||
self.client.update_router(self.router['id'], external_gateway_info={})
|
||||
self.assertRaises(exceptions.Conflict,
|
||||
self.client.update_router,
|
||||
self.router['id'],
|
||||
enable_ndp_proxy=True)
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('26e534a0-3e47-4894-8cb5-20a078ce76a9')
|
||||
def test_create_ndp_proxy_with_subnet_not_connect_router(self):
|
||||
self.client.update_router(self.router['id'], enable_ndp_proxy=True)
|
||||
port = self.create_port(self.network)
|
||||
self.assertRaises(exceptions.Conflict,
|
||||
self.create_ndp_proxy,
|
||||
self.router['id'],
|
||||
port_id=port['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('a0d93fd6-1219-4b05-9db8-bdf02846c447')
|
||||
def test_create_ndp_proxy_with_different_address_scope(self):
|
||||
self.client.update_router(self.router['id'], enable_ndp_proxy=True)
|
||||
address_scope = self.create_address_scope(
|
||||
"test-as", ip_version=constants.IP_VERSION_6)
|
||||
subnet_pool = self.create_subnetpool(
|
||||
"test-sp", address_scope_id=address_scope['id'],
|
||||
prefixes=['2002::abc:0/112'], default_prefixlen=112)
|
||||
network = self.create_network()
|
||||
subnet = self.create_subnet(
|
||||
network, ip_version=constants.IP_VERSION_6,
|
||||
cidr="2002::abc:0/112", subnetpool_id=subnet_pool['id'],
|
||||
reserve_cidr=False)
|
||||
self.create_router_interface(self.router['id'], subnet['id'])
|
||||
port = self.create_port(network)
|
||||
self.assertRaises(exceptions.Conflict, self.create_ndp_proxy,
|
||||
self.router['id'], port_id=port['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('f9a4e56d-3836-40cd-8c05-585b3f1e034a')
|
||||
def test_create_ndp_proxy_without_ipv6_address(self):
|
||||
self.client.update_router(
|
||||
self.router['id'], enable_ndp_proxy=True)
|
||||
subnet = self.create_subnet(
|
||||
self.network, ip_version=constants.IP_VERSION_4)
|
||||
self.create_router_interface(self.router['id'], subnet['id'])
|
||||
port = self.create_port(self.network)
|
||||
self.assertRaises(exceptions.Conflict,
|
||||
self.create_ndp_proxy,
|
||||
self.router['id'], port_id=port['id'])
|
||||
|
||||
@decorators.attr(type='negative')
|
||||
@decorators.idempotent_id('e035b3af-ebf9-466d-9ef5-a73b063a1f56')
|
||||
def test_enable_ndp_proxy_and_unset_gateway(self):
|
||||
self.assertRaises(exceptions.Conflict,
|
||||
self.client.update_router,
|
||||
self.router['id'],
|
||||
enable_ndp_proxy=True,
|
||||
external_gateway_info={})
|
|
@ -391,6 +391,8 @@ class NetworkClientJSON(service_client.RestClient):
|
|||
update_body['ha'] = kwargs['ha']
|
||||
if 'routes' in kwargs:
|
||||
update_body['routes'] = kwargs['routes']
|
||||
if 'enable_ndp_proxy' in kwargs:
|
||||
update_body['enable_ndp_proxy'] = kwargs['enable_ndp_proxy']
|
||||
update_body = dict(router=update_body)
|
||||
update_body = jsonutils.dumps(update_body)
|
||||
resp, body = self.put(uri, update_body)
|
||||
|
@ -1132,3 +1134,44 @@ class NetworkClientJSON(service_client.RestClient):
|
|||
self.expected_success(200, resp.status)
|
||||
return service_client.ResponseBody(
|
||||
resp, jsonutils.loads(response_body))
|
||||
|
||||
def create_ndp_proxy(self, **kwargs):
|
||||
uri = '%s/ndp_proxies' % self.uri_prefix
|
||||
post_body = jsonutils.dumps({'ndp_proxy': kwargs})
|
||||
resp, response_body = self.post(uri, post_body)
|
||||
self.expected_success(201, resp.status)
|
||||
body = jsonutils.loads(response_body)
|
||||
return service_client.ResponseBody(resp, body)
|
||||
|
||||
def list_ndp_proxies(self, **kwargs):
|
||||
uri = '%s/ndp_proxies' % self.uri_prefix
|
||||
if kwargs:
|
||||
uri += '?' + urlparse.urlencode(kwargs, doseq=1)
|
||||
resp, response_body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = jsonutils.loads(response_body)
|
||||
return service_client.ResponseBody(resp, body)
|
||||
|
||||
def get_ndp_proxy(self, ndp_proxy_id):
|
||||
uri = '%s/ndp_proxies/%s' % (self.uri_prefix, ndp_proxy_id)
|
||||
get_resp, response_body = self.get(uri)
|
||||
self.expected_success(200, get_resp.status)
|
||||
body = jsonutils.loads(response_body)
|
||||
return service_client.ResponseBody(get_resp, body)
|
||||
|
||||
def update_ndp_proxy(self, ndp_proxy_id, **kwargs):
|
||||
uri = '%s/ndp_proxies/%s' % (self.uri_prefix, ndp_proxy_id)
|
||||
get_resp, _ = self.get(uri)
|
||||
self.expected_success(200, get_resp.status)
|
||||
put_body = jsonutils.dumps({'ndp_proxy': kwargs})
|
||||
put_resp, response_body = self.put(uri, put_body)
|
||||
self.expected_success(200, put_resp.status)
|
||||
body = jsonutils.loads(response_body)
|
||||
return service_client.ResponseBody(put_resp, body)
|
||||
|
||||
def delete_ndp_proxy(self, ndp_proxy_id):
|
||||
uri = '%s/ndp_proxies/%s' % (
|
||||
self.uri_prefix, ndp_proxy_id)
|
||||
resp, body = self.delete(uri)
|
||||
self.expected_success(204, resp.status)
|
||||
return service_client.ResponseBody(resp, body)
|
||||
|
|
|
@ -79,8 +79,10 @@
|
|||
- floatingip-pools
|
||||
- ip-substring-filtering
|
||||
- l3-conntrack-helper
|
||||
- l3-ext-ndp-proxy
|
||||
- l3-flavors
|
||||
- l3-ha
|
||||
- l3-ndp-proxy
|
||||
- l3_agent_scheduler
|
||||
- metering
|
||||
- multi-provider
|
||||
|
@ -140,6 +142,7 @@
|
|||
neutron-port-forwarding: true
|
||||
neutron-conntrack-helper: true
|
||||
neutron-tag-ports-during-bulk-creation: true
|
||||
neutron-ndp-proxy: true
|
||||
br-ex-tcpdump: true
|
||||
br-int-flows: true
|
||||
# Cinder services
|
||||
|
|
Loading…
Reference in New Issue