24
from oslo_db import exception as db_exc
23
26
from neutron.common import constants
24
27
from neutron.common import exceptions as exc
25
28
from neutron.common import utils
26
29
from neutron import context
30
from neutron.db import api as db_api
27
31
from neutron.db import db_base_plugin_v2 as base_plugin
28
32
from neutron.db import l3_db
29
33
from neutron.extensions import external_net as external_net
30
from neutron.extensions import l3agentscheduler
31
34
from neutron.extensions import multiprovidernet as mpnet
32
35
from neutron.extensions import portbindings
33
36
from neutron.extensions import providernet as pnet
138
141
class TestMl2NetworksV2(test_plugin.TestNetworksV2,
139
142
Ml2PluginV2TestCase):
143
def setUp(self, plugin=None):
144
super(TestMl2NetworksV2, self).setUp()
146
self.pnets = [{'name': 'net1',
147
pnet.NETWORK_TYPE: 'vlan',
148
pnet.PHYSICAL_NETWORK: 'physnet1',
149
pnet.SEGMENTATION_ID: 1,
150
'tenant_id': 'tenant_one'},
152
pnet.NETWORK_TYPE: 'vlan',
153
pnet.PHYSICAL_NETWORK: 'physnet2',
154
pnet.SEGMENTATION_ID: 210,
155
'tenant_id': 'tenant_one'},
157
pnet.NETWORK_TYPE: 'vlan',
158
pnet.PHYSICAL_NETWORK: 'physnet2',
159
pnet.SEGMENTATION_ID: 220,
160
'tenant_id': 'tenant_one'}
162
# multiprovider networks
163
self.mp_nets = [{'name': 'net4',
165
[{pnet.NETWORK_TYPE: 'vlan',
166
pnet.PHYSICAL_NETWORK: 'physnet2',
167
pnet.SEGMENTATION_ID: 1},
168
{pnet.NETWORK_TYPE: 'vlan',
169
pnet.PHYSICAL_NETWORK: 'physnet2',
170
pnet.SEGMENTATION_ID: 202}],
171
'tenant_id': 'tenant_one'}
173
self.nets = self.mp_nets + self.pnets
140
175
def test_port_delete_helper_tolerates_failure(self):
141
176
plugin = manager.NeutronManager.get_plugin()
142
177
with mock.patch.object(plugin, "delete_port",
149
184
side_effect=exc.SubnetNotFound(subnet_id="1")):
150
185
plugin._delete_subnets(None, [mock.MagicMock()])
187
def _create_and_verify_networks(self, networks):
188
for net_idx, net in enumerate(networks):
190
req = self.new_create_request('networks',
193
network = self.deserialize(self.fmt,
194
req.get_response(self.api))['network']
195
if mpnet.SEGMENTS not in net:
196
for k, v in six.iteritems(net):
197
self.assertEqual(net[k], network[k])
198
self.assertNotIn(mpnet.SEGMENTS, network)
200
segments = network[mpnet.SEGMENTS]
201
expected_segments = net[mpnet.SEGMENTS]
202
self.assertEqual(len(expected_segments), len(segments))
203
for expected, actual in zip(expected_segments, segments):
204
self.assertEqual(expected, actual)
206
def _lookup_network_by_segmentation_id(self, seg_id, num_expected_nets):
207
params_str = "%s=%s" % (pnet.SEGMENTATION_ID, seg_id)
208
net_req = self.new_list_request('networks', None,
210
networks = self.deserialize(self.fmt, net_req.get_response(self.api))
211
if num_expected_nets:
212
self.assertIsNotNone(networks)
213
self.assertEqual(num_expected_nets, len(networks['networks']))
215
self.assertIsNone(networks)
218
def test_list_networks_with_segmentation_id(self):
219
self._create_and_verify_networks(self.pnets)
220
# verify we can find the network that we expect
222
expected_net = [n for n in self.pnets
223
if n[pnet.SEGMENTATION_ID] == lookup_vlan_id].pop()
224
networks = self._lookup_network_by_segmentation_id(lookup_vlan_id, 1)
225
# verify all provider attributes
226
network = networks['networks'][0]
227
for attr in pnet.ATTRIBUTES:
228
self.assertEqual(expected_net[attr], network[attr])
230
def test_list_mpnetworks_with_segmentation_id(self):
231
self._create_and_verify_networks(self.nets)
233
# get all networks with seg_id=1 (including multisegment networks)
235
networks = self._lookup_network_by_segmentation_id(lookup_vlan_id, 2)
238
networks = [n for n in networks['networks'] if mpnet.SEGMENTS in n]
239
network = networks.pop()
240
# verify attributes of the looked up item
241
segments = network[mpnet.SEGMENTS]
242
expected_segments = self.mp_nets[0][mpnet.SEGMENTS]
243
self.assertEqual(len(expected_segments), len(segments))
244
for expected, actual in zip(expected_segments, segments):
245
self.assertEqual(expected, actual)
247
def test_create_network_segment_allocation_fails(self):
248
plugin = manager.NeutronManager.get_plugin()
249
with mock.patch.object(plugin.type_manager, 'create_network_segments',
250
side_effect=db_exc.RetryRequest(ValueError())) as f:
251
self.assertRaises(ValueError,
252
plugin.create_network,
253
context.get_admin_context(),
254
{'network': {'tenant_id': 'sometenant',
256
'admin_state_up': True,
258
self.assertEqual(db_api.MAX_RETRIES + 1, f.call_count)
153
261
class TestMl2SubnetsV2(test_plugin.TestSubnetsV2,
154
262
Ml2PluginV2TestCase):
217
325
self._validate_behavior_on_bulk_failure(
218
326
res, 'ports', webob.exc.HTTPServerError.code)
328
def test_create_ports_bulk_with_sec_grp(self):
329
ctx = context.get_admin_context()
330
plugin = manager.NeutronManager.get_plugin()
331
with contextlib.nested(
333
mock.patch.object(plugin.notifier,
334
'security_groups_member_updated'),
335
mock.patch.object(plugin.notifier,
336
'security_groups_provider_updated')
337
) as (net, m_upd, p_upd):
339
res = self._create_port_bulk(self.fmt, 3, net['network']['id'],
340
'test', True, context=ctx)
341
ports = self.deserialize(self.fmt, res)
342
used_sg = ports['ports'][0]['security_groups']
343
m_upd.assert_called_once_with(ctx, used_sg)
344
self.assertFalse(p_upd.called)
346
def test_create_ports_bulk_with_sec_grp_member_provider_update(self):
347
ctx = context.get_admin_context()
348
plugin = manager.NeutronManager.get_plugin()
349
with contextlib.nested(
351
mock.patch.object(plugin.notifier,
352
'security_groups_member_updated'),
353
mock.patch.object(plugin.notifier,
354
'security_groups_provider_updated')
355
) as (net, m_upd, p_upd):
357
net_id = net['network']['id']
359
'network_id': net_id,
360
'tenant_id': self._tenant_id
363
'network_id': net_id,
364
'tenant_id': self._tenant_id,
365
'device_owner': constants.DEVICE_OWNER_DHCP
369
res = self._create_bulk_from_list(self.fmt, 'port',
371
ports = self.deserialize(self.fmt, res)
372
used_sg = ports['ports'][0]['security_groups']
373
m_upd.assert_called_once_with(ctx, used_sg)
374
p_upd.assert_called_once_with(ctx)
378
data[0]['device_owner'] = constants.DEVICE_OWNER_DHCP
379
self._create_bulk_from_list(self.fmt, 'port',
381
self.assertFalse(m_upd.called)
382
p_upd.assert_called_once_with(ctx)
384
def test_create_ports_bulk_with_sec_grp_provider_update_ipv6(self):
385
ctx = context.get_admin_context()
386
plugin = manager.NeutronManager.get_plugin()
387
fake_prefix = '2001:db8::/64'
388
fake_gateway = 'fe80::1'
389
with self.network() as net:
390
with contextlib.nested(
391
self.subnet(net, gateway_ip=fake_gateway,
392
cidr=fake_prefix, ip_version=6),
394
plugin.notifier, 'security_groups_member_updated'),
396
plugin.notifier, 'security_groups_provider_updated')
397
) as (snet_v6, m_upd, p_upd):
399
net_id = net['network']['id']
401
'network_id': net_id,
402
'tenant_id': self._tenant_id,
403
'fixed_ips': [{'subnet_id': snet_v6['subnet']['id']}],
404
'device_owner': constants.DEVICE_OWNER_ROUTER_INTF
407
self._create_bulk_from_list(self.fmt, 'port',
409
self.assertFalse(m_upd.called)
410
p_upd.assert_called_once_with(ctx)
220
412
def test_delete_port_no_notify_in_disassociate_floatingips(self):
221
413
ctx = context.get_admin_context()
222
414
plugin = manager.NeutronManager.get_plugin()
223
415
l3plugin = manager.NeutronManager.get_service_plugins().get(
224
416
service_constants.L3_ROUTER_NAT)
225
417
with contextlib.nested(
226
self.port(do_delete=False),
227
419
mock.patch.object(l3plugin, 'disassociate_floatingips'),
228
420
mock.patch.object(l3plugin, 'notify_routers_updated')
229
421
) as (port, disassociate_floatingips, notify):
268
460
self.assertIsNone(l3plugin.disassociate_floatingips(ctx, port_id))
463
class TestMl2PluginOnly(Ml2PluginV2TestCase):
464
"""For testing methods that don't call drivers"""
466
def _test_check_mac_update_allowed(self, vif_type, expect_change=True):
467
plugin = manager.NeutronManager.get_plugin()
468
port = {'mac_address': "fake_mac", 'id': "fake_id"}
470
new_attrs = {"mac_address": "dummy_mac"}
472
new_attrs = {"mac_address": port['mac_address']}
473
binding = mock.Mock()
474
binding.vif_type = vif_type
475
mac_changed = plugin._check_mac_update_allowed(port, new_attrs,
477
self.assertEqual(expect_change, mac_changed)
479
def test_check_mac_update_allowed_if_no_mac_change(self):
480
self._test_check_mac_update_allowed(portbindings.VIF_TYPE_UNBOUND,
483
def test_check_mac_update_allowed_unless_bound(self):
484
with testtools.ExpectedException(exc.PortBound):
485
self._test_check_mac_update_allowed(portbindings.VIF_TYPE_OVS)
271
488
class TestMl2DvrPortsV2(TestMl2PortsV2):
273
490
super(TestMl2DvrPortsV2, self).setUp()
329
545
mock.patch.object(manager.NeutronManager,
330
546
'get_service_plugins',
331
547
return_value=self.service_plugins),
332
self.port(do_delete=False,
333
device_owner='compute:None'),
548
self.port(device_owner='compute:None'),
334
549
mock.patch.object(self.l3plugin, 'dvr_deletens_if_no_port',
335
550
return_value=[ns_to_delete]),
336
mock.patch.object(self.l3plugin, 'remove_router_from_l3_agent',
337
side_effect=l3agentscheduler.RouterNotHostedByL3Agent(
338
router_id=ns_to_delete['router_id'],
339
agent_id=ns_to_delete['agent_id']))
551
mock.patch.object(self.l3plugin, 'remove_router_from_l3_agent')
340
552
) as (get_service_plugin, port, dvr_delns_ifno_port,
341
553
remove_router_from_l3_agent):
1116
1329
plugin.create_port(self.context, mock.MagicMock())
1118
plugin._notify_l3_agent_new_port.assert_called_once_with(
1119
self.context, new_host_port)
1331
kwargs = {'context': self.context, 'port': new_host_port}
1332
self.notify.assert_called_once_with('port', 'after_create',
1121
1335
def test_update_port_rpc_outside_transaction(self):
1122
1336
with contextlib.nested(
1123
1337
mock.patch.object(ml2_plugin.Ml2Plugin, '__init__'),
1124
1338
mock.patch.object(base_plugin.NeutronDbPluginV2, 'update_port'),
1125
mock.patch.object(manager.NeutronManager, 'get_service_plugins'),
1126
) as (init, super_update_port, get_service_plugins):
1339
) as (init, super_update_port):
1127
1340
init.return_value = None
1128
l3plugin = mock.Mock()
1129
l3plugin.supported_extension_aliases = [
1130
constants.L3_DISTRIBUTED_EXT_ALIAS,
1132
get_service_plugins.return_value = {
1133
service_constants.L3_ROUTER_NAT: l3plugin,
1341
new_host_port = mock.Mock()
1342
plugin = self._create_plugin_for_create_update_port(new_host_port)
1344
plugin.update_port(self.context, 'fake_id', mock.MagicMock())
1347
'context': self.context,
1348
'port': new_host_port,
1349
'mac_address_updated': True,
1136
new_host_port = mock.Mock()
1137
plugin = self._create_plugin_for_create_update_port(new_host_port)
1139
plugin.update_port(self.context, 'fake_id', mock.MagicMock())
1141
plugin._notify_l3_agent_new_port.assert_called_once_with(
1142
self.context, new_host_port)
1143
l3plugin.dvr_vmarp_table_update.assert_called_once_with(
1144
self.context, mock.ANY, "add")
1351
self.notify.assert_called_once_with('port', 'after_update',
1146
1354
def test_vmarp_table_update_outside_of_delete_transaction(self):
1147
1355
l3plugin = mock.Mock()