openstacksdk/openstack/tests/functional/cloud/test_router.py

368 lines
14 KiB
Python

# 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.
"""
test_router
----------------------------------
Functional tests for `shade` router methods.
"""
import ipaddress
from openstack.cloud.exc import OpenStackCloudException
from openstack.tests.functional import base
EXPECTED_TOPLEVEL_FIELDS = (
'id', 'name', 'is_admin_state_up', 'external_gateway_info',
'project_id', 'routes', 'status'
)
EXPECTED_GW_INFO_FIELDS = ('network_id', 'enable_snat', 'external_fixed_ips')
class TestRouter(base.BaseFunctionalTest):
def setUp(self):
super(TestRouter, self).setUp()
if not self.operator_cloud:
self.skipTest("Operator cloud required for this test")
if not self.operator_cloud.has_service('network'):
self.skipTest('Network service not supported by cloud')
self.router_prefix = self.getUniqueString('router')
self.network_prefix = self.getUniqueString('network')
self.subnet_prefix = self.getUniqueString('subnet')
# NOTE(Shrews): Order matters!
self.addCleanup(self._cleanup_networks)
self.addCleanup(self._cleanup_subnets)
self.addCleanup(self._cleanup_routers)
def _cleanup_routers(self):
exception_list = list()
for router in self.operator_cloud.list_routers():
if router['name'].startswith(self.router_prefix):
try:
self.operator_cloud.delete_router(router['name'])
except Exception as e:
exception_list.append(str(e))
continue
if exception_list:
raise OpenStackCloudException('\n'.join(exception_list))
def _cleanup_networks(self):
exception_list = list()
for network in self.operator_cloud.list_networks():
if network['name'].startswith(self.network_prefix):
try:
self.operator_cloud.delete_network(network['name'])
except Exception as e:
exception_list.append(str(e))
continue
if exception_list:
raise OpenStackCloudException('\n'.join(exception_list))
def _cleanup_subnets(self):
exception_list = list()
for subnet in self.operator_cloud.list_subnets():
if subnet['name'].startswith(self.subnet_prefix):
try:
self.operator_cloud.delete_subnet(subnet['id'])
except Exception as e:
exception_list.append(str(e))
continue
if exception_list:
raise OpenStackCloudException('\n'.join(exception_list))
def test_create_router_basic(self):
net1_name = self.network_prefix + '_net1'
net1 = self.operator_cloud.create_network(
name=net1_name, external=True)
router_name = self.router_prefix + '_create_basic'
router = self.operator_cloud.create_router(
name=router_name,
admin_state_up=True,
ext_gateway_net_id=net1['id'],
)
for field in EXPECTED_TOPLEVEL_FIELDS:
self.assertIn(field, router)
ext_gw_info = router['external_gateway_info']
for field in EXPECTED_GW_INFO_FIELDS:
self.assertIn(field, ext_gw_info)
self.assertEqual(router_name, router['name'])
self.assertEqual('ACTIVE', router['status'])
self.assertEqual(net1['id'], ext_gw_info['network_id'])
self.assertTrue(ext_gw_info['enable_snat'])
def test_create_router_project(self):
project = self.operator_cloud.get_project('demo')
self.assertIsNotNone(project)
proj_id = project['id']
net1_name = self.network_prefix + '_net1'
net1 = self.operator_cloud.create_network(
name=net1_name, external=True, project_id=proj_id)
router_name = self.router_prefix + '_create_project'
router = self.operator_cloud.create_router(
name=router_name,
admin_state_up=True,
ext_gateway_net_id=net1['id'],
project_id=proj_id
)
for field in EXPECTED_TOPLEVEL_FIELDS:
self.assertIn(field, router)
ext_gw_info = router['external_gateway_info']
for field in EXPECTED_GW_INFO_FIELDS:
self.assertIn(field, ext_gw_info)
self.assertEqual(router_name, router['name'])
self.assertEqual('ACTIVE', router['status'])
self.assertEqual(proj_id, router['tenant_id'])
self.assertEqual(net1['id'], ext_gw_info['network_id'])
self.assertTrue(ext_gw_info['enable_snat'])
def _create_and_verify_advanced_router(self,
external_cidr,
external_gateway_ip=None):
# external_cidr must be passed in as unicode (u'')
# NOTE(Shrews): The arguments are needed because these tests
# will run in parallel and we want to make sure that each test
# is using different resources to prevent race conditions.
net1_name = self.network_prefix + '_net1'
sub1_name = self.subnet_prefix + '_sub1'
net1 = self.operator_cloud.create_network(
name=net1_name, external=True)
sub1 = self.operator_cloud.create_subnet(
net1['id'], external_cidr, subnet_name=sub1_name,
gateway_ip=external_gateway_ip
)
ip_net = ipaddress.IPv4Network(external_cidr)
last_ip = str(list(ip_net.hosts())[-1])
router_name = self.router_prefix + '_create_advanced'
router = self.operator_cloud.create_router(
name=router_name,
admin_state_up=False,
ext_gateway_net_id=net1['id'],
enable_snat=False,
ext_fixed_ips=[
{'subnet_id': sub1['id'], 'ip_address': last_ip}
]
)
for field in EXPECTED_TOPLEVEL_FIELDS:
self.assertIn(field, router)
ext_gw_info = router['external_gateway_info']
for field in EXPECTED_GW_INFO_FIELDS:
self.assertIn(field, ext_gw_info)
self.assertEqual(router_name, router['name'])
self.assertEqual('ACTIVE', router['status'])
self.assertFalse(router['admin_state_up'])
self.assertEqual(1, len(ext_gw_info['external_fixed_ips']))
self.assertEqual(
sub1['id'],
ext_gw_info['external_fixed_ips'][0]['subnet_id']
)
self.assertEqual(
last_ip,
ext_gw_info['external_fixed_ips'][0]['ip_address']
)
return router
def test_create_router_advanced(self):
self._create_and_verify_advanced_router(external_cidr=u'10.2.2.0/24')
def test_add_remove_router_interface(self):
router = self._create_and_verify_advanced_router(
external_cidr=u'10.3.3.0/24')
net_name = self.network_prefix + '_intnet1'
sub_name = self.subnet_prefix + '_intsub1'
net = self.operator_cloud.create_network(name=net_name)
sub = self.operator_cloud.create_subnet(
net['id'], '10.4.4.0/24', subnet_name=sub_name,
gateway_ip='10.4.4.1'
)
iface = self.operator_cloud.add_router_interface(
router, subnet_id=sub['id'])
self.assertIsNone(
self.operator_cloud.remove_router_interface(
router, subnet_id=sub['id'])
)
# Test return values *after* the interface is detached so the
# resources we've created can be cleaned up if these asserts fail.
self.assertIsNotNone(iface)
for key in ('id', 'subnet_id', 'port_id', 'tenant_id'):
self.assertIn(key, iface)
self.assertEqual(router['id'], iface['id'])
self.assertEqual(sub['id'], iface['subnet_id'])
def test_list_router_interfaces(self):
router = self._create_and_verify_advanced_router(
external_cidr=u'10.5.5.0/24')
net_name = self.network_prefix + '_intnet1'
sub_name = self.subnet_prefix + '_intsub1'
net = self.operator_cloud.create_network(name=net_name)
sub = self.operator_cloud.create_subnet(
net['id'], '10.6.6.0/24', subnet_name=sub_name,
gateway_ip='10.6.6.1'
)
iface = self.operator_cloud.add_router_interface(
router, subnet_id=sub['id'])
all_ifaces = self.operator_cloud.list_router_interfaces(router)
int_ifaces = self.operator_cloud.list_router_interfaces(
router, interface_type='internal')
ext_ifaces = self.operator_cloud.list_router_interfaces(
router, interface_type='external')
self.assertIsNone(
self.operator_cloud.remove_router_interface(
router, subnet_id=sub['id'])
)
# Test return values *after* the interface is detached so the
# resources we've created can be cleaned up if these asserts fail.
self.assertIsNotNone(iface)
self.assertEqual(2, len(all_ifaces))
self.assertEqual(1, len(int_ifaces))
self.assertEqual(1, len(ext_ifaces))
ext_fixed_ips = router['external_gateway_info']['external_fixed_ips']
self.assertEqual(ext_fixed_ips[0]['subnet_id'],
ext_ifaces[0]['fixed_ips'][0]['subnet_id'])
self.assertEqual(sub['id'], int_ifaces[0]['fixed_ips'][0]['subnet_id'])
def test_update_router_name(self):
router = self._create_and_verify_advanced_router(
external_cidr=u'10.7.7.0/24')
new_name = self.router_prefix + '_update_name'
updated = self.operator_cloud.update_router(
router['id'], name=new_name)
self.assertIsNotNone(updated)
for field in EXPECTED_TOPLEVEL_FIELDS:
self.assertIn(field, updated)
# Name is the only change we expect
self.assertEqual(new_name, updated['name'])
# Validate nothing else changed
self.assertEqual(router['status'], updated['status'])
self.assertEqual(router['admin_state_up'], updated['admin_state_up'])
self.assertEqual(router['external_gateway_info'],
updated['external_gateway_info'])
def test_update_router_routes(self):
router = self._create_and_verify_advanced_router(
external_cidr=u'10.7.7.0/24')
routes = [{
"destination": "10.7.7.0/24",
"nexthop": "10.7.7.99"
}]
updated = self.operator_cloud.update_router(
router['id'], routes=routes)
self.assertIsNotNone(updated)
for field in EXPECTED_TOPLEVEL_FIELDS:
self.assertIn(field, updated)
# Name is the only change we expect
self.assertEqual(routes, updated['routes'])
# Validate nothing else changed
self.assertEqual(router['status'], updated['status'])
self.assertEqual(router['admin_state_up'], updated['admin_state_up'])
self.assertEqual(router['external_gateway_info'],
updated['external_gateway_info'])
def test_update_router_admin_state(self):
router = self._create_and_verify_advanced_router(
external_cidr=u'10.8.8.0/24')
updated = self.operator_cloud.update_router(
router['id'], admin_state_up=True)
self.assertIsNotNone(updated)
for field in EXPECTED_TOPLEVEL_FIELDS:
self.assertIn(field, updated)
# admin_state_up is the only change we expect
self.assertTrue(updated['admin_state_up'])
self.assertNotEqual(router['admin_state_up'],
updated['admin_state_up'])
# Validate nothing else changed
self.assertEqual(router['status'], updated['status'])
self.assertEqual(router['name'], updated['name'])
self.assertEqual(router['external_gateway_info'],
updated['external_gateway_info'])
def test_update_router_ext_gw_info(self):
router = self._create_and_verify_advanced_router(
external_cidr=u'10.9.9.0/24')
# create a new subnet
existing_net_id = router['external_gateway_info']['network_id']
sub_name = self.subnet_prefix + '_update'
sub = self.operator_cloud.create_subnet(
existing_net_id, '10.10.10.0/24', subnet_name=sub_name,
gateway_ip='10.10.10.1'
)
updated = self.operator_cloud.update_router(
router['id'],
ext_gateway_net_id=existing_net_id,
ext_fixed_ips=[
{'subnet_id': sub['id'], 'ip_address': '10.10.10.77'}
]
)
self.assertIsNotNone(updated)
for field in EXPECTED_TOPLEVEL_FIELDS:
self.assertIn(field, updated)
# external_gateway_info is the only change we expect
ext_gw_info = updated['external_gateway_info']
self.assertEqual(1, len(ext_gw_info['external_fixed_ips']))
self.assertEqual(
sub['id'],
ext_gw_info['external_fixed_ips'][0]['subnet_id']
)
self.assertEqual(
'10.10.10.77',
ext_gw_info['external_fixed_ips'][0]['ip_address']
)
# Validate nothing else changed
self.assertEqual(router['status'], updated['status'])
self.assertEqual(router['name'], updated['name'])
self.assertEqual(router['admin_state_up'], updated['admin_state_up'])