1
# Copyright 2013 VMware, Inc.
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
7
# http://www.apache.org/licenses/LICENSE-2.0
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
18
from oslo.config import cfg
20
from neutron.common import constants as n_consts
21
from neutron.common import exceptions as n_exc
22
from neutron import context
23
from neutron.plugins.vmware.api_client import exception
24
from neutron.plugins.vmware.common import exceptions as p_exc
25
from neutron.plugins.vmware.dbexts import lsn_db
26
from neutron.plugins.vmware.dhcp_meta import constants
27
from neutron.plugins.vmware.dhcp_meta import lsnmanager as lsn_man
28
from neutron.plugins.vmware.dhcp_meta import migration as mig_man
29
from neutron.plugins.vmware.dhcp_meta import nsx
30
from neutron.plugins.vmware.dhcp_meta import rpc
31
from neutron.tests import base
32
from neutron.tests.unit import testlib_api
35
class DhcpMetadataBuilderTestCase(base.BaseTestCase):
38
super(DhcpMetadataBuilderTestCase, self).setUp()
39
self.builder = mig_man.DhcpMetadataBuilder(mock.Mock(), mock.Mock())
40
self.network_id = 'foo_network_id'
41
self.subnet_id = 'foo_subnet_id'
42
self.router_id = 'foo_router_id'
44
def test_dhcp_agent_get_all(self):
46
self.builder.plugin.list_dhcp_agents_hosting_network.return_value = (
48
agents = self.builder.dhcp_agent_get_all(mock.ANY, self.network_id)
49
self.assertEqual(expected, agents)
51
def test_dhcp_port_get_all(self):
53
self.builder.plugin.get_ports.return_value = expected
54
ports = self.builder.dhcp_port_get_all(mock.ANY, self.network_id)
55
self.assertEqual(expected, ports)
57
def test_router_id_get(self):
59
'device_id': self.router_id,
60
'network_id': self.network_id,
61
'fixed_ips': [{'subnet_id': self.subnet_id}]
65
'network_id': self.network_id
67
self.builder.plugin.get_ports.return_value = [port]
68
result = self.builder.router_id_get(context, subnet)
69
self.assertEqual(self.router_id, result)
71
def test_router_id_get_none_subnet(self):
72
self.assertIsNone(self.builder.router_id_get(mock.ANY, None))
74
def test_router_id_get_none_no_router(self):
75
self.builder.plugin.get_ports.return_value = []
76
subnet = {'network_id': self.network_id}
77
self.assertIsNone(self.builder.router_id_get(mock.ANY, subnet))
79
def test_metadata_deallocate(self):
80
self.builder.metadata_deallocate(
81
mock.ANY, self.router_id, self.subnet_id)
82
self.assertTrue(self.builder.plugin.remove_router_interface.call_count)
84
def test_metadata_allocate(self):
85
self.builder.metadata_allocate(
86
mock.ANY, self.router_id, self.subnet_id)
87
self.assertTrue(self.builder.plugin.add_router_interface.call_count)
89
def test_dhcp_deallocate(self):
90
agents = [{'id': 'foo_agent_id'}]
91
ports = [{'id': 'foo_port_id'}]
92
self.builder.dhcp_deallocate(mock.ANY, self.network_id, agents, ports)
94
self.builder.plugin.remove_network_from_dhcp_agent.call_count)
95
self.assertTrue(self.builder.plugin.delete_port.call_count)
97
def _test_dhcp_allocate(self, subnet, expected_notify_count):
98
with mock.patch.object(mig_man.nsx, 'handle_network_dhcp_access') as f:
99
self.builder.dhcp_allocate(mock.ANY, self.network_id, subnet)
100
self.assertTrue(f.call_count)
101
self.assertEqual(expected_notify_count,
102
self.builder.notifier.notify.call_count)
104
def test_dhcp_allocate(self):
105
subnet = {'network_id': self.network_id, 'id': self.subnet_id}
106
self._test_dhcp_allocate(subnet, 2)
108
def test_dhcp_allocate_none_subnet(self):
109
self._test_dhcp_allocate(None, 0)
112
class MigrationManagerTestCase(base.BaseTestCase):
115
super(MigrationManagerTestCase, self).setUp()
116
self.manager = mig_man.MigrationManager(mock.Mock(),
119
self.network_id = 'foo_network_id'
120
self.router_id = 'foo_router_id'
121
self.subnet_id = 'foo_subnet_id'
122
self.mock_builder_p = mock.patch.object(self.manager, 'builder')
123
self.mock_builder = self.mock_builder_p.start()
125
def _test_validate(self, lsn_exists=False, ext_net=False, subnets=None):
126
network = {'router:external': ext_net}
127
self.manager.manager.lsn_exists.return_value = lsn_exists
128
self.manager.plugin.get_network.return_value = network
129
self.manager.plugin.get_subnets.return_value = subnets
130
result = self.manager.validate(mock.ANY, self.network_id)
132
self.assertEqual(subnets[0], result)
134
self.assertIsNone(result)
136
def test_validate_no_subnets(self):
137
self._test_validate(subnets=[])
139
def test_validate_with_one_subnet(self):
140
self._test_validate(subnets=[{'cidr': '0.0.0.0/0'}])
142
def test_validate_raise_conflict_many_subnets(self):
143
self.assertRaises(p_exc.LsnMigrationConflict,
145
subnets=[{'id': 'sub1'}, {'id': 'sub2'}])
147
def test_validate_raise_conflict_lsn_exists(self):
148
self.assertRaises(p_exc.LsnMigrationConflict,
152
def test_validate_raise_badrequest_external_net(self):
153
self.assertRaises(n_exc.BadRequest,
157
def test_validate_raise_badrequest_metadata_net(self):
158
self.assertRaises(n_exc.BadRequest,
161
subnets=[{'cidr': rpc.METADATA_SUBNET_CIDR}])
163
def _test_migrate(self, router, subnet, expected_calls):
164
self.mock_builder.router_id_get.return_value = router
165
self.manager.migrate(mock.ANY, self.network_id, subnet)
166
# testing the exact the order of calls is important
167
self.assertEqual(expected_calls, self.mock_builder.mock_calls)
169
def test_migrate(self):
171
'id': self.subnet_id,
172
'network_id': self.network_id
175
mock.call.router_id_get(mock.ANY, subnet),
176
mock.call.metadata_deallocate(
177
mock.ANY, self.router_id, self.subnet_id),
178
mock.call.dhcp_agent_get_all(mock.ANY, self.network_id),
179
mock.call.dhcp_port_get_all(mock.ANY, self.network_id),
180
mock.call.dhcp_deallocate(
181
mock.ANY, self.network_id, mock.ANY, mock.ANY),
182
mock.call.dhcp_allocate(mock.ANY, self.network_id, subnet),
183
mock.call.metadata_allocate(
184
mock.ANY, self.router_id, self.subnet_id)
186
self._test_migrate(self.router_id, subnet, call_sequence)
188
def test_migrate_no_router_uplink(self):
190
'id': self.subnet_id,
191
'network_id': self.network_id
194
mock.call.router_id_get(mock.ANY, subnet),
195
mock.call.dhcp_agent_get_all(mock.ANY, self.network_id),
196
mock.call.dhcp_port_get_all(mock.ANY, self.network_id),
197
mock.call.dhcp_deallocate(
198
mock.ANY, self.network_id, mock.ANY, mock.ANY),
199
mock.call.dhcp_allocate(mock.ANY, self.network_id, subnet),
201
self._test_migrate(None, subnet, call_sequence)
203
def test_migrate_no_subnet(self):
205
mock.call.router_id_get(mock.ANY, None),
206
mock.call.dhcp_allocate(mock.ANY, self.network_id, None),
208
self._test_migrate(None, None, call_sequence)
210
def _test_report(self, lsn_attrs, expected):
211
self.manager.manager.lsn_port_get.return_value = lsn_attrs
212
report = self.manager.report(mock.ANY, self.network_id, self.subnet_id)
213
self.assertEqual(expected, report)
215
def test_report_for_lsn(self):
216
self._test_report(('foo_lsn_id', 'foo_lsn_port_id'),
217
{'ports': ['foo_lsn_port_id'],
218
'services': ['foo_lsn_id'], 'type': 'lsn'})
220
def test_report_for_lsn_without_lsn_port(self):
221
self._test_report(('foo_lsn_id', None),
223
'services': ['foo_lsn_id'], 'type': 'lsn'})
225
def _test_report_for_lsn_without_subnet(self, validated_subnet):
226
with mock.patch.object(self.manager.plugin, 'get_subnets',
227
return_value=validated_subnet):
228
self.manager.manager.lsn_port_get.return_value = (
229
('foo_lsn_id', 'foo_lsn_port_id'))
230
report = self.manager.report(context, self.network_id)
232
'ports': ['foo_lsn_port_id'] if validated_subnet else [],
233
'services': ['foo_lsn_id'], 'type': 'lsn'
235
self.assertEqual(expected, report)
237
def test_report_for_lsn_without_subnet_subnet_found(self):
238
self._test_report_for_lsn_without_subnet([{'id': self.subnet_id}])
240
def test_report_for_lsn_without_subnet_subnet_not_found(self):
241
self.manager.manager.lsn_get.return_value = 'foo_lsn_id'
242
self._test_report_for_lsn_without_subnet(None)
244
def test_report_for_dhcp_agent(self):
245
self.manager.manager.lsn_port_get.return_value = (None, None)
246
self.mock_builder.dhcp_agent_get_all.return_value = (
247
[{'id': 'foo_agent_id'}])
248
self.mock_builder.dhcp_port_get_all.return_value = (
249
[{'id': 'foo_dhcp_port_id'}])
250
result = self.manager.report(mock.ANY, self.network_id, self.subnet_id)
252
'ports': ['foo_dhcp_port_id'],
253
'services': ['foo_agent_id'],
256
self.assertEqual(expected, result)
259
class LsnManagerTestCase(base.BaseTestCase):
262
super(LsnManagerTestCase, self).setUp()
263
self.net_id = 'foo_network_id'
264
self.sub_id = 'foo_subnet_id'
265
self.port_id = 'foo_port_id'
266
self.lsn_id = 'foo_lsn_id'
267
self.mac = 'aa:bb:cc:dd:ee:ff'
268
self.switch_id = 'foo_switch_id'
269
self.lsn_port_id = 'foo_lsn_port_id'
270
self.tenant_id = 'foo_tenant_id'
271
self.manager = lsn_man.LsnManager(mock.Mock())
272
self.context = context.get_admin_context()
273
self.mock_lsn_api_p = mock.patch.object(lsn_man, 'lsn_api')
274
self.mock_lsn_api = self.mock_lsn_api_p.start()
275
self.mock_nsx_utils_p = mock.patch.object(lsn_man, 'nsx_utils')
276
self.mock_nsx_utils = self.mock_nsx_utils_p.start()
277
nsx.register_dhcp_opts(cfg)
278
nsx.register_metadata_opts(cfg)
280
def test_lsn_get(self):
281
self.mock_lsn_api.lsn_for_network_get.return_value = self.lsn_id
282
expected = self.manager.lsn_get(mock.ANY, self.net_id)
283
self.mock_lsn_api.lsn_for_network_get.assert_called_once_with(
284
mock.ANY, self.net_id)
285
self.assertEqual(expected, self.lsn_id)
287
def _test_lsn_get_raise_not_found_with_exc(self, exc):
288
self.mock_lsn_api.lsn_for_network_get.side_effect = exc
289
self.assertRaises(p_exc.LsnNotFound,
290
self.manager.lsn_get,
291
mock.ANY, self.net_id)
292
self.mock_lsn_api.lsn_for_network_get.assert_called_once_with(
293
mock.ANY, self.net_id)
295
def test_lsn_get_raise_not_found_with_not_found(self):
296
self._test_lsn_get_raise_not_found_with_exc(n_exc.NotFound)
298
def test_lsn_get_raise_not_found_with_api_error(self):
299
self._test_lsn_get_raise_not_found_with_exc(exception.NsxApiException)
301
def _test_lsn_get_silent_raise_with_exc(self, exc):
302
self.mock_lsn_api.lsn_for_network_get.side_effect = exc
303
expected = self.manager.lsn_get(
304
mock.ANY, self.net_id, raise_on_err=False)
305
self.mock_lsn_api.lsn_for_network_get.assert_called_once_with(
306
mock.ANY, self.net_id)
307
self.assertIsNone(expected)
309
def test_lsn_get_silent_raise_with_not_found(self):
310
self._test_lsn_get_silent_raise_with_exc(n_exc.NotFound)
312
def test_lsn_get_silent_raise_with_api_error(self):
313
self._test_lsn_get_silent_raise_with_exc(exception.NsxApiException)
315
def test_lsn_create(self):
316
self.mock_lsn_api.lsn_for_network_create.return_value = self.lsn_id
317
self.manager.lsn_create(mock.ANY, self.net_id)
318
self.mock_lsn_api.lsn_for_network_create.assert_called_once_with(
319
mock.ANY, self.net_id)
321
def test_lsn_create_raise_api_error(self):
322
self.mock_lsn_api.lsn_for_network_create.side_effect = (
323
exception.NsxApiException)
324
self.assertRaises(p_exc.NsxPluginException,
325
self.manager.lsn_create,
326
mock.ANY, self.net_id)
327
self.mock_lsn_api.lsn_for_network_create.assert_called_once_with(
328
mock.ANY, self.net_id)
330
def test_lsn_delete(self):
331
self.manager.lsn_delete(mock.ANY, self.lsn_id)
332
self.mock_lsn_api.lsn_delete.assert_called_once_with(
333
mock.ANY, self.lsn_id)
335
def _test_lsn_delete_with_exc(self, exc):
336
self.mock_lsn_api.lsn_delete.side_effect = exc
337
self.manager.lsn_delete(mock.ANY, self.lsn_id)
338
self.mock_lsn_api.lsn_delete.assert_called_once_with(
339
mock.ANY, self.lsn_id)
341
def test_lsn_delete_with_not_found(self):
342
self._test_lsn_delete_with_exc(n_exc.NotFound)
344
def test_lsn_delete_api_exception(self):
345
self._test_lsn_delete_with_exc(exception.NsxApiException)
347
def test_lsn_delete_by_network(self):
348
self.mock_lsn_api.lsn_for_network_get.return_value = self.lsn_id
349
with mock.patch.object(self.manager, 'lsn_delete') as f:
350
self.manager.lsn_delete_by_network(mock.ANY, self.net_id)
351
self.mock_lsn_api.lsn_for_network_get.assert_called_once_with(
352
mock.ANY, self.net_id)
353
f.assert_called_once_with(mock.ANY, self.lsn_id)
355
def _test_lsn_delete_by_network_with_exc(self, exc):
356
self.mock_lsn_api.lsn_for_network_get.side_effect = exc
357
with mock.patch.object(lsn_man.LOG, 'warn') as l:
358
self.manager.lsn_delete_by_network(mock.ANY, self.net_id)
359
self.assertEqual(1, l.call_count)
361
def test_lsn_delete_by_network_with_not_found(self):
362
self._test_lsn_delete_by_network_with_exc(n_exc.NotFound)
364
def test_lsn_delete_by_network_with_not_api_error(self):
365
self._test_lsn_delete_by_network_with_exc(exception.NsxApiException)
367
def test_lsn_port_get(self):
368
self.mock_lsn_api.lsn_port_by_subnet_get.return_value = (
370
with mock.patch.object(
371
self.manager, 'lsn_get', return_value=self.lsn_id):
372
expected = self.manager.lsn_port_get(
373
mock.ANY, self.net_id, self.sub_id)
374
self.assertEqual(expected, (self.lsn_id, self.lsn_port_id))
376
def test_lsn_port_get_lsn_not_found_on_raise(self):
377
with mock.patch.object(
378
self.manager, 'lsn_get',
379
side_effect=p_exc.LsnNotFound(entity='network',
380
entity_id=self.net_id)):
381
self.assertRaises(p_exc.LsnNotFound,
382
self.manager.lsn_port_get,
383
mock.ANY, self.net_id, self.sub_id)
385
def test_lsn_port_get_lsn_not_found_silent_raise(self):
386
with mock.patch.object(self.manager, 'lsn_get', return_value=None):
387
expected = self.manager.lsn_port_get(
388
mock.ANY, self.net_id, self.sub_id, raise_on_err=False)
389
self.assertEqual(expected, (None, None))
391
def test_lsn_port_get_port_not_found_on_raise(self):
392
self.mock_lsn_api.lsn_port_by_subnet_get.side_effect = n_exc.NotFound
393
with mock.patch.object(
394
self.manager, 'lsn_get', return_value=self.lsn_id):
395
self.assertRaises(p_exc.LsnPortNotFound,
396
self.manager.lsn_port_get,
397
mock.ANY, self.net_id, self.sub_id)
399
def test_lsn_port_get_port_not_found_silent_raise(self):
400
self.mock_lsn_api.lsn_port_by_subnet_get.side_effect = n_exc.NotFound
401
with mock.patch.object(
402
self.manager, 'lsn_get', return_value=self.lsn_id):
403
expected = self.manager.lsn_port_get(
404
mock.ANY, self.net_id, self.sub_id, raise_on_err=False)
405
self.assertEqual(expected, (self.lsn_id, None))
407
def test_lsn_port_create(self):
408
self.mock_lsn_api.lsn_port_create.return_value = self.lsn_port_id
409
expected = self.manager.lsn_port_create(mock.ANY, mock.ANY, mock.ANY)
410
self.assertEqual(expected, self.lsn_port_id)
412
def _test_lsn_port_create_with_exc(self, exc, expected):
413
self.mock_lsn_api.lsn_port_create.side_effect = exc
414
self.assertRaises(expected,
415
self.manager.lsn_port_create,
416
mock.ANY, mock.ANY, mock.ANY)
418
def test_lsn_port_create_with_not_found(self):
419
self._test_lsn_port_create_with_exc(n_exc.NotFound, p_exc.LsnNotFound)
421
def test_lsn_port_create_api_exception(self):
422
self._test_lsn_port_create_with_exc(exception.NsxApiException,
423
p_exc.NsxPluginException)
425
def test_lsn_port_delete(self):
426
self.manager.lsn_port_delete(mock.ANY, mock.ANY, mock.ANY)
427
self.assertEqual(1, self.mock_lsn_api.lsn_port_delete.call_count)
429
def _test_lsn_port_delete_with_exc(self, exc):
430
self.mock_lsn_api.lsn_port_delete.side_effect = exc
431
with mock.patch.object(lsn_man.LOG, 'warn') as l:
432
self.manager.lsn_port_delete(mock.ANY, mock.ANY, mock.ANY)
433
self.assertEqual(1, self.mock_lsn_api.lsn_port_delete.call_count)
434
self.assertEqual(1, l.call_count)
436
def test_lsn_port_delete_with_not_found(self):
437
self._test_lsn_port_delete_with_exc(n_exc.NotFound)
439
def test_lsn_port_delete_api_exception(self):
440
self._test_lsn_port_delete_with_exc(exception.NsxApiException)
442
def _test_lsn_port_dhcp_setup(self, ret_val, sub):
443
self.mock_nsx_utils.get_nsx_switch_ids.return_value = [self.switch_id]
444
self.mock_lsn_api.lsn_port_create.return_value = self.lsn_port_id
445
with mock.patch.object(
446
self.manager, 'lsn_get', return_value=self.lsn_id):
447
with mock.patch.object(lsn_man.switch_api,
448
'get_port_by_neutron_tag'):
449
expected = self.manager.lsn_port_dhcp_setup(
450
mock.Mock(), mock.ANY, mock.ANY,
451
mock.ANY, subnet_config=sub)
453
1, self.mock_lsn_api.lsn_port_create.call_count)
455
1, self.mock_lsn_api.lsn_port_plug_network.call_count)
456
self.assertEqual(expected, ret_val)
458
def test_lsn_port_dhcp_setup(self):
459
self._test_lsn_port_dhcp_setup((self.lsn_id, self.lsn_port_id), None)
461
def test_lsn_port_dhcp_setup_with_config(self):
462
with mock.patch.object(self.manager, 'lsn_port_dhcp_configure') as f:
463
self._test_lsn_port_dhcp_setup(None, mock.ANY)
464
self.assertEqual(1, f.call_count)
466
def test_lsn_port_dhcp_setup_with_not_found(self):
467
self.mock_nsx_utils.get_nsx_switch_ids.return_value = [self.switch_id]
468
with mock.patch.object(lsn_man.switch_api,
469
'get_port_by_neutron_tag') as f:
470
f.side_effect = n_exc.NotFound
471
self.assertRaises(p_exc.PortConfigurationError,
472
self.manager.lsn_port_dhcp_setup,
473
mock.Mock(), mock.ANY, mock.ANY, mock.ANY)
475
def test_lsn_port_dhcp_setup_with_conflict(self):
476
self.mock_lsn_api.lsn_port_plug_network.side_effect = (
477
p_exc.LsnConfigurationConflict(lsn_id=self.lsn_id))
478
self.mock_nsx_utils.get_nsx_switch_ids.return_value = [self.switch_id]
479
with mock.patch.object(lsn_man.switch_api, 'get_port_by_neutron_tag'):
480
with mock.patch.object(self.manager, 'lsn_port_delete') as g:
481
self.assertRaises(p_exc.PortConfigurationError,
482
self.manager.lsn_port_dhcp_setup,
483
mock.Mock(), mock.ANY, mock.ANY, mock.ANY)
484
self.assertEqual(1, g.call_count)
486
def _test_lsn_port_dhcp_configure_with_subnet(
487
self, expected, dns=None, gw=None, routes=None):
490
'dns_nameservers': dns or [],
492
'host_routes': routes
494
self.manager.lsn_port_dhcp_configure(mock.ANY, self.lsn_id,
495
self.lsn_port_id, subnet)
496
self.mock_lsn_api.lsn_port_dhcp_configure.assert_called_once_with(
497
mock.ANY, self.lsn_id, self.lsn_port_id, subnet['enable_dhcp'],
500
def test_lsn_port_dhcp_configure(self):
502
'routers': '127.0.0.1',
503
'default_lease_time': cfg.CONF.NSX_DHCP.default_lease_time,
504
'domain_name': cfg.CONF.NSX_DHCP.domain_name
506
self._test_lsn_port_dhcp_configure_with_subnet(
507
expected, dns=[], gw='127.0.0.1', routes=[])
509
def test_lsn_port_dhcp_configure_gatewayless(self):
511
'default_lease_time': cfg.CONF.NSX_DHCP.default_lease_time,
512
'domain_name': cfg.CONF.NSX_DHCP.domain_name
514
self._test_lsn_port_dhcp_configure_with_subnet(expected, gw=None)
516
def test_lsn_port_dhcp_configure_with_extra_dns_servers(self):
518
'default_lease_time': cfg.CONF.NSX_DHCP.default_lease_time,
519
'domain_name_servers': '8.8.8.8,9.9.9.9',
520
'domain_name': cfg.CONF.NSX_DHCP.domain_name
522
self._test_lsn_port_dhcp_configure_with_subnet(
523
expected, dns=['8.8.8.8', '9.9.9.9'])
525
def test_lsn_port_dhcp_configure_with_host_routes(self):
527
'default_lease_time': cfg.CONF.NSX_DHCP.default_lease_time,
528
'domain_name': cfg.CONF.NSX_DHCP.domain_name,
529
'classless_static_routes': '8.8.8.8,9.9.9.9'
531
self._test_lsn_port_dhcp_configure_with_subnet(
532
expected, routes=['8.8.8.8', '9.9.9.9'])
534
def _test_lsn_metadata_configure(self, is_enabled):
535
with mock.patch.object(self.manager, 'lsn_port_dispose') as f:
536
self.manager.plugin.get_subnet.return_value = (
537
{'network_id': self.net_id})
538
self.manager.lsn_metadata_configure(mock.ANY,
539
self.sub_id, is_enabled)
541
'metadata_server_port': 8775,
542
'metadata_server_ip': '127.0.0.1',
543
'metadata_proxy_shared_secret': ''
545
self.mock_lsn_api.lsn_metadata_configure.assert_called_once_with(
546
mock.ANY, mock.ANY, is_enabled, expected)
549
1, self.mock_lsn_api.lsn_port_by_subnet_get.call_count)
551
self.assertEqual(1, f.call_count)
553
def test_lsn_metadata_configure_enabled(self):
554
self._test_lsn_metadata_configure(True)
556
def test_lsn_metadata_configure_disabled(self):
557
self._test_lsn_metadata_configure(False)
559
def test_lsn_metadata_configure_not_found(self):
560
self.mock_lsn_api.lsn_metadata_configure.side_effect = (
561
p_exc.LsnNotFound(entity='lsn', entity_id=self.lsn_id))
562
self.manager.plugin.get_subnet.return_value = (
563
{'network_id': self.net_id})
564
self.assertRaises(p_exc.NsxPluginException,
565
self.manager.lsn_metadata_configure,
566
mock.ANY, self.sub_id, True)
568
def test_lsn_port_metadata_setup(self):
572
'network_id': self.net_id,
573
'tenant_id': self.tenant_id
576
'subnet_id': subnet['id'],
577
'ip_address': subnet['cidr'],
578
'mac_address': constants.METADATA_MAC
580
self.mock_nsx_utils.get_nsx_switch_ids.return_value = [self.switch_id]
581
with mock.patch.object(lsn_man.switch_api, 'create_lport') as f:
582
with mock.patch.object(self.manager, 'lsn_port_create') as g:
583
f.return_value = {'uuid': self.port_id}
584
self.manager.lsn_port_metadata_setup(
585
self.context, self.lsn_id, subnet)
586
(self.mock_lsn_api.lsn_port_plug_network.
587
assert_called_once_with(mock.ANY, self.lsn_id,
588
mock.ANY, self.port_id))
589
g.assert_called_once_with(
590
self.context, self.lsn_id, expected_data)
592
def test_lsn_port_metadata_setup_raise_not_found(self):
596
'network_id': self.net_id,
597
'tenant_id': self.tenant_id
599
self.mock_nsx_utils.get_nsx_switch_ids.return_value = [self.switch_id]
600
with mock.patch.object(lsn_man.switch_api, 'create_lport') as f:
601
f.side_effect = n_exc.NotFound
602
self.assertRaises(p_exc.PortConfigurationError,
603
self.manager.lsn_port_metadata_setup,
604
mock.Mock(), self.lsn_id, subnet)
606
def test_lsn_port_metadata_setup_raise_conflict(self):
610
'network_id': self.net_id,
611
'tenant_id': self.tenant_id
613
self.mock_nsx_utils.get_nsx_switch_ids.return_value = [self.switch_id]
614
with mock.patch.object(lsn_man.switch_api, 'create_lport') as f:
615
with mock.patch.object(lsn_man.switch_api, 'delete_port') as g:
616
f.return_value = {'uuid': self.port_id}
617
self.mock_lsn_api.lsn_port_plug_network.side_effect = (
618
p_exc.LsnConfigurationConflict(lsn_id=self.lsn_id))
619
self.assertRaises(p_exc.PortConfigurationError,
620
self.manager.lsn_port_metadata_setup,
621
mock.Mock(), self.lsn_id, subnet)
623
self.mock_lsn_api.lsn_port_delete.call_count)
624
self.assertEqual(1, g.call_count)
626
def _test_lsn_port_dispose_with_values(self, lsn_id, lsn_port_id, count):
627
with mock.patch.object(self.manager,
628
'lsn_port_get_by_mac',
629
return_value=(lsn_id, lsn_port_id)):
630
self.manager.lsn_port_dispose(mock.ANY, self.net_id, self.mac)
631
self.assertEqual(count,
632
self.mock_lsn_api.lsn_port_delete.call_count)
634
def test_lsn_port_dispose(self):
635
self._test_lsn_port_dispose_with_values(
636
self.lsn_id, self.lsn_port_id, 1)
638
def test_lsn_port_dispose_meta_mac(self):
639
self.mac = constants.METADATA_MAC
640
with mock.patch.object(lsn_man.switch_api,
641
'get_port_by_neutron_tag') as f:
642
with mock.patch.object(lsn_man.switch_api, 'delete_port') as g:
643
f.return_value = {'uuid': self.port_id}
644
self._test_lsn_port_dispose_with_values(
645
self.lsn_id, self.lsn_port_id, 1)
646
f.assert_called_once_with(
647
mock.ANY, self.net_id, constants.METADATA_PORT_ID)
648
g.assert_called_once_with(mock.ANY, self.net_id, self.port_id)
650
def test_lsn_port_dispose_lsn_not_found(self):
651
self._test_lsn_port_dispose_with_values(None, None, 0)
653
def test_lsn_port_dispose_lsn_port_not_found(self):
654
self._test_lsn_port_dispose_with_values(self.lsn_id, None, 0)
656
def test_lsn_port_dispose_api_error(self):
657
self.mock_lsn_api.lsn_port_delete.side_effect = (
658
exception.NsxApiException)
659
with mock.patch.object(lsn_man.LOG, 'warn') as l:
660
self.manager.lsn_port_dispose(mock.ANY, self.net_id, self.mac)
661
self.assertEqual(1, l.call_count)
663
def test_lsn_port_host_conf(self):
664
with mock.patch.object(self.manager,
666
return_value=(self.lsn_id, self.lsn_port_id)):
668
self.manager._lsn_port_host_conf(mock.ANY, self.net_id,
669
self.sub_id, mock.ANY, f)
670
self.assertEqual(1, f.call_count)
672
def test_lsn_port_host_conf_lsn_port_not_found(self):
673
with mock.patch.object(
674
self.manager, 'lsn_port_get', return_value=(None, None)) as f:
675
self.manager._lsn_port_host_conf(
676
mock.ANY, self.net_id, self.sub_id, mock.ANY, mock.Mock())
677
self.assertEqual(1, f.call_count)
679
def _test_lsn_port_update(self, dhcp=None, meta=None):
680
self.manager.lsn_port_update(
681
mock.ANY, self.net_id, self.sub_id, dhcp, meta)
682
count = 1 if dhcp else 0
683
count = count + 1 if meta else count
684
self.assertEqual(count, (self.mock_lsn_api.
685
lsn_port_host_entries_update.call_count))
687
def test_lsn_port_update(self):
688
self._test_lsn_port_update()
690
def test_lsn_port_update_dhcp_meta(self):
691
self._test_lsn_port_update(mock.ANY, mock.ANY)
693
def test_lsn_port_update_dhcp_and_nometa(self):
694
self._test_lsn_port_update(mock.ANY, None)
696
def test_lsn_port_update_nodhcp_and_nmeta(self):
697
self._test_lsn_port_update(None, mock.ANY)
699
def test_lsn_port_update_raise_error(self):
700
self.mock_lsn_api.lsn_port_host_entries_update.side_effect = (
701
exception.NsxApiException)
702
self.assertRaises(p_exc.PortConfigurationError,
703
self.manager.lsn_port_update,
704
mock.ANY, mock.ANY, mock.ANY, mock.ANY)
707
class PersistentLsnManagerTestCase(testlib_api.SqlTestCase):
710
super(PersistentLsnManagerTestCase, self).setUp()
711
self.net_id = 'foo_network_id'
712
self.sub_id = 'foo_subnet_id'
713
self.port_id = 'foo_port_id'
714
self.lsn_id = 'foo_lsn_id'
715
self.mac = 'aa:bb:cc:dd:ee:ff'
716
self.lsn_port_id = 'foo_lsn_port_id'
717
self.tenant_id = 'foo_tenant_id'
718
nsx.register_dhcp_opts(cfg)
719
nsx.register_metadata_opts(cfg)
720
lsn_man.register_lsn_opts(cfg)
721
self.manager = lsn_man.PersistentLsnManager(mock.Mock())
722
self.context = context.get_admin_context()
723
self.mock_lsn_api_p = mock.patch.object(lsn_man, 'lsn_api')
724
self.mock_lsn_api = self.mock_lsn_api_p.start()
726
def test_lsn_get(self):
727
lsn_db.lsn_add(self.context, self.net_id, self.lsn_id)
728
result = self.manager.lsn_get(self.context, self.net_id)
729
self.assertEqual(self.lsn_id, result)
731
def test_lsn_get_raise_not_found(self):
732
self.assertRaises(p_exc.LsnNotFound,
733
self.manager.lsn_get, self.context, self.net_id)
735
def test_lsn_get_silent_not_found(self):
736
result = self.manager.lsn_get(
737
self.context, self.net_id, raise_on_err=False)
738
self.assertIsNone(result)
740
def test_lsn_get_sync_on_missing(self):
741
cfg.CONF.set_override('sync_on_missing_data', True, 'NSX_LSN')
742
self.manager = lsn_man.PersistentLsnManager(mock.Mock())
743
with mock.patch.object(self.manager, 'lsn_save') as f:
744
self.manager.lsn_get(self.context, self.net_id, raise_on_err=True)
745
self.assertTrue(self.mock_lsn_api.lsn_for_network_get.call_count)
746
self.assertTrue(f.call_count)
748
def test_lsn_save(self):
749
self.manager.lsn_save(self.context, self.net_id, self.lsn_id)
750
result = self.manager.lsn_get(self.context, self.net_id)
751
self.assertEqual(self.lsn_id, result)
753
def test_lsn_create(self):
754
self.mock_lsn_api.lsn_for_network_create.return_value = self.lsn_id
755
with mock.patch.object(self.manager, 'lsn_save') as f:
756
result = self.manager.lsn_create(self.context, self.net_id)
758
self.mock_lsn_api.lsn_for_network_create.call_count)
759
self.assertTrue(f.call_count)
760
self.assertEqual(self.lsn_id, result)
762
def test_lsn_create_failure(self):
763
with mock.patch.object(
764
self.manager, 'lsn_save',
765
side_effect=p_exc.NsxPluginException(err_msg='')):
766
self.assertRaises(p_exc.NsxPluginException,
767
self.manager.lsn_create,
768
self.context, self.net_id)
769
self.assertTrue(self.mock_lsn_api.lsn_delete.call_count)
771
def test_lsn_delete(self):
772
self.mock_lsn_api.lsn_for_network_create.return_value = self.lsn_id
773
self.manager.lsn_create(self.context, self.net_id)
774
self.manager.lsn_delete(self.context, self.lsn_id)
775
self.assertIsNone(self.manager.lsn_get(
776
self.context, self.net_id, raise_on_err=False))
778
def test_lsn_delete_not_existent(self):
779
self.manager.lsn_delete(self.context, self.lsn_id)
780
self.assertTrue(self.mock_lsn_api.lsn_delete.call_count)
782
def test_lsn_port_get(self):
783
lsn_db.lsn_add(self.context, self.net_id, self.lsn_id)
784
lsn_db.lsn_port_add_for_lsn(self.context, self.lsn_port_id,
785
self.sub_id, self.mac, self.lsn_id)
786
res = self.manager.lsn_port_get(self.context, self.net_id, self.sub_id)
787
self.assertEqual((self.lsn_id, self.lsn_port_id), res)
789
def test_lsn_port_get_raise_not_found(self):
790
self.assertRaises(p_exc.LsnPortNotFound,
791
self.manager.lsn_port_get,
792
self.context, self.net_id, self.sub_id)
794
def test_lsn_port_get_silent_not_found(self):
795
result = self.manager.lsn_port_get(
796
self.context, self.net_id, self.sub_id, raise_on_err=False)
797
self.assertEqual((None, None), result)
799
def test_lsn_port_get_sync_on_missing(self):
801
cfg.CONF.set_override('sync_on_missing_data', True, 'NSX_LSN')
802
self.manager = lsn_man.PersistentLsnManager(mock.Mock())
803
self.mock_lsn_api.lsn_for_network_get.return_value = self.lsn_id
804
self.mock_lsn_api.lsn_port_by_subnet_get.return_value = (
805
self.lsn_id, self.lsn_port_id)
806
with mock.patch.object(self.manager, 'lsn_save') as f:
807
with mock.patch.object(self.manager, 'lsn_port_save') as g:
808
self.manager.lsn_port_get(
809
self.context, self.net_id, self.sub_id)
811
self.mock_lsn_api.lsn_port_by_subnet_get.call_count)
813
self.mock_lsn_api.lsn_port_info_get.call_count)
814
self.assertTrue(f.call_count)
815
self.assertTrue(g.call_count)
817
def test_lsn_port_get_by_mac(self):
818
lsn_db.lsn_add(self.context, self.net_id, self.lsn_id)
819
lsn_db.lsn_port_add_for_lsn(self.context, self.lsn_port_id,
820
self.sub_id, self.mac, self.lsn_id)
821
res = self.manager.lsn_port_get_by_mac(
822
self.context, self.net_id, self.mac)
823
self.assertEqual((self.lsn_id, self.lsn_port_id), res)
825
def test_lsn_port_get_by_mac_raise_not_found(self):
826
self.assertRaises(p_exc.LsnPortNotFound,
827
self.manager.lsn_port_get_by_mac,
828
self.context, self.net_id, self.sub_id)
830
def test_lsn_port_get_by_mac_silent_not_found(self):
831
result = self.manager.lsn_port_get_by_mac(
832
self.context, self.net_id, self.sub_id, raise_on_err=False)
833
self.assertEqual((None, None), result)
835
def test_lsn_port_create(self):
836
lsn_db.lsn_add(self.context, self.net_id, self.lsn_id)
837
self.mock_lsn_api.lsn_port_create.return_value = self.lsn_port_id
838
subnet = {'subnet_id': self.sub_id, 'mac_address': self.mac}
839
with mock.patch.object(self.manager, 'lsn_port_save') as f:
840
result = self.manager.lsn_port_create(
841
self.context, self.net_id, subnet)
843
self.mock_lsn_api.lsn_port_create.call_count)
844
self.assertTrue(f.call_count)
845
self.assertEqual(self.lsn_port_id, result)
847
def test_lsn_port_create_failure(self):
848
subnet = {'subnet_id': self.sub_id, 'mac_address': self.mac}
849
with mock.patch.object(
850
self.manager, 'lsn_port_save',
851
side_effect=p_exc.NsxPluginException(err_msg='')):
852
self.assertRaises(p_exc.NsxPluginException,
853
self.manager.lsn_port_create,
854
self.context, self.net_id, subnet)
855
self.assertTrue(self.mock_lsn_api.lsn_port_delete.call_count)
857
def test_lsn_port_delete(self):
858
lsn_db.lsn_add(self.context, self.net_id, self.lsn_id)
859
lsn_db.lsn_port_add_for_lsn(self.context, self.lsn_port_id,
860
self.sub_id, self.mac, self.lsn_id)
861
self.manager.lsn_port_delete(
862
self.context, self.lsn_id, self.lsn_port_id)
863
self.assertEqual((None, None), self.manager.lsn_port_get(
864
self.context, self.lsn_id, self.sub_id, raise_on_err=False))
866
def test_lsn_port_delete_not_existent(self):
867
self.manager.lsn_port_delete(
868
self.context, self.lsn_id, self.lsn_port_id)
869
self.assertTrue(self.mock_lsn_api.lsn_port_delete.call_count)
871
def test_lsn_port_save(self):
872
self.manager.lsn_save(self.context, self.net_id, self.lsn_id)
873
self.manager.lsn_port_save(self.context, self.lsn_port_id,
874
self.sub_id, self.mac, self.lsn_id)
875
result = self.manager.lsn_port_get(
876
self.context, self.net_id, self.sub_id, raise_on_err=False)
877
self.assertEqual((self.lsn_id, self.lsn_port_id), result)
880
class DhcpAgentNotifyAPITestCase(base.BaseTestCase):
883
super(DhcpAgentNotifyAPITestCase, self).setUp()
884
self.notifier = nsx.DhcpAgentNotifyAPI(mock.Mock(), mock.Mock())
885
self.plugin = self.notifier.plugin
886
self.lsn_manager = self.notifier.lsn_manager
888
def _test_notify_port_update(
889
self, ports, expected_count, expected_args=None):
892
'network_id': 'foo_network_id',
893
'fixed_ips': [{'subnet_id': 'foo_subnet_id'}]
895
self.notifier.plugin.get_ports.return_value = ports
896
self.notifier.notify(mock.ANY, {'port': port}, 'port.update.end')
897
self.lsn_manager.lsn_port_update.assert_has_calls(expected_args)
899
def test_notify_ports_update_no_ports(self):
900
self._test_notify_port_update(None, 0, [])
901
self._test_notify_port_update([], 0, [])
903
def test_notify_ports_update_one_port(self):
905
'fixed_ips': [{'subnet_id': 'foo_subnet_id',
906
'ip_address': '1.2.3.4'}],
907
'device_id': 'foo_device_id',
908
'device_owner': 'foo_device_owner',
909
'mac_address': 'fa:16:3e:da:1d:46'
911
call_args = mock.call(
912
mock.ANY, 'foo_network_id', 'foo_subnet_id',
913
dhcp=[{'ip_address': '1.2.3.4',
914
'mac_address': 'fa:16:3e:da:1d:46'}],
915
meta=[{'instance_id': 'foo_device_id',
916
'ip_address': '1.2.3.4'}])
917
self._test_notify_port_update(ports, 1, call_args)
919
def test_notify_ports_update_ports_with_empty_device_id(self):
921
'fixed_ips': [{'subnet_id': 'foo_subnet_id',
922
'ip_address': '1.2.3.4'}],
924
'device_owner': 'foo_device_owner',
925
'mac_address': 'fa:16:3e:da:1d:46'
927
call_args = mock.call(
928
mock.ANY, 'foo_network_id', 'foo_subnet_id',
929
dhcp=[{'ip_address': '1.2.3.4',
930
'mac_address': 'fa:16:3e:da:1d:46'}],
933
self._test_notify_port_update(ports, 1, call_args)
935
def test_notify_ports_update_ports_with_no_fixed_ips(self):
938
'device_id': 'foo_device_id',
939
'device_owner': 'foo_device_owner',
940
'mac_address': 'fa:16:3e:da:1d:46'
942
call_args = mock.call(
943
mock.ANY, 'foo_network_id', 'foo_subnet_id', dhcp=[], meta=[])
944
self._test_notify_port_update(ports, 1, call_args)
946
def test_notify_ports_update_ports_with_no_fixed_ips_and_no_device(self):
950
'device_owner': 'foo_device_owner',
951
'mac_address': 'fa:16:3e:da:1d:46'
953
call_args = mock.call(
954
mock.ANY, 'foo_network_id', 'foo_subnet_id', dhcp=[], meta=[])
955
self._test_notify_port_update(ports, 0, call_args)
957
def test_notify_ports_update_with_special_ports(self):
958
ports = [{'fixed_ips': [],
960
'device_owner': n_consts.DEVICE_OWNER_DHCP,
961
'mac_address': 'fa:16:3e:da:1d:46'},
962
{'fixed_ips': [{'subnet_id': 'foo_subnet_id',
963
'ip_address': '1.2.3.4'}],
964
'device_id': 'foo_device_id',
965
'device_owner': n_consts.DEVICE_OWNER_ROUTER_GW,
966
'mac_address': 'fa:16:3e:da:1d:46'}]
967
call_args = mock.call(
968
mock.ANY, 'foo_network_id', 'foo_subnet_id', dhcp=[], meta=[])
969
self._test_notify_port_update(ports, 0, call_args)
971
def test_notify_ports_update_many_ports(self):
972
ports = [{'fixed_ips': [],
974
'device_owner': 'foo_device_owner',
975
'mac_address': 'fa:16:3e:da:1d:46'},
976
{'fixed_ips': [{'subnet_id': 'foo_subnet_id',
977
'ip_address': '1.2.3.4'}],
978
'device_id': 'foo_device_id',
979
'device_owner': 'foo_device_owner',
980
'mac_address': 'fa:16:3e:da:1d:46'}]
981
call_args = mock.call(
982
mock.ANY, 'foo_network_id', 'foo_subnet_id',
983
dhcp=[{'ip_address': '1.2.3.4',
984
'mac_address': 'fa:16:3e:da:1d:46'}],
985
meta=[{'instance_id': 'foo_device_id',
986
'ip_address': '1.2.3.4'}])
987
self._test_notify_port_update(ports, 1, call_args)
989
def _test_notify_subnet_action(self, action):
990
with mock.patch.object(self.notifier, '_subnet_%s' % action) as f:
991
self.notifier._handle_subnet_dhcp_access[action] = f
992
subnet = {'subnet': mock.ANY}
993
self.notifier.notify(
994
mock.ANY, subnet, 'subnet.%s.end' % action)
995
f.assert_called_once_with(mock.ANY, subnet)
997
def test_notify_subnet_create(self):
998
self._test_notify_subnet_action('create')
1000
def test_notify_subnet_update(self):
1001
self._test_notify_subnet_action('update')
1003
def test_notify_subnet_delete(self):
1004
self._test_notify_subnet_action('delete')
1006
def _test_subnet_create(self, enable_dhcp, exc=None,
1007
exc_obj=None, call_notify=True):
1009
'id': 'foo_subnet_id',
1010
'enable_dhcp': enable_dhcp,
1011
'network_id': 'foo_network_id',
1012
'tenant_id': 'foo_tenant_id',
1016
self.plugin.create_port.side_effect = exc_obj or exc
1017
self.assertRaises(exc,
1018
self.notifier.notify,
1021
'subnet.create.end')
1022
self.plugin.delete_subnet.assert_called_with(
1023
mock.ANY, subnet['id'])
1026
self.notifier.notify(
1027
mock.ANY, {'subnet': subnet}, 'subnet.create.end')
1031
'admin_state_up': True,
1032
'network_id': 'foo_network_id',
1033
'tenant_id': 'foo_tenant_id',
1034
'device_owner': n_consts.DEVICE_OWNER_DHCP,
1035
'mac_address': mock.ANY,
1036
'fixed_ips': [{'subnet_id': 'foo_subnet_id'}],
1039
self.plugin.create_port.assert_called_once_with(
1040
mock.ANY, {'port': dhcp_port})
1042
self.assertEqual(0, self.plugin.create_port.call_count)
1044
def test_subnet_create_enabled_dhcp(self):
1045
self._test_subnet_create(True)
1047
def test_subnet_create_disabled_dhcp(self):
1048
self._test_subnet_create(False)
1050
def test_subnet_create_raise_port_config_error(self):
1051
with mock.patch.object(nsx.db_base_plugin_v2.NeutronDbPluginV2,
1052
'delete_port') as d:
1053
self._test_subnet_create(
1056
exc_obj=p_exc.PortConfigurationError(lsn_id='foo_lsn_id',
1057
net_id='foo_net_id',
1058
port_id='foo_port_id'))
1059
d.assert_called_once_with(self.plugin, mock.ANY, 'foo_port_id')
1061
def test_subnet_update(self):
1063
'id': 'foo_subnet_id',
1064
'network_id': 'foo_network_id',
1066
self.lsn_manager.lsn_port_get.return_value = ('foo_lsn_id',
1068
self.notifier.notify(
1069
mock.ANY, {'subnet': subnet}, 'subnet.update.end')
1070
self.lsn_manager.lsn_port_dhcp_configure.assert_called_once_with(
1071
mock.ANY, 'foo_lsn_id', 'foo_lsn_port_id', subnet)
1073
def test_subnet_update_raise_lsn_not_found(self):
1075
'id': 'foo_subnet_id',
1076
'network_id': 'foo_network_id',
1078
self.lsn_manager.lsn_port_get.side_effect = (
1079
p_exc.LsnNotFound(entity='network',
1080
entity_id=subnet['network_id']))
1081
self.assertRaises(p_exc.LsnNotFound,
1082
self.notifier.notify,
1083
mock.ANY, {'subnet': subnet}, 'subnet.update.end')
1085
def _test_subnet_update_lsn_port_not_found(self, dhcp_port):
1087
'id': 'foo_subnet_id',
1088
'enable_dhcp': True,
1089
'network_id': 'foo_network_id',
1090
'tenant_id': 'foo_tenant_id'
1092
self.lsn_manager.lsn_port_get.side_effect = (
1093
p_exc.LsnPortNotFound(lsn_id='foo_lsn_id',
1095
entity_id=subnet['id']))
1096
self.notifier.plugin.get_ports.return_value = dhcp_port
1097
count = 0 if dhcp_port is None else 1
1098
with mock.patch.object(nsx, 'handle_port_dhcp_access') as h:
1099
self.notifier.notify(
1100
mock.ANY, {'subnet': subnet}, 'subnet.update.end')
1101
self.assertEqual(count, h.call_count)
1103
self._test_subnet_create(enable_dhcp=True,
1104
exc=None, call_notify=False)
1106
def test_subnet_update_lsn_port_not_found_without_dhcp_port(self):
1107
self._test_subnet_update_lsn_port_not_found(None)
1109
def test_subnet_update_lsn_port_not_found_with_dhcp_port(self):
1110
self._test_subnet_update_lsn_port_not_found([mock.ANY])
1112
def _test_subnet_delete(self, ports=None):
1114
'id': 'foo_subnet_id',
1115
'network_id': 'foo_network_id',
1118
self.plugin.get_ports.return_value = ports
1119
self.notifier.notify(mock.ANY, {'subnet': subnet}, 'subnet.delete.end')
1121
'network_id': [subnet['network_id']],
1122
'device_owner': [n_consts.DEVICE_OWNER_DHCP]
1124
self.plugin.get_ports.assert_called_once_with(
1125
mock.ANY, filters=filters)
1127
self.plugin.delete_port.assert_called_once_with(
1128
mock.ANY, ports[0]['id'])
1130
self.assertEqual(0, self.plugin.delete_port.call_count)
1132
def test_subnet_delete_enabled_dhcp_no_ports(self):
1133
self._test_subnet_delete()
1135
def test_subnet_delete_enabled_dhcp_with_dhcp_port(self):
1136
self._test_subnet_delete([{'id': 'foo_port_id'}])
1139
class DhcpTestCase(base.BaseTestCase):
1142
super(DhcpTestCase, self).setUp()
1143
self.plugin = mock.Mock()
1144
self.plugin.lsn_manager = mock.Mock()
1146
def test_handle_create_network(self):
1147
network = {'id': 'foo_network_id'}
1148
nsx.handle_network_dhcp_access(
1149
self.plugin, mock.ANY, network, 'create_network')
1150
self.plugin.lsn_manager.lsn_create.assert_called_once_with(
1151
mock.ANY, network['id'])
1153
def test_handle_create_network_router_external(self):
1154
network = {'id': 'foo_network_id', 'router:external': True}
1155
nsx.handle_network_dhcp_access(
1156
self.plugin, mock.ANY, network, 'create_network')
1157
self.assertFalse(self.plugin.lsn_manager.lsn_create.call_count)
1159
def test_handle_delete_network(self):
1160
network_id = 'foo_network_id'
1161
self.plugin.lsn_manager.lsn_delete_by_network.return_value = (
1163
nsx.handle_network_dhcp_access(
1164
self.plugin, mock.ANY, network_id, 'delete_network')
1165
self.plugin.lsn_manager.lsn_delete_by_network.assert_called_once_with(
1166
mock.ANY, 'foo_network_id')
1168
def _test_handle_create_dhcp_owner_port(self, exc=None):
1170
'cidr': '0.0.0.0/0',
1171
'id': 'foo_subnet_id'
1174
'id': 'foo_port_id',
1175
'device_owner': n_consts.DEVICE_OWNER_DHCP,
1176
'mac_address': 'aa:bb:cc:dd:ee:ff',
1177
'network_id': 'foo_network_id',
1178
'fixed_ips': [{'subnet_id': subnet['id']}]
1181
'subnet_id': subnet['id'],
1182
'ip_address': subnet['cidr'],
1183
'mac_address': port['mac_address']
1185
self.plugin.get_subnet.return_value = subnet
1187
nsx.handle_port_dhcp_access(
1188
self.plugin, mock.ANY, port, 'create_port')
1189
(self.plugin.lsn_manager.lsn_port_dhcp_setup.
1190
assert_called_once_with(mock.ANY, port['network_id'],
1191
port['id'], expected_data, subnet))
1193
self.plugin.lsn_manager.lsn_port_dhcp_setup.side_effect = exc
1194
self.assertRaises(n_exc.NeutronException,
1195
nsx.handle_port_dhcp_access,
1196
self.plugin, mock.ANY, port, 'create_port')
1198
def test_handle_create_dhcp_owner_port(self):
1199
self._test_handle_create_dhcp_owner_port()
1201
def test_handle_create_dhcp_owner_port_raise_port_config_error(self):
1202
config_error = p_exc.PortConfigurationError(lsn_id='foo_lsn_id',
1203
net_id='foo_net_id',
1204
port_id='foo_port_id')
1205
self._test_handle_create_dhcp_owner_port(exc=config_error)
1207
def test_handle_delete_dhcp_owner_port(self):
1209
'id': 'foo_port_id',
1210
'device_owner': n_consts.DEVICE_OWNER_DHCP,
1211
'network_id': 'foo_network_id',
1213
'mac_address': 'aa:bb:cc:dd:ee:ff'
1215
nsx.handle_port_dhcp_access(self.plugin, mock.ANY, port, 'delete_port')
1216
self.plugin.lsn_manager.lsn_port_dispose.assert_called_once_with(
1217
mock.ANY, port['network_id'], port['mac_address'])
1219
def _test_handle_user_port(self, action, handler):
1221
'id': 'foo_port_id',
1222
'device_owner': 'foo_device_owner',
1223
'network_id': 'foo_network_id',
1224
'mac_address': 'aa:bb:cc:dd:ee:ff',
1225
'fixed_ips': [{'subnet_id': 'foo_subnet_id',
1226
'ip_address': '1.2.3.4'}]
1229
'ip_address': '1.2.3.4',
1230
'mac_address': 'aa:bb:cc:dd:ee:ff'
1232
self.plugin.get_subnet.return_value = {'enable_dhcp': True}
1233
nsx.handle_port_dhcp_access(self.plugin, mock.ANY, port, action)
1234
handler.assert_called_once_with(
1235
mock.ANY, port['network_id'], 'foo_subnet_id', expected_data)
1237
def test_handle_create_user_port(self):
1238
self._test_handle_user_port(
1239
'create_port', self.plugin.lsn_manager.lsn_port_dhcp_host_add)
1241
def test_handle_delete_user_port(self):
1242
self._test_handle_user_port(
1243
'delete_port', self.plugin.lsn_manager.lsn_port_dhcp_host_remove)
1245
def _test_handle_user_port_disabled_dhcp(self, action, handler):
1247
'id': 'foo_port_id',
1248
'device_owner': 'foo_device_owner',
1249
'network_id': 'foo_network_id',
1250
'mac_address': 'aa:bb:cc:dd:ee:ff',
1251
'fixed_ips': [{'subnet_id': 'foo_subnet_id',
1252
'ip_address': '1.2.3.4'}]
1254
self.plugin.get_subnet.return_value = {'enable_dhcp': False}
1255
nsx.handle_port_dhcp_access(self.plugin, mock.ANY, port, action)
1256
self.assertEqual(0, handler.call_count)
1258
def test_handle_create_user_port_disabled_dhcp(self):
1259
self._test_handle_user_port_disabled_dhcp(
1260
'create_port', self.plugin.lsn_manager.lsn_port_dhcp_host_add)
1262
def test_handle_delete_user_port_disabled_dhcp(self):
1263
self._test_handle_user_port_disabled_dhcp(
1264
'delete_port', self.plugin.lsn_manager.lsn_port_dhcp_host_remove)
1266
def _test_handle_user_port_no_fixed_ips(self, action, handler):
1268
'id': 'foo_port_id',
1269
'device_owner': 'foo_device_owner',
1270
'network_id': 'foo_network_id',
1273
nsx.handle_port_dhcp_access(self.plugin, mock.ANY, port, action)
1274
self.assertEqual(0, handler.call_count)
1276
def test_handle_create_user_port_no_fixed_ips(self):
1277
self._test_handle_user_port_no_fixed_ips(
1278
'create_port', self.plugin.lsn_manager.lsn_port_dhcp_host_add)
1280
def test_handle_delete_user_port_no_fixed_ips(self):
1281
self._test_handle_user_port_no_fixed_ips(
1282
'delete_port', self.plugin.lsn_manager.lsn_port_dhcp_host_remove)
1285
class MetadataTestCase(base.BaseTestCase):
1288
super(MetadataTestCase, self).setUp()
1289
self.plugin = mock.Mock()
1290
self.plugin.lsn_manager = mock.Mock()
1292
def _test_handle_port_metadata_access_special_owners(
1293
self, owner, dev_id='foo_device_id', ips=None):
1295
'id': 'foo_port_id',
1296
'device_owner': owner,
1297
'device_id': dev_id,
1298
'fixed_ips': ips or []
1300
nsx.handle_port_metadata_access(self.plugin, mock.ANY, port, mock.ANY)
1302
self.plugin.lsn_manager.lsn_port_meta_host_add.call_count)
1304
self.plugin.lsn_manager.lsn_port_meta_host_remove.call_count)
1306
def test_handle_port_metadata_access_external_network(self):
1308
'id': 'foo_port_id',
1309
'device_owner': 'foo_device_owner',
1310
'device_id': 'foo_device_id',
1311
'network_id': 'foo_network_id',
1312
'fixed_ips': [{'subnet_id': 'foo_subnet'}]
1314
self.plugin.get_network.return_value = {'router:external': True}
1315
nsx.handle_port_metadata_access(self.plugin, mock.ANY, port, mock.ANY)
1317
self.plugin.lsn_manager.lsn_port_meta_host_add.call_count)
1319
self.plugin.lsn_manager.lsn_port_meta_host_remove.call_count)
1321
def test_handle_port_metadata_access_dhcp_port(self):
1322
self._test_handle_port_metadata_access_special_owners(
1323
n_consts.DEVICE_OWNER_DHCP, [{'subnet_id': 'foo_subnet'}])
1325
def test_handle_port_metadata_access_router_port(self):
1326
self._test_handle_port_metadata_access_special_owners(
1327
n_consts.DEVICE_OWNER_ROUTER_INTF, [{'subnet_id': 'foo_subnet'}])
1329
def test_handle_port_metadata_access_no_device_id(self):
1330
self._test_handle_port_metadata_access_special_owners(
1331
n_consts.DEVICE_OWNER_DHCP, '')
1333
def test_handle_port_metadata_access_no_fixed_ips(self):
1334
self._test_handle_port_metadata_access_special_owners(
1337
def _test_handle_port_metadata_access(self, is_delete, raise_exc=False):
1339
'id': 'foo_port_id',
1340
'device_owner': 'foo_device_id',
1341
'network_id': 'foo_network_id',
1342
'device_id': 'foo_device_id',
1343
'tenant_id': 'foo_tenant_id',
1345
{'subnet_id': 'foo_subnet_id', 'ip_address': '1.2.3.4'}
1349
'instance_id': port['device_id'],
1350
'tenant_id': port['tenant_id'],
1351
'ip_address': port['fixed_ips'][0]['ip_address']
1353
self.plugin.get_network.return_value = {'router:external': False}
1355
mock_func = self.plugin.lsn_manager.lsn_port_meta_host_remove
1357
mock_func = self.plugin.lsn_manager.lsn_port_meta_host_add
1359
mock_func.side_effect = p_exc.PortConfigurationError(
1360
lsn_id='foo_lsn_id', net_id='foo_net_id', port_id=None)
1361
with mock.patch.object(nsx.db_base_plugin_v2.NeutronDbPluginV2,
1362
'delete_port') as d:
1363
self.assertRaises(p_exc.PortConfigurationError,
1364
nsx.handle_port_metadata_access,
1365
self.plugin, mock.ANY, port,
1366
is_delete=is_delete)
1368
d.assert_called_once_with(mock.ANY, mock.ANY, port['id'])
1370
self.assertFalse(d.call_count)
1372
nsx.handle_port_metadata_access(
1373
self.plugin, mock.ANY, port, is_delete=is_delete)
1374
mock_func.assert_called_once_with(mock.ANY, mock.ANY, mock.ANY, meta)
1376
def test_handle_port_metadata_access_on_delete_true(self):
1377
self._test_handle_port_metadata_access(True)
1379
def test_handle_port_metadata_access_on_delete_false(self):
1380
self._test_handle_port_metadata_access(False)
1382
def test_handle_port_metadata_access_on_delete_true_raise(self):
1383
self._test_handle_port_metadata_access(True, raise_exc=True)
1385
def test_handle_port_metadata_access_on_delete_false_raise(self):
1386
self._test_handle_port_metadata_access(False, raise_exc=True)
1388
def _test_handle_router_metadata_access(
1389
self, is_port_found, raise_exc=False):
1391
'id': 'foo_subnet_id',
1392
'network_id': 'foo_network_id'
1395
'subnet_id': subnet['id'],
1396
'port_id': 'foo_port_id'
1398
mock_func = self.plugin.lsn_manager.lsn_metadata_configure
1399
if not is_port_found:
1400
self.plugin.get_port.side_effect = n_exc.NotFound
1402
with mock.patch.object(nsx.l3_db.L3_NAT_db_mixin,
1403
'remove_router_interface') as d:
1404
mock_func.side_effect = p_exc.NsxPluginException(err_msg='')
1405
self.assertRaises(p_exc.NsxPluginException,
1406
nsx.handle_router_metadata_access,
1407
self.plugin, mock.ANY, 'foo_router_id',
1409
d.assert_called_once_with(mock.ANY, mock.ANY, 'foo_router_id',
1412
nsx.handle_router_metadata_access(
1413
self.plugin, mock.ANY, 'foo_router_id', interface)
1414
mock_func.assert_called_once_with(
1415
mock.ANY, subnet['id'], is_port_found)
1417
def test_handle_router_metadata_access_add_interface(self):
1418
self._test_handle_router_metadata_access(True)
1420
def test_handle_router_metadata_access_delete_interface(self):
1421
self._test_handle_router_metadata_access(False)
1423
def test_handle_router_metadata_access_raise_error_on_add(self):
1424
self._test_handle_router_metadata_access(True, raise_exc=True)
1426
def test_handle_router_metadata_access_raise_error_on_delete(self):
1427
self._test_handle_router_metadata_access(True, raise_exc=False)