asarfaty 5d2837c83a Removing dependency on the "mock" package
Now that we are python3 only, we should move to using the built
in version of mock that supports all of our testing needs and
remove the dependency on the "mock" package.

Also see commit: Ifcaf1c21bea0ec3c35278e49cecc90a101a82113

Change-Id: I58da980351fe14357c210c02eb167a6c0af9d09e
2020-05-10 17:21:14 +02:00

329 lines
16 KiB
Python

# Copyright 2015 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.
from unittest import mock
import netaddr
from neutron_lib import constants
from neutron_lib import exceptions as n_exc
from neutron_lib.plugins import directory
from oslo_config import cfg
import webob.exc
from vmware_nsx.api_client import exception as api_exc
from vmware_nsx.common import config
class MetaDataTestCase(object):
def _metadata_setup(self, mode=config.MetadataModes.DIRECT,
on_demand=False):
cfg.CONF.set_override('metadata_mode', mode, self.plugin.cfg_group)
if hasattr(getattr(cfg.CONF, self.plugin.cfg_group),
'metadata_on_demand'):
cfg.CONF.set_override('metadata_on_demand', on_demand,
self.plugin.cfg_group)
def _metadata_teardown(self):
cfg.CONF.set_override('metadata_mode', None, self.plugin.cfg_group)
if hasattr(getattr(cfg.CONF, self.plugin.cfg_group),
'metadata_on_demand'):
cfg.CONF.set_override('metadata_on_demand', False,
self.plugin.cfg_group)
def _check_metadata(self, expected_subnets, expected_ports):
subnets = self._list('subnets')['subnets']
self.assertEqual(len(subnets), expected_subnets)
meta_net_id, meta_sub_id = None, None
meta_cidr = netaddr.IPNetwork('169.254.0.0/16')
for subnet in subnets:
cidr = netaddr.IPNetwork(subnet['cidr'])
if meta_cidr == cidr or meta_cidr in cidr.supernet(16):
meta_sub_id = subnet['id']
meta_net_id = subnet['network_id']
break
ports = self._list(
'ports',
query_params='network_id=%s' % meta_net_id)['ports']
self.assertEqual(len(ports), expected_ports)
meta_port_id = ports[0]['id'] if ports else None
return meta_net_id, meta_sub_id, meta_port_id
def test_router_add_interface_subnet_with_metadata_access(self):
self._metadata_setup()
self.test_router_add_interface_subnet()
self._metadata_teardown()
def test_router_add_interface_port_with_metadata_access(self):
self._metadata_setup()
self.test_router_add_interface_port()
self._metadata_teardown()
def test_router_add_interface_dupsubnet_returns_400_with_metadata(self):
self._metadata_setup()
self.test_router_add_interface_dup_subnet1_returns_400()
self._metadata_teardown()
def test_router_add_interface_overlapped_cidr_returns_400_with(self):
self._metadata_setup()
self.test_router_add_interface_overlapped_cidr_returns_400()
self._metadata_teardown()
def test_router_remove_interface_inuse_returns_409_with_metadata(self):
self._metadata_setup()
self.test_router_remove_interface_inuse_returns_409()
self._metadata_teardown()
def test_router_remove_iface_wrong_sub_returns_400_with_metadata(self):
self._metadata_setup()
self.test_router_remove_interface_wrong_subnet_returns_400()
self._metadata_teardown()
def test_router_delete_with_metadata_access(self):
self._metadata_setup()
self.test_router_delete()
self._metadata_teardown()
def test_router_delete_with_port_existed_returns_409_with_metadata(self):
self._metadata_setup()
self.test_router_delete_with_port_existed_returns_409()
self._metadata_teardown()
def test_delete_port_with_metadata(self):
self._metadata_setup(config.MetadataModes.INDIRECT)
with self.subnet() as s:
with self.port(subnet=s, fixed_ips=[], device_id='1234',
device_owner=constants.DEVICE_OWNER_DHCP) as port:
self._delete('ports', port['port']['id'])
self._metadata_teardown()
def test_metadatata_network_created_with_router_interface_add(self):
self._metadata_setup()
with mock.patch.object(self._plugin_class, 'schedule_network') as f:
with self.router() as r:
with self.subnet() as s:
self._router_interface_action('add',
r['router']['id'],
s['subnet']['id'],
None)
r_ports = self._list('ports')['ports']
self.assertEqual(len(r_ports), 2)
ips = []
for port in r_ports:
ips.extend([netaddr.IPAddress(fixed_ip['ip_address'])
for fixed_ip in port['fixed_ips']])
meta_cidr = netaddr.IPNetwork('169.254.0.0/16')
self.assertTrue(any([ip in meta_cidr for ip in ips]))
# Needed to avoid 409.
self._router_interface_action('remove',
r['router']['id'],
s['subnet']['id'],
None)
# Verify that there has been a schedule_network all for the
# metadata network
expected_net_name = 'meta-%s' % r['router']['id']
found = False
for call in f.call_args_list:
# The network data are the last of the positional arguments
net_dict = call[0][-1]
if net_dict['name'] == expected_net_name:
self.assertFalse(net_dict['port_security_enabled'])
self.assertFalse(net_dict['shared'])
self.assertFalse(net_dict['tenant_id'])
found = True
break
else:
self.fail("Expected schedule_network call for metadata "
"network %s not found" % expected_net_name)
self.assertTrue(found)
self._metadata_teardown()
def test_metadata_network_create_rollback_on_create_subnet_failure(self):
self._metadata_setup()
with self.router() as r:
with self.subnet() as s:
# Raise a NeutronException (eg: NotFound).
with mock.patch.object(self._plugin_class,
'create_subnet',
side_effect=n_exc.NotFound):
self._router_interface_action(
'add', r['router']['id'], s['subnet']['id'], None)
# Ensure metadata network was removed.
nets = self._list('networks')['networks']
self.assertEqual(len(nets), 1)
# Needed to avoid 409.
self._router_interface_action('remove',
r['router']['id'],
s['subnet']['id'],
None)
self._metadata_teardown()
def test_metadata_network_create_rollback_on_add_rtr_iface_failure(self):
self._metadata_setup()
with self.router() as r:
with self.subnet() as s:
# Save function being mocked.
real_func = self._plugin_class.add_router_interface
plugin_instance = directory.get_plugin()
# Raise a NeutronException when adding metadata subnet
# to router.
def side_effect(*args):
if args[-1]['subnet_id'] == s['subnet']['id']:
# Do the real thing.
return real_func(plugin_instance, *args)
# Otherwise raise.
raise api_exc.NsxApiException()
with mock.patch.object(self._plugin_class,
'add_router_interface',
side_effect=side_effect):
self._router_interface_action(
'add', r['router']['id'], s['subnet']['id'], None)
# Ensure metadata network was removed.
nets = self._list('networks')['networks']
self.assertEqual(len(nets), 1)
# Needed to avoid 409.
self._router_interface_action('remove',
r['router']['id'],
s['subnet']['id'],
None)
self._metadata_teardown()
def test_metadata_network_removed_with_router_interface_remove(self):
self._metadata_setup()
with self.router() as r:
with self.subnet() as s:
self._router_interface_action('add', r['router']['id'],
s['subnet']['id'], None)
meta_net_id, meta_sub_id, meta_port_id = self._check_metadata(
expected_subnets=2, expected_ports=1)
self._router_interface_action('remove', r['router']['id'],
s['subnet']['id'], None)
self._show('networks', meta_net_id,
webob.exc.HTTPNotFound.code)
self._show('ports', meta_port_id,
webob.exc.HTTPNotFound.code)
self._show('subnets', meta_sub_id,
webob.exc.HTTPNotFound.code)
self._metadata_teardown()
def test_metadata_network_remove_rollback_on_failure(self):
self._metadata_setup()
with self.router() as r:
with self.subnet() as s:
self._router_interface_action('add', r['router']['id'],
s['subnet']['id'], None)
networks = self._list('networks')['networks']
for network in networks:
if network['id'] != s['subnet']['network_id']:
meta_net_id = network['id']
ports = self._list(
'ports',
query_params='network_id=%s' % meta_net_id)['ports']
meta_port_id = ports[0]['id']
# Save function being mocked.
real_func = self._plugin_class.remove_router_interface
plugin_instance = directory.get_plugin()
# Raise a NeutronException when removing metadata subnet
# from router.
def side_effect(*args):
if args[-1].get('subnet_id') == s['subnet']['id']:
# Do the real thing.
return real_func(plugin_instance, *args)
# Otherwise raise.
raise api_exc.NsxApiException()
with mock.patch.object(self._plugin_class,
'remove_router_interface',
side_effect=side_effect):
self._router_interface_action('remove', r['router']['id'],
s['subnet']['id'], None)
# Metadata network and subnet should still be there.
self._show('networks', meta_net_id,
webob.exc.HTTPOk.code)
self._show('ports', meta_port_id,
webob.exc.HTTPOk.code)
self._metadata_teardown()
def test_metadata_network_with_update_subnet_dhcp_enable(self):
self._metadata_setup(on_demand=True)
with self.router() as r:
# Create a DHCP-disabled subnet.
with self.subnet(enable_dhcp=False) as s:
self._router_interface_action('add', r['router']['id'],
s['subnet']['id'], None)
meta_net_id, meta_sub_id, meta_port_id = self._check_metadata(
expected_subnets=2, expected_ports=1)
# Update subnet to DHCP-enabled.
data = {'subnet': {'enable_dhcp': True}}
req = self.new_update_request('subnets', data,
s['subnet']['id'])
res = self.deserialize(self.fmt, req.get_response(self.api))
self.assertEqual(True, res['subnet']['enable_dhcp'])
self._check_metadata(expected_subnets=1, expected_ports=0)
self._show('networks', meta_net_id,
webob.exc.HTTPNotFound.code)
self._show('ports', meta_port_id,
webob.exc.HTTPNotFound.code)
self._show('subnets', meta_sub_id,
webob.exc.HTTPNotFound.code)
self._metadata_teardown()
def test_metadata_network_with_update_subnet_dhcp_disable(self):
self._metadata_setup(on_demand=True)
with self.router() as r:
# Create a DHCP-enabled subnet.
with self.subnet(enable_dhcp=True) as s:
self._router_interface_action('add', r['router']['id'],
s['subnet']['id'], None)
self._check_metadata(expected_subnets=1, expected_ports=0)
# Update subnet to DHCP-disabled.
data = {'subnet': {'enable_dhcp': False}}
req = self.new_update_request('subnets', data,
s['subnet']['id'])
res = self.deserialize(self.fmt, req.get_response(self.api))
self.assertEqual(False, res['subnet']['enable_dhcp'])
meta_net_id, meta_sub_id, meta_port_id = self._check_metadata(
expected_subnets=2, expected_ports=1)
self._show('networks', meta_net_id,
webob.exc.HTTPOk.code)
self._show('ports', meta_port_id,
webob.exc.HTTPOk.code)
self._show('subnets', meta_sub_id,
webob.exc.HTTPOk.code)
self._metadata_teardown()
def test_metadata_dhcp_host_route(self):
self._metadata_setup(config.MetadataModes.INDIRECT)
subnets = self._list('subnets')['subnets']
with self.subnet() as s:
with self.port(subnet=s, device_id='1234',
device_owner=constants.DEVICE_OWNER_DHCP) as port:
subnets = self._list('subnets')['subnets']
self.assertEqual(len(subnets), 1)
subnet_ip_net = netaddr.IPNetwork(s['subnet']['cidr'])
self.assertIn(netaddr.IPAddress(
subnets[0]['host_routes'][0]['nexthop']),
subnet_ip_net)
self.assertEqual(subnets[0]['host_routes'][0]['destination'],
'169.254.169.254/32')
self._delete('ports', port['port']['id'])
subnets = self._list('subnets')['subnets']
# Test that route is deleted after dhcp port is removed.
self.assertEqual(len(subnets[0]['host_routes']), 0)
self._metadata_teardown()