~ubuntu-branches/ubuntu/vivid/neutron/vivid-updates

« back to all changes in this revision

Viewing changes to neutron/tests/unit/vmware/test_dhcpmeta.py

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2015-03-30 11:17:19 UTC
  • mfrom: (1.1.21)
  • Revision ID: package-import@ubuntu.com-20150330111719-h0gx7233p4jkkgfh
Tags: 1:2015.1~b3-0ubuntu1
* New upstream milestone release:
  - d/control: Align version requirements with upstream.
  - d/control: Add new dependency on oslo-log.
  - d/p/*: Rebase.
  - d/control,d/neutron-plugin-hyperv*: Dropped, decomposed into
    separate project upstream.
  - d/control,d/neutron-plugin-openflow*: Dropped, decomposed into
    separate project upstream.
  - d/neutron-common.install: Add neutron-rootwrap-daemon and 
    neutron-keepalived-state-change binaries.
  - d/rules: Ignore neutron-hyperv-agent when installing; only for Windows.
  - d/neutron-plugin-cisco.install: Drop neutron-cisco-cfg-agent as
    decomposed into separate project upstream.
  - d/neutron-plugin-vmware.install: Drop neutron-check-nsx-config and
    neutron-nsx-manage as decomposed into separate project upstream.
  - d/control: Add dependency on python-neutron-fwaas to neutron-l3-agent.
* d/pydist-overrides: Add overrides for oslo packages.
* d/control: Fixup type in package description (LP: #1263539).
* d/p/fixup-driver-test-execution.patch: Cherry pick fix from upstream VCS
  to support unit test exection in out-of-tree vendor drivers.
* d/neutron-common.postinst: Allow general access to /etc/neutron but limit
  access to root/neutron to /etc/neutron/neutron.conf to support execution
  of unit tests in decomposed vendor drivers.
* d/control: Add dependency on python-neutron-fwaas to neutron-l3-agent
  package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2013 VMware, Inc.
2
 
#
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
6
 
#
7
 
#    http://www.apache.org/licenses/LICENSE-2.0
8
 
#
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
12
 
# implied.
13
 
# See the License for the specific language governing permissions and
14
 
# limitations under the License.
15
 
 
16
 
import mock
17
 
 
18
 
from oslo.config import cfg
19
 
 
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
33
 
 
34
 
 
35
 
class DhcpMetadataBuilderTestCase(base.BaseTestCase):
36
 
 
37
 
    def setUp(self):
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'
43
 
 
44
 
    def test_dhcp_agent_get_all(self):
45
 
        expected = []
46
 
        self.builder.plugin.list_dhcp_agents_hosting_network.return_value = (
47
 
            {'agents': expected})
48
 
        agents = self.builder.dhcp_agent_get_all(mock.ANY, self.network_id)
49
 
        self.assertEqual(expected, agents)
50
 
 
51
 
    def test_dhcp_port_get_all(self):
52
 
        expected = []
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)
56
 
 
57
 
    def test_router_id_get(self):
58
 
        port = {
59
 
            'device_id': self.router_id,
60
 
            'network_id': self.network_id,
61
 
            'fixed_ips': [{'subnet_id': self.subnet_id}]
62
 
        }
63
 
        subnet = {
64
 
            'id': self.subnet_id,
65
 
            'network_id': self.network_id
66
 
        }
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)
70
 
 
71
 
    def test_router_id_get_none_subnet(self):
72
 
        self.assertIsNone(self.builder.router_id_get(mock.ANY, None))
73
 
 
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))
78
 
 
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)
83
 
 
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)
88
 
 
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)
93
 
        self.assertTrue(
94
 
            self.builder.plugin.remove_network_from_dhcp_agent.call_count)
95
 
        self.assertTrue(self.builder.plugin.delete_port.call_count)
96
 
 
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)
103
 
 
104
 
    def test_dhcp_allocate(self):
105
 
        subnet = {'network_id': self.network_id, 'id': self.subnet_id}
106
 
        self._test_dhcp_allocate(subnet, 2)
107
 
 
108
 
    def test_dhcp_allocate_none_subnet(self):
109
 
        self._test_dhcp_allocate(None, 0)
110
 
 
111
 
 
112
 
class MigrationManagerTestCase(base.BaseTestCase):
113
 
 
114
 
    def setUp(self):
115
 
        super(MigrationManagerTestCase, self).setUp()
116
 
        self.manager = mig_man.MigrationManager(mock.Mock(),
117
 
                                                mock.Mock(),
118
 
                                                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()
124
 
 
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)
131
 
        if len(subnets):
132
 
            self.assertEqual(subnets[0], result)
133
 
        else:
134
 
            self.assertIsNone(result)
135
 
 
136
 
    def test_validate_no_subnets(self):
137
 
        self._test_validate(subnets=[])
138
 
 
139
 
    def test_validate_with_one_subnet(self):
140
 
        self._test_validate(subnets=[{'cidr': '0.0.0.0/0'}])
141
 
 
142
 
    def test_validate_raise_conflict_many_subnets(self):
143
 
        self.assertRaises(p_exc.LsnMigrationConflict,
144
 
                          self._test_validate,
145
 
                          subnets=[{'id': 'sub1'}, {'id': 'sub2'}])
146
 
 
147
 
    def test_validate_raise_conflict_lsn_exists(self):
148
 
        self.assertRaises(p_exc.LsnMigrationConflict,
149
 
                          self._test_validate,
150
 
                          lsn_exists=True)
151
 
 
152
 
    def test_validate_raise_badrequest_external_net(self):
153
 
        self.assertRaises(n_exc.BadRequest,
154
 
                          self._test_validate,
155
 
                          ext_net=True)
156
 
 
157
 
    def test_validate_raise_badrequest_metadata_net(self):
158
 
        self.assertRaises(n_exc.BadRequest,
159
 
                          self._test_validate,
160
 
                          ext_net=False,
161
 
                          subnets=[{'cidr': rpc.METADATA_SUBNET_CIDR}])
162
 
 
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)
168
 
 
169
 
    def test_migrate(self):
170
 
        subnet = {
171
 
            'id': self.subnet_id,
172
 
            'network_id': self.network_id
173
 
        }
174
 
        call_sequence = [
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)
185
 
        ]
186
 
        self._test_migrate(self.router_id, subnet, call_sequence)
187
 
 
188
 
    def test_migrate_no_router_uplink(self):
189
 
        subnet = {
190
 
            'id': self.subnet_id,
191
 
            'network_id': self.network_id
192
 
        }
193
 
        call_sequence = [
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),
200
 
        ]
201
 
        self._test_migrate(None, subnet, call_sequence)
202
 
 
203
 
    def test_migrate_no_subnet(self):
204
 
        call_sequence = [
205
 
            mock.call.router_id_get(mock.ANY, None),
206
 
            mock.call.dhcp_allocate(mock.ANY, self.network_id, None),
207
 
        ]
208
 
        self._test_migrate(None, None, call_sequence)
209
 
 
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)
214
 
 
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'})
219
 
 
220
 
    def test_report_for_lsn_without_lsn_port(self):
221
 
        self._test_report(('foo_lsn_id', None),
222
 
                          {'ports': [],
223
 
                           'services': ['foo_lsn_id'], 'type': 'lsn'})
224
 
 
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)
231
 
            expected = {
232
 
                'ports': ['foo_lsn_port_id'] if validated_subnet else [],
233
 
                'services': ['foo_lsn_id'], 'type': 'lsn'
234
 
            }
235
 
            self.assertEqual(expected, report)
236
 
 
237
 
    def test_report_for_lsn_without_subnet_subnet_found(self):
238
 
        self._test_report_for_lsn_without_subnet([{'id': self.subnet_id}])
239
 
 
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)
243
 
 
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)
251
 
        expected = {
252
 
            'ports': ['foo_dhcp_port_id'],
253
 
            'services': ['foo_agent_id'],
254
 
            'type': 'agent'
255
 
        }
256
 
        self.assertEqual(expected, result)
257
 
 
258
 
 
259
 
class LsnManagerTestCase(base.BaseTestCase):
260
 
 
261
 
    def setUp(self):
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)
279
 
 
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)
286
 
 
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)
294
 
 
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)
297
 
 
298
 
    def test_lsn_get_raise_not_found_with_api_error(self):
299
 
        self._test_lsn_get_raise_not_found_with_exc(exception.NsxApiException)
300
 
 
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)
308
 
 
309
 
    def test_lsn_get_silent_raise_with_not_found(self):
310
 
        self._test_lsn_get_silent_raise_with_exc(n_exc.NotFound)
311
 
 
312
 
    def test_lsn_get_silent_raise_with_api_error(self):
313
 
        self._test_lsn_get_silent_raise_with_exc(exception.NsxApiException)
314
 
 
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)
320
 
 
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)
329
 
 
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)
334
 
 
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)
340
 
 
341
 
    def test_lsn_delete_with_not_found(self):
342
 
        self._test_lsn_delete_with_exc(n_exc.NotFound)
343
 
 
344
 
    def test_lsn_delete_api_exception(self):
345
 
        self._test_lsn_delete_with_exc(exception.NsxApiException)
346
 
 
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)
354
 
 
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)
360
 
 
361
 
    def test_lsn_delete_by_network_with_not_found(self):
362
 
        self._test_lsn_delete_by_network_with_exc(n_exc.NotFound)
363
 
 
364
 
    def test_lsn_delete_by_network_with_not_api_error(self):
365
 
        self._test_lsn_delete_by_network_with_exc(exception.NsxApiException)
366
 
 
367
 
    def test_lsn_port_get(self):
368
 
        self.mock_lsn_api.lsn_port_by_subnet_get.return_value = (
369
 
            self.lsn_port_id)
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))
375
 
 
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)
384
 
 
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))
390
 
 
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)
398
 
 
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))
406
 
 
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)
411
 
 
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)
417
 
 
418
 
    def test_lsn_port_create_with_not_found(self):
419
 
        self._test_lsn_port_create_with_exc(n_exc.NotFound, p_exc.LsnNotFound)
420
 
 
421
 
    def test_lsn_port_create_api_exception(self):
422
 
        self._test_lsn_port_create_with_exc(exception.NsxApiException,
423
 
                                            p_exc.NsxPluginException)
424
 
 
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)
428
 
 
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)
435
 
 
436
 
    def test_lsn_port_delete_with_not_found(self):
437
 
        self._test_lsn_port_delete_with_exc(n_exc.NotFound)
438
 
 
439
 
    def test_lsn_port_delete_api_exception(self):
440
 
        self._test_lsn_port_delete_with_exc(exception.NsxApiException)
441
 
 
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)
452
 
                self.assertEqual(
453
 
                    1, self.mock_lsn_api.lsn_port_create.call_count)
454
 
                self.assertEqual(
455
 
                    1, self.mock_lsn_api.lsn_port_plug_network.call_count)
456
 
                self.assertEqual(expected, ret_val)
457
 
 
458
 
    def test_lsn_port_dhcp_setup(self):
459
 
        self._test_lsn_port_dhcp_setup((self.lsn_id, self.lsn_port_id), None)
460
 
 
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)
465
 
 
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)
474
 
 
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)
485
 
 
486
 
    def _test_lsn_port_dhcp_configure_with_subnet(
487
 
        self, expected, dns=None, gw=None, routes=None):
488
 
        subnet = {
489
 
            'enable_dhcp': True,
490
 
            'dns_nameservers': dns or [],
491
 
            'gateway_ip': gw,
492
 
            'host_routes': routes
493
 
        }
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'],
498
 
            expected)
499
 
 
500
 
    def test_lsn_port_dhcp_configure(self):
501
 
        expected = {
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
505
 
        }
506
 
        self._test_lsn_port_dhcp_configure_with_subnet(
507
 
            expected, dns=[], gw='127.0.0.1', routes=[])
508
 
 
509
 
    def test_lsn_port_dhcp_configure_gatewayless(self):
510
 
        expected = {
511
 
            'default_lease_time': cfg.CONF.NSX_DHCP.default_lease_time,
512
 
            'domain_name': cfg.CONF.NSX_DHCP.domain_name
513
 
        }
514
 
        self._test_lsn_port_dhcp_configure_with_subnet(expected, gw=None)
515
 
 
516
 
    def test_lsn_port_dhcp_configure_with_extra_dns_servers(self):
517
 
        expected = {
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
521
 
        }
522
 
        self._test_lsn_port_dhcp_configure_with_subnet(
523
 
            expected, dns=['8.8.8.8', '9.9.9.9'])
524
 
 
525
 
    def test_lsn_port_dhcp_configure_with_host_routes(self):
526
 
        expected = {
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'
530
 
        }
531
 
        self._test_lsn_port_dhcp_configure_with_subnet(
532
 
            expected, routes=['8.8.8.8', '9.9.9.9'])
533
 
 
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)
540
 
            expected = {
541
 
                'metadata_server_port': 8775,
542
 
                'metadata_server_ip': '127.0.0.1',
543
 
                'metadata_proxy_shared_secret': ''
544
 
            }
545
 
            self.mock_lsn_api.lsn_metadata_configure.assert_called_once_with(
546
 
                mock.ANY, mock.ANY, is_enabled, expected)
547
 
            if is_enabled:
548
 
                self.assertEqual(
549
 
                    1, self.mock_lsn_api.lsn_port_by_subnet_get.call_count)
550
 
            else:
551
 
                self.assertEqual(1, f.call_count)
552
 
 
553
 
    def test_lsn_metadata_configure_enabled(self):
554
 
        self._test_lsn_metadata_configure(True)
555
 
 
556
 
    def test_lsn_metadata_configure_disabled(self):
557
 
        self._test_lsn_metadata_configure(False)
558
 
 
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)
567
 
 
568
 
    def test_lsn_port_metadata_setup(self):
569
 
        subnet = {
570
 
            'cidr': '0.0.0.0/0',
571
 
            'id': self.sub_id,
572
 
            'network_id': self.net_id,
573
 
            'tenant_id': self.tenant_id
574
 
        }
575
 
        expected_data = {
576
 
            'subnet_id': subnet['id'],
577
 
            'ip_address': subnet['cidr'],
578
 
            'mac_address': constants.METADATA_MAC
579
 
        }
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)
591
 
 
592
 
    def test_lsn_port_metadata_setup_raise_not_found(self):
593
 
        subnet = {
594
 
            'cidr': '0.0.0.0/0',
595
 
            'id': self.sub_id,
596
 
            'network_id': self.net_id,
597
 
            'tenant_id': self.tenant_id
598
 
        }
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)
605
 
 
606
 
    def test_lsn_port_metadata_setup_raise_conflict(self):
607
 
        subnet = {
608
 
            'cidr': '0.0.0.0/0',
609
 
            'id': self.sub_id,
610
 
            'network_id': self.net_id,
611
 
            'tenant_id': self.tenant_id
612
 
        }
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)
622
 
                self.assertEqual(1,
623
 
                                 self.mock_lsn_api.lsn_port_delete.call_count)
624
 
                self.assertEqual(1, g.call_count)
625
 
 
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)
633
 
 
634
 
    def test_lsn_port_dispose(self):
635
 
        self._test_lsn_port_dispose_with_values(
636
 
            self.lsn_id, self.lsn_port_id, 1)
637
 
 
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)
649
 
 
650
 
    def test_lsn_port_dispose_lsn_not_found(self):
651
 
        self._test_lsn_port_dispose_with_values(None, None, 0)
652
 
 
653
 
    def test_lsn_port_dispose_lsn_port_not_found(self):
654
 
        self._test_lsn_port_dispose_with_values(self.lsn_id, None, 0)
655
 
 
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)
662
 
 
663
 
    def test_lsn_port_host_conf(self):
664
 
        with mock.patch.object(self.manager,
665
 
                               'lsn_port_get',
666
 
                               return_value=(self.lsn_id, self.lsn_port_id)):
667
 
            f = mock.Mock()
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)
671
 
 
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)
678
 
 
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))
686
 
 
687
 
    def test_lsn_port_update(self):
688
 
        self._test_lsn_port_update()
689
 
 
690
 
    def test_lsn_port_update_dhcp_meta(self):
691
 
        self._test_lsn_port_update(mock.ANY, mock.ANY)
692
 
 
693
 
    def test_lsn_port_update_dhcp_and_nometa(self):
694
 
        self._test_lsn_port_update(mock.ANY, None)
695
 
 
696
 
    def test_lsn_port_update_nodhcp_and_nmeta(self):
697
 
        self._test_lsn_port_update(None, mock.ANY)
698
 
 
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)
705
 
 
706
 
 
707
 
class PersistentLsnManagerTestCase(testlib_api.SqlTestCase):
708
 
 
709
 
    def setUp(self):
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()
725
 
 
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)
730
 
 
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)
734
 
 
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)
739
 
 
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)
747
 
 
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)
752
 
 
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)
757
 
            self.assertTrue(
758
 
                self.mock_lsn_api.lsn_for_network_create.call_count)
759
 
            self.assertTrue(f.call_count)
760
 
            self.assertEqual(self.lsn_id, result)
761
 
 
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)
770
 
 
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))
777
 
 
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)
781
 
 
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)
788
 
 
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)
793
 
 
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)
798
 
 
799
 
    def test_lsn_port_get_sync_on_missing(self):
800
 
        return
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)
810
 
                self.assertTrue(
811
 
                    self.mock_lsn_api.lsn_port_by_subnet_get.call_count)
812
 
                self.assertTrue(
813
 
                    self.mock_lsn_api.lsn_port_info_get.call_count)
814
 
                self.assertTrue(f.call_count)
815
 
                self.assertTrue(g.call_count)
816
 
 
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)
824
 
 
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)
829
 
 
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)
834
 
 
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)
842
 
            self.assertTrue(
843
 
                self.mock_lsn_api.lsn_port_create.call_count)
844
 
            self.assertTrue(f.call_count)
845
 
            self.assertEqual(self.lsn_port_id, result)
846
 
 
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)
856
 
 
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))
865
 
 
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)
870
 
 
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)
878
 
 
879
 
 
880
 
class DhcpAgentNotifyAPITestCase(base.BaseTestCase):
881
 
 
882
 
    def setUp(self):
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
887
 
 
888
 
    def _test_notify_port_update(
889
 
        self, ports, expected_count, expected_args=None):
890
 
        port = {
891
 
            'id': 'foo_port_id',
892
 
            'network_id': 'foo_network_id',
893
 
            'fixed_ips': [{'subnet_id': 'foo_subnet_id'}]
894
 
        }
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)
898
 
 
899
 
    def test_notify_ports_update_no_ports(self):
900
 
        self._test_notify_port_update(None, 0, [])
901
 
        self._test_notify_port_update([], 0, [])
902
 
 
903
 
    def test_notify_ports_update_one_port(self):
904
 
        ports = [{
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'
910
 
        }]
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)
918
 
 
919
 
    def test_notify_ports_update_ports_with_empty_device_id(self):
920
 
        ports = [{
921
 
            'fixed_ips': [{'subnet_id': 'foo_subnet_id',
922
 
                           'ip_address': '1.2.3.4'}],
923
 
            'device_id': '',
924
 
            'device_owner': 'foo_device_owner',
925
 
            'mac_address': 'fa:16:3e:da:1d:46'
926
 
        }]
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'}],
931
 
            meta=[]
932
 
        )
933
 
        self._test_notify_port_update(ports, 1, call_args)
934
 
 
935
 
    def test_notify_ports_update_ports_with_no_fixed_ips(self):
936
 
        ports = [{
937
 
            'fixed_ips': [],
938
 
            'device_id': 'foo_device_id',
939
 
            'device_owner': 'foo_device_owner',
940
 
            'mac_address': 'fa:16:3e:da:1d:46'
941
 
        }]
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)
945
 
 
946
 
    def test_notify_ports_update_ports_with_no_fixed_ips_and_no_device(self):
947
 
        ports = [{
948
 
            'fixed_ips': [],
949
 
            'device_id': '',
950
 
            'device_owner': 'foo_device_owner',
951
 
            'mac_address': 'fa:16:3e:da:1d:46'
952
 
        }]
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)
956
 
 
957
 
    def test_notify_ports_update_with_special_ports(self):
958
 
        ports = [{'fixed_ips': [],
959
 
                  'device_id': '',
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)
970
 
 
971
 
    def test_notify_ports_update_many_ports(self):
972
 
        ports = [{'fixed_ips': [],
973
 
                  'device_id': '',
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)
988
 
 
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)
996
 
 
997
 
    def test_notify_subnet_create(self):
998
 
        self._test_notify_subnet_action('create')
999
 
 
1000
 
    def test_notify_subnet_update(self):
1001
 
        self._test_notify_subnet_action('update')
1002
 
 
1003
 
    def test_notify_subnet_delete(self):
1004
 
        self._test_notify_subnet_action('delete')
1005
 
 
1006
 
    def _test_subnet_create(self, enable_dhcp, exc=None,
1007
 
                            exc_obj=None, call_notify=True):
1008
 
        subnet = {
1009
 
            'id': 'foo_subnet_id',
1010
 
            'enable_dhcp': enable_dhcp,
1011
 
            'network_id': 'foo_network_id',
1012
 
            'tenant_id': 'foo_tenant_id',
1013
 
            'cidr': '0.0.0.0/0'
1014
 
        }
1015
 
        if exc:
1016
 
            self.plugin.create_port.side_effect = exc_obj or exc
1017
 
            self.assertRaises(exc,
1018
 
                              self.notifier.notify,
1019
 
                              mock.ANY,
1020
 
                              {'subnet': subnet},
1021
 
                              'subnet.create.end')
1022
 
            self.plugin.delete_subnet.assert_called_with(
1023
 
                mock.ANY, subnet['id'])
1024
 
        else:
1025
 
            if call_notify:
1026
 
                self.notifier.notify(
1027
 
                    mock.ANY, {'subnet': subnet}, 'subnet.create.end')
1028
 
            if enable_dhcp:
1029
 
                dhcp_port = {
1030
 
                    'name': '',
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'}],
1037
 
                    'device_id': ''
1038
 
                }
1039
 
                self.plugin.create_port.assert_called_once_with(
1040
 
                    mock.ANY, {'port': dhcp_port})
1041
 
            else:
1042
 
                self.assertEqual(0, self.plugin.create_port.call_count)
1043
 
 
1044
 
    def test_subnet_create_enabled_dhcp(self):
1045
 
        self._test_subnet_create(True)
1046
 
 
1047
 
    def test_subnet_create_disabled_dhcp(self):
1048
 
        self._test_subnet_create(False)
1049
 
 
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(
1054
 
                True,
1055
 
                exc=n_exc.Conflict,
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')
1060
 
 
1061
 
    def test_subnet_update(self):
1062
 
        subnet = {
1063
 
            'id': 'foo_subnet_id',
1064
 
            'network_id': 'foo_network_id',
1065
 
        }
1066
 
        self.lsn_manager.lsn_port_get.return_value = ('foo_lsn_id',
1067
 
                                                      'foo_lsn_port_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)
1072
 
 
1073
 
    def test_subnet_update_raise_lsn_not_found(self):
1074
 
        subnet = {
1075
 
            'id': 'foo_subnet_id',
1076
 
            'network_id': 'foo_network_id',
1077
 
        }
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')
1084
 
 
1085
 
    def _test_subnet_update_lsn_port_not_found(self, dhcp_port):
1086
 
        subnet = {
1087
 
            'id': 'foo_subnet_id',
1088
 
            'enable_dhcp': True,
1089
 
            'network_id': 'foo_network_id',
1090
 
            'tenant_id': 'foo_tenant_id'
1091
 
        }
1092
 
        self.lsn_manager.lsn_port_get.side_effect = (
1093
 
            p_exc.LsnPortNotFound(lsn_id='foo_lsn_id',
1094
 
                                  entity='subnet',
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)
1102
 
            if not dhcp_port:
1103
 
                self._test_subnet_create(enable_dhcp=True,
1104
 
                                         exc=None, call_notify=False)
1105
 
 
1106
 
    def test_subnet_update_lsn_port_not_found_without_dhcp_port(self):
1107
 
        self._test_subnet_update_lsn_port_not_found(None)
1108
 
 
1109
 
    def test_subnet_update_lsn_port_not_found_with_dhcp_port(self):
1110
 
        self._test_subnet_update_lsn_port_not_found([mock.ANY])
1111
 
 
1112
 
    def _test_subnet_delete(self, ports=None):
1113
 
        subnet = {
1114
 
            'id': 'foo_subnet_id',
1115
 
            'network_id': 'foo_network_id',
1116
 
            'cidr': '0.0.0.0/0'
1117
 
        }
1118
 
        self.plugin.get_ports.return_value = ports
1119
 
        self.notifier.notify(mock.ANY, {'subnet': subnet}, 'subnet.delete.end')
1120
 
        filters = {
1121
 
            'network_id': [subnet['network_id']],
1122
 
            'device_owner': [n_consts.DEVICE_OWNER_DHCP]
1123
 
        }
1124
 
        self.plugin.get_ports.assert_called_once_with(
1125
 
            mock.ANY, filters=filters)
1126
 
        if ports:
1127
 
            self.plugin.delete_port.assert_called_once_with(
1128
 
                mock.ANY, ports[0]['id'])
1129
 
        else:
1130
 
            self.assertEqual(0, self.plugin.delete_port.call_count)
1131
 
 
1132
 
    def test_subnet_delete_enabled_dhcp_no_ports(self):
1133
 
        self._test_subnet_delete()
1134
 
 
1135
 
    def test_subnet_delete_enabled_dhcp_with_dhcp_port(self):
1136
 
        self._test_subnet_delete([{'id': 'foo_port_id'}])
1137
 
 
1138
 
 
1139
 
class DhcpTestCase(base.BaseTestCase):
1140
 
 
1141
 
    def setUp(self):
1142
 
        super(DhcpTestCase, self).setUp()
1143
 
        self.plugin = mock.Mock()
1144
 
        self.plugin.lsn_manager = mock.Mock()
1145
 
 
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'])
1152
 
 
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)
1158
 
 
1159
 
    def test_handle_delete_network(self):
1160
 
        network_id = 'foo_network_id'
1161
 
        self.plugin.lsn_manager.lsn_delete_by_network.return_value = (
1162
 
            'foo_lsn_id')
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')
1167
 
 
1168
 
    def _test_handle_create_dhcp_owner_port(self, exc=None):
1169
 
        subnet = {
1170
 
            'cidr': '0.0.0.0/0',
1171
 
            'id': 'foo_subnet_id'
1172
 
        }
1173
 
        port = {
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']}]
1179
 
        }
1180
 
        expected_data = {
1181
 
            'subnet_id': subnet['id'],
1182
 
            'ip_address': subnet['cidr'],
1183
 
            'mac_address': port['mac_address']
1184
 
        }
1185
 
        self.plugin.get_subnet.return_value = subnet
1186
 
        if exc is None:
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))
1192
 
        else:
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')
1197
 
 
1198
 
    def test_handle_create_dhcp_owner_port(self):
1199
 
        self._test_handle_create_dhcp_owner_port()
1200
 
 
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)
1206
 
 
1207
 
    def test_handle_delete_dhcp_owner_port(self):
1208
 
        port = {
1209
 
            'id': 'foo_port_id',
1210
 
            'device_owner': n_consts.DEVICE_OWNER_DHCP,
1211
 
            'network_id': 'foo_network_id',
1212
 
            'fixed_ips': [],
1213
 
            'mac_address': 'aa:bb:cc:dd:ee:ff'
1214
 
        }
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'])
1218
 
 
1219
 
    def _test_handle_user_port(self, action, handler):
1220
 
        port = {
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'}]
1227
 
        }
1228
 
        expected_data = {
1229
 
            'ip_address': '1.2.3.4',
1230
 
            'mac_address': 'aa:bb:cc:dd:ee:ff'
1231
 
        }
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)
1236
 
 
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)
1240
 
 
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)
1244
 
 
1245
 
    def _test_handle_user_port_disabled_dhcp(self, action, handler):
1246
 
        port = {
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'}]
1253
 
        }
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)
1257
 
 
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)
1261
 
 
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)
1265
 
 
1266
 
    def _test_handle_user_port_no_fixed_ips(self, action, handler):
1267
 
        port = {
1268
 
            'id': 'foo_port_id',
1269
 
            'device_owner': 'foo_device_owner',
1270
 
            'network_id': 'foo_network_id',
1271
 
            'fixed_ips': []
1272
 
        }
1273
 
        nsx.handle_port_dhcp_access(self.plugin, mock.ANY, port, action)
1274
 
        self.assertEqual(0, handler.call_count)
1275
 
 
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)
1279
 
 
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)
1283
 
 
1284
 
 
1285
 
class MetadataTestCase(base.BaseTestCase):
1286
 
 
1287
 
    def setUp(self):
1288
 
        super(MetadataTestCase, self).setUp()
1289
 
        self.plugin = mock.Mock()
1290
 
        self.plugin.lsn_manager = mock.Mock()
1291
 
 
1292
 
    def _test_handle_port_metadata_access_special_owners(
1293
 
        self, owner, dev_id='foo_device_id', ips=None):
1294
 
        port = {
1295
 
            'id': 'foo_port_id',
1296
 
            'device_owner': owner,
1297
 
            'device_id': dev_id,
1298
 
            'fixed_ips': ips or []
1299
 
        }
1300
 
        nsx.handle_port_metadata_access(self.plugin, mock.ANY, port, mock.ANY)
1301
 
        self.assertFalse(
1302
 
            self.plugin.lsn_manager.lsn_port_meta_host_add.call_count)
1303
 
        self.assertFalse(
1304
 
            self.plugin.lsn_manager.lsn_port_meta_host_remove.call_count)
1305
 
 
1306
 
    def test_handle_port_metadata_access_external_network(self):
1307
 
        port = {
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'}]
1313
 
        }
1314
 
        self.plugin.get_network.return_value = {'router:external': True}
1315
 
        nsx.handle_port_metadata_access(self.plugin, mock.ANY, port, mock.ANY)
1316
 
        self.assertFalse(
1317
 
            self.plugin.lsn_manager.lsn_port_meta_host_add.call_count)
1318
 
        self.assertFalse(
1319
 
            self.plugin.lsn_manager.lsn_port_meta_host_remove.call_count)
1320
 
 
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'}])
1324
 
 
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'}])
1328
 
 
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, '')
1332
 
 
1333
 
    def test_handle_port_metadata_access_no_fixed_ips(self):
1334
 
        self._test_handle_port_metadata_access_special_owners(
1335
 
            'foo', 'foo', None)
1336
 
 
1337
 
    def _test_handle_port_metadata_access(self, is_delete, raise_exc=False):
1338
 
        port = {
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',
1344
 
            'fixed_ips': [
1345
 
                {'subnet_id': 'foo_subnet_id', 'ip_address': '1.2.3.4'}
1346
 
            ]
1347
 
        }
1348
 
        meta = {
1349
 
            'instance_id': port['device_id'],
1350
 
            'tenant_id': port['tenant_id'],
1351
 
            'ip_address': port['fixed_ips'][0]['ip_address']
1352
 
        }
1353
 
        self.plugin.get_network.return_value = {'router:external': False}
1354
 
        if is_delete:
1355
 
            mock_func = self.plugin.lsn_manager.lsn_port_meta_host_remove
1356
 
        else:
1357
 
            mock_func = self.plugin.lsn_manager.lsn_port_meta_host_add
1358
 
        if raise_exc:
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)
1367
 
                if not is_delete:
1368
 
                    d.assert_called_once_with(mock.ANY, mock.ANY, port['id'])
1369
 
                else:
1370
 
                    self.assertFalse(d.call_count)
1371
 
        else:
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)
1375
 
 
1376
 
    def test_handle_port_metadata_access_on_delete_true(self):
1377
 
        self._test_handle_port_metadata_access(True)
1378
 
 
1379
 
    def test_handle_port_metadata_access_on_delete_false(self):
1380
 
        self._test_handle_port_metadata_access(False)
1381
 
 
1382
 
    def test_handle_port_metadata_access_on_delete_true_raise(self):
1383
 
        self._test_handle_port_metadata_access(True, raise_exc=True)
1384
 
 
1385
 
    def test_handle_port_metadata_access_on_delete_false_raise(self):
1386
 
        self._test_handle_port_metadata_access(False, raise_exc=True)
1387
 
 
1388
 
    def _test_handle_router_metadata_access(
1389
 
        self, is_port_found, raise_exc=False):
1390
 
        subnet = {
1391
 
            'id': 'foo_subnet_id',
1392
 
            'network_id': 'foo_network_id'
1393
 
        }
1394
 
        interface = {
1395
 
            'subnet_id': subnet['id'],
1396
 
            'port_id': 'foo_port_id'
1397
 
        }
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
1401
 
        if raise_exc:
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',
1408
 
                                  interface)
1409
 
                d.assert_called_once_with(mock.ANY, mock.ANY, 'foo_router_id',
1410
 
                                          interface)
1411
 
        else:
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)
1416
 
 
1417
 
    def test_handle_router_metadata_access_add_interface(self):
1418
 
        self._test_handle_router_metadata_access(True)
1419
 
 
1420
 
    def test_handle_router_metadata_access_delete_interface(self):
1421
 
        self._test_handle_router_metadata_access(False)
1422
 
 
1423
 
    def test_handle_router_metadata_access_raise_error_on_add(self):
1424
 
        self._test_handle_router_metadata_access(True, raise_exc=True)
1425
 
 
1426
 
    def test_handle_router_metadata_access_raise_error_on_delete(self):
1427
 
        self._test_handle_router_metadata_access(True, raise_exc=False)