~ubuntu-branches/ubuntu/saucy/nova/saucy-proposed

« back to all changes in this revision

Viewing changes to nova/tests/network/test_quantum.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-24 13:12:53 UTC
  • mfrom: (1.1.55)
  • Revision ID: package-import@ubuntu.com-20120524131253-ommql08fg1en06ut
Tags: 2012.2~f1-0ubuntu1
* New upstream release.
* Prepare for quantal:
  - Dropped debian/patches/upstream/0006-Use-project_id-in-ec2.cloud._format_image.patch
  - Dropped debian/patches/upstream/0005-Populate-image-properties-with-project_id-again.patch
  - Dropped debian/patches/upstream/0004-Fixed-bug-962840-added-a-test-case.patch
  - Dropped debian/patches/upstream/0003-Allow-unprivileged-RADOS-users-to-access-rbd-volumes.patch
  - Dropped debian/patches/upstream/0002-Stop-libvirt-test-from-deleting-instances-dir.patch
  - Dropped debian/patches/upstream/0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch 
  - Dropped debian/patches/0001-fix-useexisting-deprecation-warnings.patch
* debian/control: Add python-keystone as a dependency. (LP: #907197)
* debian/patches/kombu_tests_timeout.patch: Refreshed.
* debian/nova.conf, debian/nova-common.postinst: Convert to new ini
  file configuration
* debian/patches/nova-manage_flagfile_location.patch: Refreshed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2011,2012 Nicira, Inc.
 
4
# All Rights Reserved.
 
5
#
 
6
# Licensed under the Apache License, Version 2.0 (the "License"); you may
 
7
# not use this file except in compliance with the License. You may obtain
 
8
# a copy of the License at
 
9
#
 
10
#      http://www.apache.org/licenses/LICENSE-2.0
 
11
#
 
12
# Unless required by applicable law or agreed to in writing, software
 
13
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
14
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
15
# License for the specific language governing permissions and limitations
 
16
# under the License.
 
17
 
 
18
import mox
 
19
 
 
20
from nova import context
 
21
from nova import db
 
22
from nova.db.sqlalchemy import models
 
23
from nova.db.sqlalchemy import session as sql_session
 
24
from nova import exception
 
25
from nova import flags
 
26
from nova import log as logging
 
27
from nova.network.quantum import client as quantum_client
 
28
from nova.network.quantum import fake_client
 
29
from nova.network.quantum import manager as quantum_manager
 
30
from nova.network.quantum import melange_connection
 
31
from nova.network.quantum import melange_ipam_lib
 
32
from nova.network.quantum import quantum_connection
 
33
 
 
34
from nova import test
 
35
from nova import utils
 
36
 
 
37
LOG = logging.getLogger(__name__)
 
38
FLAGS = flags.FLAGS
 
39
 
 
40
 
 
41
networks = [{'label': 'project1-net1',
 
42
             'injected': False,
 
43
             'multi_host': False,
 
44
             'cidr': '100.168.0.0/24',
 
45
             'cidr_v6': '100:1db8::/64',
 
46
             'gateway_v6': '100:1db8::1',
 
47
             'netmask_v6': '64',
 
48
             'netmask': '255.255.255.0',
 
49
             'bridge': None,
 
50
             'bridge_interface': None,
 
51
             'gateway': '100.168.0.1',
 
52
             'broadcast': '100.168.0.255',
 
53
             'dns1': '8.8.8.8',
 
54
             'vlan': None,
 
55
             'host': None,
 
56
             'vpn_public_address': None,
 
57
             'project_id': 'fake_project1',
 
58
             'priority': 1},
 
59
            {'label': 'project2-net1',
 
60
             'injected': False,
 
61
             'multi_host': False,
 
62
             'cidr': '101.168.1.0/24',
 
63
             'cidr_v6': '101:1db9::/64',
 
64
             'gateway_v6': '101:1db9::1',
 
65
             'netmask_v6': '64',
 
66
             'netmask': '255.255.255.0',
 
67
             'bridge': None,
 
68
             'bridge_interface': None,
 
69
             'gateway': '101.168.1.1',
 
70
             'broadcast': '101.168.1.255',
 
71
             'dns1': '8.8.8.8',
 
72
             'vlan': None,
 
73
             'host': None,
 
74
             'project_id': 'fake_project2',
 
75
             'priority': 1},
 
76
             {'label': "public",
 
77
             'injected': False,
 
78
             'multi_host': False,
 
79
             'cidr': '102.0.0.0/24',
 
80
             'cidr_v6': '102:1dba::/64',
 
81
             'gateway_v6': '102:1dba::1',
 
82
             'netmask_v6': '64',
 
83
             'netmask': '255.255.255.0',
 
84
             'bridge': None,
 
85
             'bridge_interface': None,
 
86
             'gateway': '102.0.0.1',
 
87
             'broadcast': '102.0.0.255',
 
88
             'dns1': '8.8.8.8',
 
89
             'vlan': None,
 
90
             'host': None,
 
91
             'project_id': None,
 
92
             'priority': 0},
 
93
             {'label': "project2-net2",
 
94
             'injected': False,
 
95
             'multi_host': False,
 
96
             'cidr': '103.0.0.0/24',
 
97
             'cidr_v6': '103:1dbb::/64',
 
98
             'gateway_v6': '103:1dbb::1',
 
99
             'netmask_v6': '64',
 
100
             'netmask': '255.255.255.0',
 
101
             'bridge': None,
 
102
             'bridge_interface': None,
 
103
             'gateway': '103.0.0.1',
 
104
             'broadcast': '103.0.0.255',
 
105
             'dns1': '8.8.8.8',
 
106
             'vlan': None,
 
107
             'host': None,
 
108
             'project_id': "fake_project2",
 
109
             'priority': 2}]
 
110
 
 
111
 
 
112
class QuantumConnectionTestCase(test.TestCase):
 
113
 
 
114
    def test_connection(self):
 
115
        fc = fake_client.FakeClient(LOG)
 
116
        qc = quantum_connection.QuantumClientConnection(client=fc)
 
117
        t = "tenant1"
 
118
        net1_name = "net1"
 
119
        net1_uuid = qc.create_network(t, net1_name)
 
120
        self.assertEquals(net1_name, qc.get_network_name(t, net1_uuid))
 
121
        self.assertTrue(qc.network_exists(t, net1_uuid))
 
122
        self.assertFalse(qc.network_exists(t, "fake-uuid"))
 
123
        self.assertFalse(qc.network_exists("fake-tenant", net1_uuid))
 
124
 
 
125
        nets = qc.get_networks(t)['networks']
 
126
        self.assertEquals(len(nets), 1)
 
127
        self.assertEquals(nets[0]['id'], net1_uuid)
 
128
 
 
129
        num_ports = 10
 
130
        for i in range(0, num_ports):
 
131
            qc.create_and_attach_port(t, net1_uuid,
 
132
                                'iface' + str(i), state='ACTIVE')
 
133
 
 
134
        self.assertEquals(len(qc.get_attached_ports(t, net1_uuid)), num_ports)
 
135
 
 
136
        for i in range(0, num_ports):
 
137
            port_uuid = qc.get_port_by_attachment(t, net1_uuid,
 
138
                                'iface' + str(i))
 
139
            self.assertTrue(port_uuid)
 
140
            qc.detach_and_delete_port(t, net1_uuid, port_uuid)
 
141
 
 
142
        self.assertEquals(len(qc.get_attached_ports(t, net1_uuid)), 0)
 
143
 
 
144
        # test port not found
 
145
        qc.create_and_attach_port(t, net1_uuid, 'foo', state='ACTIVE')
 
146
        port_uuid = qc.get_port_by_attachment(t, net1_uuid, 'foo')
 
147
        qc.detach_and_delete_port(t, net1_uuid, port_uuid)
 
148
        self.assertRaises(quantum_client.QuantumNotFoundException,
 
149
                            qc.detach_and_delete_port, t,
 
150
                            net1_uuid, port_uuid)
 
151
 
 
152
        qc.delete_network(t, net1_uuid)
 
153
        self.assertFalse(qc.network_exists(t, net1_uuid))
 
154
        self.assertEquals(len(qc.get_networks(t)['networks']), 0)
 
155
 
 
156
        self.assertRaises(quantum_client.QuantumNotFoundException,
 
157
                            qc.get_network_name, t, net1_uuid)
 
158
 
 
159
 
 
160
# this is a base class to be used by other QuantumManager Test classes
 
161
class QuantumNovaTestCase(test.TestCase):
 
162
 
 
163
    def setUp(self):
 
164
        super(QuantumNovaTestCase, self).setUp()
 
165
 
 
166
        self.flags(quantum_use_dhcp=True)
 
167
        self.flags(l3_lib="nova.network.l3.LinuxNetL3")
 
168
        linuxdrv = "nova.network.linux_net.LinuxOVSInterfaceDriver"
 
169
        self.flags(linuxnet_interface_driver=linuxdrv)
 
170
        fc = fake_client.FakeClient(LOG)
 
171
        qc = quantum_connection.QuantumClientConnection(client=fc)
 
172
 
 
173
        self.net_man = quantum_manager.QuantumManager(
 
174
                ipam_lib="nova.network.quantum.nova_ipam_lib",
 
175
                q_conn=qc)
 
176
 
 
177
        def func(arg1, arg2):
 
178
            pass
 
179
 
 
180
        def func2(arg1, arg2, arg3):
 
181
            pass
 
182
 
 
183
        def func1(arg1):
 
184
            pass
 
185
 
 
186
        self.net_man.driver.update_dhcp_hostfile_with_text = func
 
187
        self.net_man.driver.restart_dhcp = func2
 
188
        self.net_man.driver.kill_dhcp = func1
 
189
 
 
190
        # Tests seem to create some networks by default, which
 
191
        # we don't want.  So we delete them.
 
192
 
 
193
        ctx = context.RequestContext('user1', 'fake_project1').elevated()
 
194
        for n in db.network_get_all(ctx):
 
195
            db.network_delete_safe(ctx, n['id'])
 
196
 
 
197
        # Other unit tests (e.g., test_compute.py) have a nasty
 
198
        # habit of of creating fixed IPs and not cleaning up, which
 
199
        # can confuse these tests, so we remove all existing fixed
 
200
        # ips before starting.
 
201
        session = sql_session.get_session()
 
202
        result = session.query(models.FixedIp).all()
 
203
        with session.begin():
 
204
            for fip_ref in result:
 
205
                session.delete(fip_ref)
 
206
 
 
207
        self.net_man.init_host()
 
208
 
 
209
    def _create_network(self, n):
 
210
        ctx = context.RequestContext('user1', n['project_id'])
 
211
        nwks = self.net_man.create_networks(
 
212
            ctx,
 
213
            label=n['label'], cidr=n['cidr'],
 
214
            multi_host=n['multi_host'],
 
215
            num_networks=1, network_size=256,
 
216
            cidr_v6=n['cidr_v6'],
 
217
            gateway=n['gateway'],
 
218
            gateway_v6=n['gateway_v6'], bridge=None,
 
219
            bridge_interface=None, dns1=n['dns1'],
 
220
            project_id=n['project_id'],
 
221
            priority=n['priority'])
 
222
        n['uuid'] = nwks[0]['uuid']
 
223
 
 
224
 
 
225
class QuantumAllocationTestCase(QuantumNovaTestCase):
 
226
    def test_get_network_in_db(self):
 
227
        context = self.mox.CreateMockAnything()
 
228
        context.elevated().AndReturn('elevated')
 
229
        self.mox.StubOutWithMock(db, 'network_get_by_uuid')
 
230
        self.net_man.context = context
 
231
        db.network_get_by_uuid('elevated', 'quantum_net_id').AndReturn(
 
232
                                                                {'uuid': 1})
 
233
 
 
234
        self.mox.ReplayAll()
 
235
 
 
236
        network = self.net_man.get_network(context, ('quantum_net_id',
 
237
                                                     'net_tenant_id'))
 
238
        self.assertEquals(network['quantum_net_id'], 'quantum_net_id')
 
239
        self.assertEquals(network['uuid'], 1)
 
240
 
 
241
    def test_get_network_not_in_db(self):
 
242
        context = self.mox.CreateMockAnything()
 
243
        context.elevated().AndReturn('elevated')
 
244
        self.mox.StubOutWithMock(db, 'network_get_by_uuid')
 
245
        self.net_man.context = context
 
246
        db.network_get_by_uuid('elevated', 'quantum_net_id').AndReturn(None)
 
247
 
 
248
        self.mox.ReplayAll()
 
249
 
 
250
        network = self.net_man.get_network(context, ('quantum_net_id',
 
251
                                                     'net_tenant_id'))
 
252
        self.assertEquals(network['quantum_net_id'], 'quantum_net_id')
 
253
        self.assertEquals(network['uuid'], 'quantum_net_id')
 
254
 
 
255
 
 
256
class QuantumDeallocationTestCase(QuantumNovaTestCase):
 
257
    def test_deallocate_port(self):
 
258
        quantum = self.mox.CreateMock(
 
259
                                quantum_connection.QuantumClientConnection)
 
260
        quantum.get_port_by_attachment('q_tenant_id', 'net_id',
 
261
                                       'interface_id').AndReturn('port_id')
 
262
        quantum.detach_and_delete_port('q_tenant_id', 'net_id', 'port_id')
 
263
        self.net_man.q_conn = quantum
 
264
 
 
265
        self.mox.ReplayAll()
 
266
 
 
267
        self.net_man.deallocate_port('interface_id', 'net_id', 'q_tenant_id',
 
268
                                     'instance_id')
 
269
 
 
270
    def test_deallocate_port_logs_error(self):
 
271
        quantum = self.mox.CreateMock(
 
272
            quantum_connection.QuantumClientConnection)
 
273
        quantum.get_port_by_attachment('q_tenant_id', 'net_id',
 
274
                            'interface_id').AndRaise(Exception)
 
275
        self.net_man.q_conn = quantum
 
276
 
 
277
        self.mox.StubOutWithMock(quantum_manager.LOG, 'exception')
 
278
        quantum_manager.LOG.exception(mox.Regex(r'port deallocation failed'))
 
279
 
 
280
        self.mox.ReplayAll()
 
281
 
 
282
        self.net_man.deallocate_port('interface_id', 'net_id', 'q_tenant_id',
 
283
                                     'instance_id')
 
284
 
 
285
    def test_deallocate_ip_address(self):
 
286
        ipam = self.mox.CreateMock(melange_ipam_lib.QuantumMelangeIPAMLib)
 
287
        ipam.get_tenant_id_by_net_id('context', 'net_id', {'uuid': 1},
 
288
                                     'project_id').AndReturn('ipam_tenant_id')
 
289
        self.net_man.ipam = ipam
 
290
        self.mox.ReplayAll()
 
291
        self.net_man.deallocate_ip_address('context', 'net_id', 'project_id',
 
292
                {'uuid': 1}, 'instance_id')
 
293
 
 
294
    def test_deallocate_ip_address(self):
 
295
        ipam = self.mox.CreateMock(melange_ipam_lib.QuantumMelangeIPAMLib)
 
296
        ipam.get_tenant_id_by_net_id('context', 'net_id', {'uuid': 1},
 
297
                                     'project_id').AndRaise(Exception())
 
298
        self.net_man.ipam = ipam
 
299
 
 
300
        self.mox.StubOutWithMock(quantum_manager.LOG, 'exception')
 
301
        quantum_manager.LOG.exception(mox.Regex(r'ipam deallocation failed'))
 
302
 
 
303
        self.mox.ReplayAll()
 
304
        self.net_man.deallocate_ip_address('context', 'net_id', 'project_id',
 
305
                {'uuid': 1}, 'instance_id')
 
306
 
 
307
 
 
308
class QuantumManagerTestCase(QuantumNovaTestCase):
 
309
    def test_create_and_delete_nets(self):
 
310
        self._create_nets()
 
311
        self._delete_nets()
 
312
 
 
313
    def _create_nets(self):
 
314
        for n in networks:
 
315
            self._create_network(n)
 
316
 
 
317
    def _delete_nets(self):
 
318
        for n in networks:
 
319
            ctx = context.RequestContext('user1', n['project_id'])
 
320
            self.net_man.delete_network(ctx, None, n['uuid'])
 
321
        self.assertRaises(exception.NoNetworksFound,
 
322
                          db.network_get_all, ctx.elevated())
 
323
 
 
324
    def _validate_nw_info(self, nw_info, expected_net_labels):
 
325
 
 
326
        self.assertEquals(len(nw_info), len(expected_net_labels))
 
327
 
 
328
        ctx = context.RequestContext('user1', 'foo').elevated()
 
329
        all_net_map = {}
 
330
        for n in db.network_get_all(ctx):
 
331
            all_net_map[n['label']] = n
 
332
 
 
333
        for i in range(0, len(nw_info)):
 
334
            vif = nw_info[i]
 
335
            net = all_net_map[expected_net_labels[i]]
 
336
 
 
337
            # simple test assumes that each starting prefix is unique
 
338
            expected_v4_cidr_start = net['cidr'].split(".")[0].lower()
 
339
            expected_v6_cidr_start = net['cidr_v6'].split(":")[0].lower()
 
340
 
 
341
            for subnet in vif['network']['subnets']:
 
342
                addr = subnet['ips'][0]['address']
 
343
                if subnet['version'] == 4:
 
344
                    address_start = addr.split(".")[0].lower()
 
345
                    self.assertTrue(expected_v4_cidr_start, address_start)
 
346
                else:
 
347
                    address_start = addr.split(":")[0].lower()
 
348
                    self.assertTrue(expected_v6_cidr_start, address_start)
 
349
 
 
350
        # confirm that there is a DHCP device on corresponding net
 
351
        for l in expected_net_labels:
 
352
            n = all_net_map[l]
 
353
            tenant_id = (n['project_id'] or
 
354
                                FLAGS.quantum_default_tenant_id)
 
355
            ports = self.net_man.q_conn.get_attached_ports(
 
356
                                                    tenant_id, n['uuid'])
 
357
            self.assertEquals(len(ports), 2)  # gw + instance VIF
 
358
 
 
359
            # make sure we aren't allowed to delete network with
 
360
            # active port
 
361
            self.assertRaises(exception.NetworkBusy,
 
362
                              self.net_man.delete_network,
 
363
                              ctx, None, n['uuid'])
 
364
 
 
365
    def _check_vifs(self, expect_num_vifs):
 
366
        ctx = context.RequestContext('user1', "").elevated()
 
367
        self.assertEqual(len(db.virtual_interface_get_all(ctx)),
 
368
                        expect_num_vifs)
 
369
 
 
370
    def _allocate_and_deallocate_instance(self, project_id, requested_networks,
 
371
                                            expected_labels):
 
372
 
 
373
        ctx = context.RequestContext('user1', project_id)
 
374
        self._check_vifs(0)
 
375
 
 
376
        instance_ref = db.instance_create(ctx,
 
377
                                    {"project_id": project_id})
 
378
 
 
379
        nw_info = self.net_man.allocate_for_instance(ctx.elevated(),
 
380
                        instance_id=instance_ref['id'], host="",
 
381
                        rxtx_factor=3,
 
382
                        project_id=project_id,
 
383
                        requested_networks=requested_networks)
 
384
 
 
385
        self._check_vifs(len(nw_info))
 
386
 
 
387
        self._validate_nw_info(nw_info, expected_labels)
 
388
 
 
389
        nw_info = self.net_man.get_instance_nw_info(ctx, instance_ref['id'],
 
390
                                instance_ref['uuid'],
 
391
                                instance_ref['instance_type_id'], "",
 
392
                                project_id=project_id)
 
393
 
 
394
        self._check_vifs(len(nw_info))
 
395
        self._validate_nw_info(nw_info, expected_labels)
 
396
 
 
397
        port_net_pairs = []
 
398
        for vif in nw_info:
 
399
            nid = vif['network']['id']
 
400
            pid = self.net_man.q_conn.get_port_by_attachment(
 
401
                                project_id, nid, vif['id'])
 
402
            if pid is None:
 
403
                pid = self.net_man.q_conn.get_port_by_attachment(
 
404
                                FLAGS.quantum_default_tenant_id,
 
405
                                nid, vif['id'])
 
406
            self.assertTrue(pid is not None)
 
407
            port_net_pairs.append((pid, nid))
 
408
 
 
409
        self.net_man.deallocate_for_instance(ctx,
 
410
                    instance_id=instance_ref['id'],
 
411
                    project_id=project_id)
 
412
 
 
413
        for pid, nid in port_net_pairs:
 
414
            self.assertRaises(quantum_client.QuantumNotFoundException,
 
415
                            self.net_man.q_conn.detach_and_delete_port,
 
416
                            project_id, nid, pid)
 
417
            self.assertRaises(quantum_client.QuantumNotFoundException,
 
418
                            self.net_man.q_conn.detach_and_delete_port,
 
419
                            FLAGS.quantum_default_tenant_id, nid, pid)
 
420
 
 
421
        self._check_vifs(0)
 
422
 
 
423
    def test_allocate_and_deallocate_instance_static(self):
 
424
        self._create_nets()
 
425
        self._allocate_and_deallocate_instance("fake_project1", None,
 
426
                                 ['public', 'project1-net1'])
 
427
        self._delete_nets()
 
428
 
 
429
    def test_allocate_and_deallocate_instance_dynamic(self):
 
430
 
 
431
        self._create_nets()
 
432
        project_id = "fake_project2"
 
433
        ctx = context.RequestContext('user1', project_id)
 
434
        all_valid_networks = self.net_man.ipam.get_project_and_global_net_ids(
 
435
                                                               ctx, project_id)
 
436
        requested_networks = [(n[0], None) for n in all_valid_networks]
 
437
 
 
438
        self.net_man.validate_networks(ctx, requested_networks)
 
439
 
 
440
        label_map = {}
 
441
        for n in db.network_get_all(ctx.elevated()):
 
442
            label_map[n['uuid']] = n['label']
 
443
        expected_labels = [label_map[uid] for uid, _i in requested_networks]
 
444
 
 
445
        self._allocate_and_deallocate_instance(project_id, requested_networks,
 
446
                                              expected_labels)
 
447
        self._delete_nets()
 
448
 
 
449
    def test_validate_bad_network(self):
 
450
        ctx = context.RequestContext('user1', 'fake_project1')
 
451
        self.assertRaises(exception.NetworkNotFound,
 
452
                        self.net_man.validate_networks, ctx, [("", None)])
 
453
 
 
454
    def test_create_net_external_uuid(self):
 
455
        """Tests use case where network can be created directly via
 
456
           Quantum API, then the UUID is passed in via nova-manage"""
 
457
        project_id = "foo_project"
 
458
        ctx = context.RequestContext('user1', project_id)
 
459
        net_id = self.net_man.q_conn.create_network(project_id, 'net1')
 
460
        self.net_man.create_networks(
 
461
            ctx,
 
462
            label='achtungbaby',
 
463
            cidr="9.9.9.0/24",
 
464
            multi_host=False,
 
465
            num_networks=1,
 
466
            network_size=256,
 
467
            cidr_v6=None,
 
468
            gateway="9.9.9.1",
 
469
            gateway_v6=None,
 
470
            bridge=None,
 
471
            bridge_interface=None,
 
472
            dns1="8.8.8.8",
 
473
            project_id=project_id,
 
474
            priority=9,
 
475
            uuid=net_id)
 
476
        net = db.network_get_by_uuid(ctx.elevated(), net_id)
 
477
        self.assertTrue(net is not None)
 
478
        self.assertEquals(net['uuid'], net_id)
 
479
 
 
480
    def test_create_net_external_uuid_and_host_is_set(self):
 
481
        """Make sure network['host'] is set when creating a network via the
 
482
           network manager"""
 
483
        project_id = "foo_project"
 
484
        ctx = context.RequestContext('user1', project_id)
 
485
        net_id = self.net_man.q_conn.create_network(project_id, 'net2')
 
486
        self.net_man.create_networks(
 
487
            ctx, label='achtungbaby2', cidr="9.9.8.0/24", multi_host=False,
 
488
            num_networks=1, network_size=256, cidr_v6=None,
 
489
            gateway="9.9.8.1", gateway_v6=None, bridge=None,
 
490
            bridge_interface=None, dns1="8.8.8.8", project_id=project_id,
 
491
            priority=8, uuid=net_id)
 
492
        net = db.network_get_by_uuid(ctx.elevated(), net_id)
 
493
        self.assertTrue(net is not None)
 
494
        self.assertEquals(net['uuid'], net_id)
 
495
        self.assertTrue(net['host'] != None)
 
496
 
 
497
 
 
498
class QuantumNovaMACGenerationTestCase(QuantumNovaTestCase):
 
499
    def test_local_mac_address_creation(self):
 
500
        self.flags(use_melange_mac_generation=False)
 
501
        fake_mac = "ab:cd:ef:ab:cd:ef"
 
502
        self.stubs.Set(utils, "generate_mac_address",
 
503
                       lambda: fake_mac)
 
504
        project_id = "fake_project1"
 
505
        ctx = context.RequestContext('user1', project_id)
 
506
        self._create_network(networks[0])
 
507
 
 
508
        all_valid_networks = self.net_man.ipam.get_project_and_global_net_ids(
 
509
                                                               ctx, project_id)
 
510
        requested_networks = [(n[0], None) for n in all_valid_networks]
 
511
 
 
512
        instance_ref = db.api.instance_create(ctx,
 
513
                                    {"project_id": project_id})
 
514
        nw_info = self.net_man.allocate_for_instance(ctx,
 
515
                        instance_id=instance_ref['id'], host="",
 
516
                        rxtx_factor=3,
 
517
                        project_id=project_id,
 
518
                        requested_networks=requested_networks)
 
519
        self.assertEqual(nw_info[0]['address'], fake_mac)
 
520
 
 
521
    def test_melange_mac_address_creation(self):
 
522
        self.flags(use_melange_mac_generation=True)
 
523
        fake_mac = "ab:cd:ef:ab:cd:ef"
 
524
        self.stubs.Set(melange_connection.MelangeConnection, "create_vif",
 
525
                       lambda w, x, y, z: fake_mac)
 
526
        project_id = "fake_project1"
 
527
        ctx = context.RequestContext('user1', project_id)
 
528
        self._create_network(networks[0])
 
529
 
 
530
        all_valid_networks = self.net_man.ipam.get_project_and_global_net_ids(
 
531
                                                               ctx, project_id)
 
532
        requested_networks = [(n[0], None) for n in all_valid_networks]
 
533
 
 
534
        instance_ref = db.api.instance_create(ctx,
 
535
                                    {"project_id": project_id})
 
536
        nw_info = self.net_man.allocate_for_instance(ctx,
 
537
                        instance_id=instance_ref['id'], host="",
 
538
                        rxtx_factor=3,
 
539
                        project_id=project_id,
 
540
                        requested_networks=requested_networks)
 
541
        self.assertEqual(nw_info[0]['address'], fake_mac)
 
542
 
 
543
 
 
544
class QuantumNovaPortSecurityTestCase(QuantumNovaTestCase):
 
545
    def test_port_securty(self):
 
546
        self.flags(use_melange_mac_generation=True)
 
547
        self.flags(quantum_use_port_security=True)
 
548
        fake_mac = "ab:cd:ef:ab:cd:ef"
 
549
        self.stubs.Set(melange_connection.MelangeConnection, "create_vif",
 
550
                       lambda w, x, y, z: fake_mac)
 
551
        project_id = "fake_project1"
 
552
        ctx = context.RequestContext('user1', project_id)
 
553
        self._create_network(networks[0])
 
554
 
 
555
        all_valid_networks = self.net_man.ipam.get_project_and_global_net_ids(
 
556
                                                               ctx, project_id)
 
557
        requested_networks = [(n[0], None) for n in all_valid_networks]
 
558
 
 
559
        instance_ref = db.api.instance_create(ctx,
 
560
                                    {"project_id": project_id})
 
561
        oldfunc = self.net_man.q_conn.create_and_attach_port
 
562
 
 
563
        # Make sure we get the appropriate mac set in allowed_address_pairs
 
564
        # if port security is enabled.
 
565
        def _instrumented_create_and_attach_port(tenant_id, net_id,
 
566
                                                 interface_id, **kwargs):
 
567
            self.assertTrue('allowed_address_pairs' in kwargs.keys())
 
568
            pairs = kwargs['allowed_address_pairs']
 
569
            self.assertTrue(pairs[0]['mac_address'] == fake_mac)
 
570
            self.net_man.q_conn.create_and_attach_port = oldfunc
 
571
            return oldfunc(tenant_id, net_id, interface_id, **kwargs)
 
572
        _port_attach = _instrumented_create_and_attach_port
 
573
        self.net_man.q_conn.create_and_attach_port = _port_attach
 
574
        nw_info = self.net_man.allocate_for_instance(ctx,
 
575
                        instance_id=instance_ref['id'], host="",
 
576
                        rxtx_factor=3,
 
577
                        project_id=project_id,
 
578
                        requested_networks=requested_networks)
 
579
        self.assertEqual(nw_info[0]['address'], fake_mac)
 
580
 
 
581
    def test_port_securty_negative(self):
 
582
        self.flags(use_melange_mac_generation=True)
 
583
        self.flags(quantum_use_port_security=False)
 
584
        fake_mac = "ab:cd:ef:ab:cd:ef"
 
585
        self.stubs.Set(melange_connection.MelangeConnection, "create_vif",
 
586
                       lambda w, x, y, z: fake_mac)
 
587
        project_id = "fake_project1"
 
588
        ctx = context.RequestContext('user1', project_id)
 
589
        self._create_network(networks[0])
 
590
 
 
591
        all_valid_networks = self.net_man.ipam.get_project_and_global_net_ids(
 
592
                                                               ctx, project_id)
 
593
        requested_networks = [(n[0], None) for n in all_valid_networks]
 
594
 
 
595
        instance_ref = db.api.instance_create(ctx,
 
596
                                    {"project_id": project_id})
 
597
        oldfunc = self.net_man.q_conn.create_and_attach_port
 
598
 
 
599
        # Make sure no pairs are passed in if port security is turned off
 
600
        def _instrumented_create_and_attach_port(tenant_id, net_id,
 
601
                                                 interface_id, **kwargs):
 
602
            self.assertTrue('allowed_address_pairs' in kwargs.keys())
 
603
            pairs = kwargs['allowed_address_pairs']
 
604
            self.assertTrue(len(pairs) == 0)
 
605
            self.net_man.q_conn.create_and_attach_port = oldfunc
 
606
            return oldfunc(tenant_id, net_id, interface_id, **kwargs)
 
607
        _port_attach = _instrumented_create_and_attach_port
 
608
        self.net_man.q_conn.create_and_attach_port = _port_attach
 
609
        nw_info = self.net_man.allocate_for_instance(ctx,
 
610
                        instance_id=instance_ref['id'], host="",
 
611
                        rxtx_factor=3,
 
612
                        project_id=project_id,
 
613
                        requested_networks=requested_networks)
 
614
        self.assertEqual(nw_info[0]['address'], fake_mac)
 
615
 
 
616
 
 
617
class QuantumMelangeTestCase(test.TestCase):
 
618
    def setUp(self):
 
619
        super(QuantumMelangeTestCase, self).setUp()
 
620
 
 
621
        fc = fake_client.FakeClient(LOG)
 
622
        qc = quantum_connection.QuantumClientConnection(client=fc)
 
623
 
 
624
        self.net_man = quantum_manager.QuantumManager(
 
625
            ipam_lib="nova.network.quantum.nova_ipam_lib",
 
626
            q_conn=qc)
 
627
 
 
628
    def test_get_instance_uuids_by_ip_filter(self):
 
629
        fake_context = context.RequestContext('user', 'project')
 
630
        address = '1.2.3.4'
 
631
        filters = {'ip': address}
 
632
 
 
633
        self.net_man.ipam = self.mox.CreateMockAnything()
 
634
        self.net_man.ipam.get_instance_ids_by_ip_address(fake_context,
 
635
                address).AndReturn(['instance_id'])
 
636
 
 
637
        instance = self.mox.CreateMockAnything()
 
638
        instance.uuid = 'instance_uuid'
 
639
 
 
640
        self.mox.StubOutWithMock(db, 'instance_get')
 
641
        db.instance_get(fake_context, 'instance_id').AndReturn(instance)
 
642
 
 
643
        self.mox.ReplayAll()
 
644
 
 
645
        uuids = self.net_man.get_instance_uuids_by_ip_filter(fake_context,
 
646
                                                             filters)
 
647
        self.assertEquals(uuids, [{'instance_uuid':'instance_uuid'}])