~ubuntu-branches/ubuntu/trusty/heat/trusty-security

« back to all changes in this revision

Viewing changes to .pc/rename-quantumclient.patch/heat/tests/test_quantum.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Chuck Short
  • Date: 2013-08-08 01:08:42 UTC
  • Revision ID: package-import@ubuntu.com-20130808010842-77cni2v4vlib7rus
Tags: 2013.2~b2-0ubuntu4
[ Chuck Short ]
* debian/rules: Enable testsuite during builds.
* debian/patches/fix-sqlalchemy-0.8.patch: Build against sqlalchemy 0.8.
* debian/patches/rename-quantumclient.patch: quantumclient -> neutronclient.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
4
#    not use this file except in compliance with the License. You may obtain
 
5
#    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, WITHOUT
 
11
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
12
#    License for the specific language governing permissions and limitations
 
13
#    under the License.
 
14
 
 
15
 
 
16
from testtools import skipIf
 
17
 
 
18
from heat.common import exception
 
19
from heat.common import template_format
 
20
from heat.engine import properties
 
21
from heat.engine import resource
 
22
from heat.engine import scheduler
 
23
from heat.engine.resources.quantum import net
 
24
from heat.engine.resources.quantum import subnet
 
25
from heat.engine.resources.quantum import router
 
26
from heat.engine.resources.quantum.quantum import QuantumResource as qr
 
27
from heat.openstack.common.importutils import try_import
 
28
from heat.tests.common import HeatTestCase
 
29
from heat.tests import utils
 
30
from heat.tests.utils import setup_dummy_db
 
31
from heat.tests.utils import parse_stack
 
32
 
 
33
quantumclient = try_import('quantumclient.v2_0.client')
 
34
qe = try_import('quantumclient.common.exceptions')
 
35
 
 
36
quantum_template = '''
 
37
{
 
38
  "AWSTemplateFormatVersion" : "2010-09-09",
 
39
  "Description" : "Template to test Quantum resources",
 
40
  "Parameters" : {},
 
41
  "Resources" : {
 
42
    "network": {
 
43
      "Type": "OS::Quantum::Net",
 
44
      "Properties": {
 
45
        "name": "the_network"
 
46
      }
 
47
    },
 
48
    "unnamed_network": {
 
49
      "Type": "OS::Quantum::Net"
 
50
    },
 
51
    "admin_down_network": {
 
52
      "Type": "OS::Quantum::Net",
 
53
      "Properties": {
 
54
        "admin_state_up": false
 
55
      }
 
56
    },
 
57
    "subnet": {
 
58
      "Type": "OS::Quantum::Subnet",
 
59
      "Properties": {
 
60
        "network_id": { "Ref" : "network" },
 
61
        "ip_version": 4,
 
62
        "cidr": "10.0.3.0/24",
 
63
        "allocation_pools": [{"start": "10.0.3.20", "end": "10.0.3.150"}],
 
64
        "dns_nameservers": ["8.8.8.8"]
 
65
      }
 
66
    },
 
67
    "port": {
 
68
      "Type": "OS::Quantum::Port",
 
69
      "Properties": {
 
70
        "device_id": "d6b4d3a5-c700-476f-b609-1493dd9dadc0",
 
71
        "name": "port1",
 
72
        "network_id": { "Ref" : "network" },
 
73
        "fixed_ips": [{
 
74
          "subnet_id": { "Ref" : "subnet" },
 
75
          "ip_address": "10.0.3.21"
 
76
        }]
 
77
      }
 
78
    },
 
79
    "port2": {
 
80
      "Type": "OS::Quantum::Port",
 
81
      "Properties": {
 
82
        "name": "port2",
 
83
        "network_id": { "Ref" : "network" }
 
84
      }
 
85
    },
 
86
    "router": {
 
87
      "Type": "OS::Quantum::Router"
 
88
    },
 
89
    "router_interface": {
 
90
      "Type": "OS::Quantum::RouterInterface",
 
91
      "Properties": {
 
92
        "router_id": { "Ref" : "router" },
 
93
        "subnet_id": { "Ref" : "subnet" }
 
94
      }
 
95
    },
 
96
    "gateway": {
 
97
      "Type": "OS::Quantum::RouterGateway",
 
98
      "Properties": {
 
99
        "router_id": { "Ref" : "router" },
 
100
        "network_id": { "Ref" : "network" }
 
101
      }
 
102
    }
 
103
  }
 
104
}
 
105
'''
 
106
 
 
107
quantum_floating_template = '''
 
108
{
 
109
  "AWSTemplateFormatVersion" : "2010-09-09",
 
110
  "Description" : "Template to test Quantum resources",
 
111
  "Parameters" : {},
 
112
  "Resources" : {
 
113
    "port_floating": {
 
114
      "Type": "OS::Quantum::Port",
 
115
      "Properties": {
 
116
        "network_id": "xyz1234",
 
117
        "fixed_ips": [{
 
118
          "subnet_id": "12.12.12.0",
 
119
          "ip_address": "10.0.0.10"
 
120
        }]
 
121
      }
 
122
    },
 
123
    "floating_ip": {
 
124
      "Type": "OS::Quantum::FloatingIP",
 
125
      "Properties": {
 
126
        "floating_network_id": "abcd1234",
 
127
      }
 
128
    },
 
129
    "floating_ip_assoc": {
 
130
      "Type": "OS::Quantum::FloatingIPAssociation",
 
131
      "Properties": {
 
132
        "floatingip_id": { "Ref" : "floating_ip" },
 
133
        "port_id": { "Ref" : "port_floating" }
 
134
      }
 
135
    },
 
136
    "router": {
 
137
      "Type": "OS::Quantum::Router"
 
138
    },
 
139
    "gateway": {
 
140
      "Type": "OS::Quantum::RouterGateway",
 
141
      "Properties": {
 
142
        "router_id": { "Ref" : "router" },
 
143
        "network_id": "abcd1234"
 
144
      }
 
145
    }
 
146
  }
 
147
}
 
148
'''
 
149
 
 
150
 
 
151
class QuantumTest(HeatTestCase):
 
152
 
 
153
    def test_validate_properties(self):
 
154
        vs = {'router:external': True}
 
155
        data = {'admin_state_up': False,
 
156
                'value_specs': vs}
 
157
        p = properties.Properties(net.Net.properties_schema, data)
 
158
        self.assertEqual(None, qr.validate_properties(p))
 
159
 
 
160
        vs['shared'] = True
 
161
        self.assertEqual('shared not allowed in value_specs',
 
162
                         qr.validate_properties(p))
 
163
        vs.pop('shared')
 
164
 
 
165
        vs['name'] = 'foo'
 
166
        self.assertEqual('name not allowed in value_specs',
 
167
                         qr.validate_properties(p))
 
168
        vs.pop('name')
 
169
 
 
170
        vs['tenant_id'] = '1234'
 
171
        self.assertEqual('tenant_id not allowed in value_specs',
 
172
                         qr.validate_properties(p))
 
173
        vs.pop('tenant_id')
 
174
 
 
175
        vs['foo'] = '1234'
 
176
        self.assertEqual(None, qr.validate_properties(p))
 
177
 
 
178
    def test_prepare_properties(self):
 
179
        data = {'admin_state_up': False,
 
180
                'value_specs': {'router:external': True}}
 
181
        p = properties.Properties(net.Net.properties_schema, data)
 
182
        props = qr.prepare_properties(p, 'resource_name')
 
183
        self.assertEqual({'name': 'resource_name',
 
184
                          'router:external': True,
 
185
                          'admin_state_up': False}, props)
 
186
 
 
187
    def test_is_built(self):
 
188
        self.assertTrue(qr.is_built({
 
189
            'name': 'the_net',
 
190
            'status': 'ACTIVE'
 
191
        }))
 
192
        self.assertTrue(qr.is_built({
 
193
            'name': 'the_net',
 
194
            'status': 'DOWN'
 
195
        }))
 
196
        self.assertFalse(qr.is_built({
 
197
            'name': 'the_net',
 
198
            'status': 'BUILD'
 
199
        }))
 
200
        self.assertRaises(exception.Error, qr.is_built, {
 
201
            'name': 'the_net',
 
202
            'status': 'FROBULATING'
 
203
        })
 
204
 
 
205
 
 
206
@skipIf(quantumclient is None, 'quantumclient unavailable')
 
207
class QuantumNetTest(HeatTestCase):
 
208
 
 
209
    def setUp(self):
 
210
        super(QuantumNetTest, self).setUp()
 
211
        self.m.StubOutWithMock(quantumclient.Client, 'create_network')
 
212
        self.m.StubOutWithMock(quantumclient.Client, 'delete_network')
 
213
        self.m.StubOutWithMock(quantumclient.Client, 'show_network')
 
214
        setup_dummy_db()
 
215
 
 
216
    def create_net(self, t, stack, resource_name):
 
217
        rsrc = net.Net('test_net', t['Resources'][resource_name], stack)
 
218
        scheduler.TaskRunner(rsrc.create)()
 
219
        self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
 
220
        return rsrc
 
221
 
 
222
    def test_net(self):
 
223
        quantumclient.Client.create_network({
 
224
            'network': {'name': u'the_network', 'admin_state_up': True}
 
225
        }).AndReturn({"network": {
 
226
            "status": "BUILD",
 
227
            "subnets": [],
 
228
            "name": "name",
 
229
            "admin_state_up": False,
 
230
            "shared": False,
 
231
            "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
 
232
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
233
        }})
 
234
 
 
235
        quantumclient.Client.show_network(
 
236
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
237
        ).AndReturn({"network": {
 
238
            "status": "BUILD",
 
239
            "subnets": [],
 
240
            "name": "name",
 
241
            "admin_state_up": False,
 
242
            "shared": False,
 
243
            "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
 
244
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
245
        }})
 
246
 
 
247
        quantumclient.Client.show_network(
 
248
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
249
        ).AndReturn({"network": {
 
250
            "status": "ACTIVE",
 
251
            "subnets": [],
 
252
            "name": "name",
 
253
            "admin_state_up": False,
 
254
            "shared": False,
 
255
            "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
 
256
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
257
        }})
 
258
 
 
259
        quantumclient.Client.show_network(
 
260
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
261
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
262
 
 
263
        quantumclient.Client.show_network(
 
264
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
265
        ).AndReturn({"network": {
 
266
            "status": "ACTIVE",
 
267
            "subnets": [],
 
268
            "name": "name",
 
269
            "admin_state_up": False,
 
270
            "shared": False,
 
271
            "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
 
272
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
273
        }})
 
274
 
 
275
        quantumclient.Client.show_network(
 
276
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
277
        ).AndReturn({"network": {
 
278
            "status": "ACTIVE",
 
279
            "subnets": [],
 
280
            "name": "name",
 
281
            "admin_state_up": False,
 
282
            "shared": False,
 
283
            "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
 
284
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
285
        }})
 
286
 
 
287
        quantumclient.Client.delete_network(
 
288
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
289
        ).AndReturn(None)
 
290
 
 
291
        quantumclient.Client.show_network(
 
292
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
293
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
294
 
 
295
        quantumclient.Client.delete_network(
 
296
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
297
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
298
 
 
299
        self.m.ReplayAll()
 
300
        t = template_format.parse(quantum_template)
 
301
        stack = parse_stack(t)
 
302
        rsrc = self.create_net(t, stack, 'network')
 
303
 
 
304
        # assert the implicit dependency between the gateway and the interface
 
305
        deps = stack.dependencies[stack['router_interface']]
 
306
        self.assertIn(stack['gateway'], deps)
 
307
 
 
308
        # assert the implicit dependency between the gateway and the subnet
 
309
        deps = stack.dependencies[stack['subnet']]
 
310
        self.assertIn(stack['gateway'], deps)
 
311
 
 
312
        rsrc.validate()
 
313
 
 
314
        ref_id = rsrc.FnGetRefId()
 
315
        self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', ref_id)
 
316
 
 
317
        self.assertEqual(None, rsrc.FnGetAtt('status'))
 
318
        self.assertEqual('ACTIVE', rsrc.FnGetAtt('status'))
 
319
        try:
 
320
            rsrc.FnGetAtt('Foo')
 
321
            raise Exception('Expected InvalidTemplateAttribute')
 
322
        except exception.InvalidTemplateAttribute:
 
323
            pass
 
324
 
 
325
        self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766',
 
326
                         rsrc.FnGetAtt('id'))
 
327
 
 
328
        self.assertRaises(resource.UpdateReplace,
 
329
                          rsrc.handle_update, {}, {}, {})
 
330
 
 
331
        scheduler.TaskRunner(rsrc.delete)()
 
332
        rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
 
333
        scheduler.TaskRunner(rsrc.delete)()
 
334
        self.m.VerifyAll()
 
335
 
 
336
 
 
337
@skipIf(quantumclient is None, 'quantumclient unavailable')
 
338
class QuantumSubnetTest(HeatTestCase):
 
339
 
 
340
    def setUp(self):
 
341
        super(QuantumSubnetTest, self).setUp()
 
342
        self.m.StubOutWithMock(quantumclient.Client, 'create_subnet')
 
343
        self.m.StubOutWithMock(quantumclient.Client, 'delete_subnet')
 
344
        self.m.StubOutWithMock(quantumclient.Client, 'show_subnet')
 
345
        setup_dummy_db()
 
346
 
 
347
    def create_subnet(self, t, stack, resource_name):
 
348
        rsrc = subnet.Subnet('test_subnet', t['Resources'][resource_name],
 
349
                             stack)
 
350
        scheduler.TaskRunner(rsrc.create)()
 
351
        self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
 
352
        return rsrc
 
353
 
 
354
    def test_subnet(self):
 
355
 
 
356
        quantumclient.Client.create_subnet({
 
357
            'subnet': {
 
358
                'name': utils.PhysName('test_stack', 'test_subnet'),
 
359
                'network_id': u'None',
 
360
                'dns_nameservers': [u'8.8.8.8'],
 
361
                'allocation_pools': [
 
362
                    {'start': u'10.0.3.20', 'end': u'10.0.3.150'}],
 
363
                'ip_version': 4,
 
364
                'cidr': u'10.0.3.0/24'
 
365
            }
 
366
        }).AndReturn({
 
367
            "subnet": {
 
368
                "allocation_pools": [
 
369
                    {"start": "10.0.3.20", "end": "10.0.3.150"}],
 
370
                "cidr": "10.0.3.0/24",
 
371
                "dns_nameservers": ["8.8.8.8"],
 
372
                "enable_dhcp": True,
 
373
                "gateway_ip": "10.0.3.1",
 
374
                "id": "91e47a57-7508-46fe-afc9-fc454e8580e1",
 
375
                "ip_version": 4,
 
376
                "name": "name",
 
377
                "network_id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
 
378
                "tenant_id": "c1210485b2424d48804aad5d39c61b8f"
 
379
            }
 
380
        })
 
381
        quantumclient.Client.show_subnet(
 
382
            '91e47a57-7508-46fe-afc9-fc454e8580e1').AndRaise(
 
383
                qe.QuantumClientException(status_code=404))
 
384
        sn = {
 
385
            "subnet": {
 
386
                "name": "name",
 
387
                "network_id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
 
388
                "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
 
389
                "allocation_pools": [
 
390
                    {"start": "10.0.3.20", "end": "10.0.3.150"}],
 
391
                "gateway_ip": "10.0.3.1",
 
392
                "ip_version": 4,
 
393
                "cidr": "10.0.3.0/24",
 
394
                "dns_nameservers": ["8.8.8.8"],
 
395
                "id": "91e47a57-7508-46fe-afc9-fc454e8580e1",
 
396
                "enable_dhcp": True,
 
397
            }
 
398
        }
 
399
        quantumclient.Client.show_subnet(
 
400
            '91e47a57-7508-46fe-afc9-fc454e8580e1').AndReturn(sn)
 
401
        quantumclient.Client.show_subnet(
 
402
            '91e47a57-7508-46fe-afc9-fc454e8580e1').AndReturn(sn)
 
403
        quantumclient.Client.show_subnet(
 
404
            '91e47a57-7508-46fe-afc9-fc454e8580e1').AndReturn(sn)
 
405
 
 
406
        quantumclient.Client.delete_subnet(
 
407
            '91e47a57-7508-46fe-afc9-fc454e8580e1'
 
408
        ).AndReturn(None)
 
409
 
 
410
        quantumclient.Client.show_subnet(
 
411
            '91e47a57-7508-46fe-afc9-fc454e8580e1'
 
412
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
413
 
 
414
        quantumclient.Client.delete_subnet(
 
415
            '91e47a57-7508-46fe-afc9-fc454e8580e1'
 
416
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
417
 
 
418
        self.m.ReplayAll()
 
419
        t = template_format.parse(quantum_template)
 
420
        stack = parse_stack(t)
 
421
        rsrc = self.create_subnet(t, stack, 'subnet')
 
422
 
 
423
        rsrc.validate()
 
424
 
 
425
        ref_id = rsrc.FnGetRefId()
 
426
        self.assertEqual('91e47a57-7508-46fe-afc9-fc454e8580e1', ref_id)
 
427
        self.assertEqual(None,
 
428
                         rsrc.FnGetAtt('network_id'))
 
429
        self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766',
 
430
                         rsrc.FnGetAtt('network_id'))
 
431
        self.assertEqual('8.8.8.8', rsrc.FnGetAtt('dns_nameservers')[0])
 
432
        self.assertEqual('91e47a57-7508-46fe-afc9-fc454e8580e1',
 
433
                         rsrc.FnGetAtt('id'))
 
434
 
 
435
        # assert the dependency (implicit or explicit) between the ports
 
436
        # and the subnet
 
437
        self.assertIn(stack['port'], stack.dependencies[stack['subnet']])
 
438
        self.assertIn(stack['port2'], stack.dependencies[stack['subnet']])
 
439
 
 
440
        self.assertRaises(resource.UpdateReplace,
 
441
                          rsrc.handle_update, {}, {}, {})
 
442
 
 
443
        self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None)
 
444
        rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
 
445
        self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None)
 
446
        self.m.VerifyAll()
 
447
 
 
448
    def test_subnet_disable_dhcp(self):
 
449
 
 
450
        quantumclient.Client.create_subnet({
 
451
            'subnet': {
 
452
                'name': utils.PhysName('test_stack', 'test_subnet'),
 
453
                'network_id': u'None',
 
454
                'dns_nameservers': [u'8.8.8.8'],
 
455
                'allocation_pools': [
 
456
                    {'start': u'10.0.3.20', 'end': u'10.0.3.150'}],
 
457
                'ip_version': 4,
 
458
                'enable_dhcp': False,
 
459
                'cidr': u'10.0.3.0/24'
 
460
            }
 
461
        }).AndReturn({
 
462
            "subnet": {
 
463
                "allocation_pools": [
 
464
                    {"start": "10.0.3.20", "end": "10.0.3.150"}],
 
465
                "cidr": "10.0.3.0/24",
 
466
                "dns_nameservers": ["8.8.8.8"],
 
467
                "enable_dhcp": False,
 
468
                "gateway_ip": "10.0.3.1",
 
469
                "id": "91e47a57-7508-46fe-afc9-fc454e8580e1",
 
470
                "ip_version": 4,
 
471
                "name": "name",
 
472
                "network_id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
 
473
                "tenant_id": "c1210485b2424d48804aad5d39c61b8f"
 
474
            }
 
475
        })
 
476
 
 
477
        quantumclient.Client.show_subnet(
 
478
            '91e47a57-7508-46fe-afc9-fc454e8580e1').AndReturn({
 
479
                "subnet": {
 
480
                    "name": "name",
 
481
                    "network_id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
 
482
                    "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
 
483
                    "allocation_pools": [
 
484
                        {"start": "10.0.3.20", "end": "10.0.3.150"}],
 
485
                    "gateway_ip": "10.0.3.1",
 
486
                    "ip_version": 4,
 
487
                    "cidr": "10.0.3.0/24",
 
488
                    "dns_nameservers": ["8.8.8.8"],
 
489
                    "id": "91e47a57-7508-46fe-afc9-fc454e8580e1",
 
490
                    "enable_dhcp": False,
 
491
                }
 
492
            })
 
493
 
 
494
        quantumclient.Client.delete_subnet(
 
495
            '91e47a57-7508-46fe-afc9-fc454e8580e1'
 
496
        ).AndReturn(None)
 
497
 
 
498
        quantumclient.Client.show_subnet(
 
499
            '91e47a57-7508-46fe-afc9-fc454e8580e1'
 
500
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
501
 
 
502
        self.m.ReplayAll()
 
503
        t = template_format.parse(quantum_template)
 
504
        t['Resources']['subnet']['Properties']['enable_dhcp'] = 'False'
 
505
        stack = parse_stack(t)
 
506
        rsrc = self.create_subnet(t, stack, 'subnet')
 
507
 
 
508
        rsrc.validate()
 
509
 
 
510
        ref_id = rsrc.FnGetRefId()
 
511
        self.assertEqual('91e47a57-7508-46fe-afc9-fc454e8580e1', ref_id)
 
512
        self.assertEqual(False, rsrc.FnGetAtt('enable_dhcp'))
 
513
        self.assertEqual(rsrc.delete(), None)
 
514
        self.m.VerifyAll()
 
515
 
 
516
 
 
517
@skipIf(quantumclient is None, 'quantumclient unavailable')
 
518
class QuantumRouterTest(HeatTestCase):
 
519
    def setUp(self):
 
520
        super(QuantumRouterTest, self).setUp()
 
521
        self.m.StubOutWithMock(quantumclient.Client, 'create_router')
 
522
        self.m.StubOutWithMock(quantumclient.Client, 'delete_router')
 
523
        self.m.StubOutWithMock(quantumclient.Client, 'show_router')
 
524
        self.m.StubOutWithMock(quantumclient.Client, 'add_interface_router')
 
525
        self.m.StubOutWithMock(quantumclient.Client, 'remove_interface_router')
 
526
        self.m.StubOutWithMock(quantumclient.Client, 'add_gateway_router')
 
527
        self.m.StubOutWithMock(quantumclient.Client, 'remove_gateway_router')
 
528
        setup_dummy_db()
 
529
 
 
530
    def create_router(self, t, stack, resource_name):
 
531
        rsrc = router.Router('router', t['Resources'][resource_name], stack)
 
532
        scheduler.TaskRunner(rsrc.create)()
 
533
        self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
 
534
        return rsrc
 
535
 
 
536
    def create_router_interface(self, t, stack, resource_name, properties={}):
 
537
        t['Resources'][resource_name]['Properties'] = properties
 
538
        rsrc = router.RouterInterface(
 
539
            'router_interface',
 
540
            t['Resources'][resource_name],
 
541
            stack)
 
542
        scheduler.TaskRunner(rsrc.create)()
 
543
        self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
 
544
        return rsrc
 
545
 
 
546
    def create_gateway_router(self, t, stack, resource_name, properties={}):
 
547
        t['Resources'][resource_name]['Properties'] = properties
 
548
        rsrc = router.RouterGateway(
 
549
            'gateway',
 
550
            t['Resources'][resource_name],
 
551
            stack)
 
552
        scheduler.TaskRunner(rsrc.create)()
 
553
        self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
 
554
        return rsrc
 
555
 
 
556
    def test_router(self):
 
557
        quantumclient.Client.create_router({
 
558
            'router': {
 
559
                'name': utils.PhysName('test_stack', 'router'),
 
560
                'admin_state_up': True,
 
561
            }
 
562
        }).AndReturn({
 
563
            "router": {
 
564
                "status": "BUILD",
 
565
                "external_gateway_info": None,
 
566
                "name": utils.PhysName('test_stack', 'router'),
 
567
                "admin_state_up": True,
 
568
                "tenant_id": "3e21026f2dc94372b105808c0e721661",
 
569
                "id": "3e46229d-8fce-4733-819a-b5fe630550f8"
 
570
            }
 
571
        })
 
572
        quantumclient.Client.show_router(
 
573
            '3e46229d-8fce-4733-819a-b5fe630550f8').AndReturn({
 
574
                "router": {
 
575
                    "status": "BUILD",
 
576
                    "external_gateway_info": None,
 
577
                    "name": utils.PhysName('test_stack', 'router'),
 
578
                    "admin_state_up": True,
 
579
                    "tenant_id": "3e21026f2dc94372b105808c0e721661",
 
580
                    "routes": [],
 
581
                    "id": "3e46229d-8fce-4733-819a-b5fe630550f8"
 
582
                }
 
583
            })
 
584
        quantumclient.Client.show_router(
 
585
            '3e46229d-8fce-4733-819a-b5fe630550f8').AndReturn({
 
586
                "router": {
 
587
                    "status": "ACTIVE",
 
588
                    "external_gateway_info": None,
 
589
                    "name": utils.PhysName('test_stack', 'router'),
 
590
                    "admin_state_up": True,
 
591
                    "tenant_id": "3e21026f2dc94372b105808c0e721661",
 
592
                    "routes": [],
 
593
                    "id": "3e46229d-8fce-4733-819a-b5fe630550f8"
 
594
                }
 
595
            })
 
596
 
 
597
        quantumclient.Client.show_router(
 
598
            '3e46229d-8fce-4733-819a-b5fe630550f8').AndRaise(
 
599
                qe.QuantumClientException(status_code=404))
 
600
        quantumclient.Client.show_router(
 
601
            '3e46229d-8fce-4733-819a-b5fe630550f8').AndReturn({
 
602
                "router": {
 
603
                    "status": "ACTIVE",
 
604
                    "external_gateway_info": None,
 
605
                    "name": utils.PhysName('test_stack', 'router'),
 
606
                    "admin_state_up": True,
 
607
                    "tenant_id": "3e21026f2dc94372b105808c0e721661",
 
608
                    "routes": [],
 
609
                    "id": "3e46229d-8fce-4733-819a-b5fe630550f8"
 
610
                }
 
611
            })
 
612
        quantumclient.Client.show_router(
 
613
            '3e46229d-8fce-4733-819a-b5fe630550f8').AndReturn({
 
614
                "router": {
 
615
                    "status": "ACTIVE",
 
616
                    "external_gateway_info": None,
 
617
                    "name": utils.PhysName('test_stack', 'router'),
 
618
                    "admin_state_up": True,
 
619
                    "tenant_id": "3e21026f2dc94372b105808c0e721661",
 
620
                    "routes": [],
 
621
                    "id": "3e46229d-8fce-4733-819a-b5fe630550f8"
 
622
                }
 
623
            })
 
624
 
 
625
        quantumclient.Client.delete_router(
 
626
            '3e46229d-8fce-4733-819a-b5fe630550f8'
 
627
        ).AndReturn(None)
 
628
 
 
629
        quantumclient.Client.show_router(
 
630
            '3e46229d-8fce-4733-819a-b5fe630550f8'
 
631
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
632
 
 
633
        quantumclient.Client.delete_router(
 
634
            '3e46229d-8fce-4733-819a-b5fe630550f8'
 
635
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
636
 
 
637
        self.m.ReplayAll()
 
638
        t = template_format.parse(quantum_template)
 
639
        stack = parse_stack(t)
 
640
        rsrc = self.create_router(t, stack, 'router')
 
641
 
 
642
        rsrc.validate()
 
643
 
 
644
        ref_id = rsrc.FnGetRefId()
 
645
        self.assertEqual('3e46229d-8fce-4733-819a-b5fe630550f8', ref_id)
 
646
        self.assertEqual(None,
 
647
                         rsrc.FnGetAtt('tenant_id'))
 
648
        self.assertEqual('3e21026f2dc94372b105808c0e721661',
 
649
                         rsrc.FnGetAtt('tenant_id'))
 
650
        self.assertEqual('3e46229d-8fce-4733-819a-b5fe630550f8',
 
651
                         rsrc.FnGetAtt('id'))
 
652
 
 
653
        self.assertRaises(resource.UpdateReplace,
 
654
                          rsrc.handle_update, {}, {}, {})
 
655
 
 
656
        self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None)
 
657
        rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
 
658
        self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None)
 
659
        self.m.VerifyAll()
 
660
 
 
661
    def test_router_interface(self):
 
662
        quantumclient.Client.add_interface_router(
 
663
            '3e46229d-8fce-4733-819a-b5fe630550f8',
 
664
            {'subnet_id': '91e47a57-7508-46fe-afc9-fc454e8580e1'}
 
665
        ).AndReturn(None)
 
666
        quantumclient.Client.remove_interface_router(
 
667
            '3e46229d-8fce-4733-819a-b5fe630550f8',
 
668
            {'subnet_id': '91e47a57-7508-46fe-afc9-fc454e8580e1'}
 
669
        ).AndReturn(None)
 
670
        quantumclient.Client.remove_interface_router(
 
671
            '3e46229d-8fce-4733-819a-b5fe630550f8',
 
672
            {'subnet_id': '91e47a57-7508-46fe-afc9-fc454e8580e1'}
 
673
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
674
        self.m.ReplayAll()
 
675
        t = template_format.parse(quantum_template)
 
676
        stack = parse_stack(t)
 
677
 
 
678
        rsrc = self.create_router_interface(
 
679
            t, stack, 'router_interface', properties={
 
680
                'router_id': '3e46229d-8fce-4733-819a-b5fe630550f8',
 
681
                'subnet_id': '91e47a57-7508-46fe-afc9-fc454e8580e1'
 
682
            })
 
683
 
 
684
        self.assertEqual(rsrc.delete(), None)
 
685
        rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
 
686
        self.assertEqual(rsrc.delete(), None)
 
687
        self.m.VerifyAll()
 
688
 
 
689
    def test_gateway_router(self):
 
690
        quantumclient.Client.add_gateway_router(
 
691
            '3e46229d-8fce-4733-819a-b5fe630550f8',
 
692
            {'network_id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'}
 
693
        ).AndReturn(None)
 
694
        quantumclient.Client.remove_gateway_router(
 
695
            '3e46229d-8fce-4733-819a-b5fe630550f8'
 
696
        ).AndReturn(None)
 
697
        quantumclient.Client.remove_gateway_router(
 
698
            '3e46229d-8fce-4733-819a-b5fe630550f8'
 
699
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
700
        self.m.ReplayAll()
 
701
        t = template_format.parse(quantum_template)
 
702
        stack = parse_stack(t)
 
703
 
 
704
        rsrc = self.create_gateway_router(
 
705
            t, stack, 'gateway', properties={
 
706
                'router_id': '3e46229d-8fce-4733-819a-b5fe630550f8',
 
707
                'network_id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
708
            })
 
709
 
 
710
        self.assertEqual(rsrc.delete(), None)
 
711
        rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
 
712
        self.assertEqual(rsrc.delete(), None)
 
713
        self.m.VerifyAll()
 
714
 
 
715
 
 
716
@skipIf(quantumclient is None, 'quantumclient unavailable')
 
717
class QuantumFloatingIPTest(HeatTestCase):
 
718
    @skipIf(net.clients.quantumclient is None, "Missing Quantum Client")
 
719
    def setUp(self):
 
720
        super(QuantumFloatingIPTest, self).setUp()
 
721
        self.m.StubOutWithMock(quantumclient.Client, 'create_floatingip')
 
722
        self.m.StubOutWithMock(quantumclient.Client, 'delete_floatingip')
 
723
        self.m.StubOutWithMock(quantumclient.Client, 'show_floatingip')
 
724
        self.m.StubOutWithMock(quantumclient.Client, 'update_floatingip')
 
725
        self.m.StubOutWithMock(quantumclient.Client, 'create_port')
 
726
        self.m.StubOutWithMock(quantumclient.Client, 'delete_port')
 
727
        self.m.StubOutWithMock(quantumclient.Client, 'show_port')
 
728
        setup_dummy_db()
 
729
 
 
730
    def test_floating_ip(self):
 
731
 
 
732
        quantumclient.Client.create_floatingip({
 
733
            'floatingip': {'floating_network_id': u'abcd1234'}
 
734
        }).AndReturn({'floatingip': {
 
735
            "status": "ACTIVE",
 
736
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
737
        }})
 
738
 
 
739
        quantumclient.Client.show_floatingip(
 
740
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
741
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
742
        quantumclient.Client.show_floatingip(
 
743
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
744
        ).MultipleTimes().AndReturn({'floatingip': {
 
745
            "status": "ACTIVE",
 
746
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
747
        }})
 
748
 
 
749
        quantumclient.Client.delete_floatingip(
 
750
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndReturn(None)
 
751
        quantumclient.Client.delete_floatingip(
 
752
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndRaise(
 
753
                qe.QuantumClientException(status_code=404))
 
754
        self.m.ReplayAll()
 
755
 
 
756
        t = template_format.parse(quantum_floating_template)
 
757
        stack = parse_stack(t)
 
758
 
 
759
        # assert the implicit dependency between the floating_ip
 
760
        # and the gateway
 
761
        deps = stack.dependencies[stack['gateway']]
 
762
        self.assertIn(stack['floating_ip'], deps)
 
763
 
 
764
        fip = stack['floating_ip']
 
765
        scheduler.TaskRunner(fip.create)()
 
766
        self.assertEqual((fip.CREATE, fip.COMPLETE), fip.state)
 
767
        fip.validate()
 
768
 
 
769
        fip_id = fip.FnGetRefId()
 
770
        self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', fip_id)
 
771
 
 
772
        self.assertEqual(None, fip.FnGetAtt('status'))
 
773
        self.assertEqual('ACTIVE', fip.FnGetAtt('status'))
 
774
        try:
 
775
            fip.FnGetAtt('Foo')
 
776
            raise Exception('Expected InvalidTemplateAttribute')
 
777
        except exception.InvalidTemplateAttribute:
 
778
            pass
 
779
 
 
780
        self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766',
 
781
                         fip.FnGetAtt('id'))
 
782
        self.assertRaises(resource.UpdateReplace,
 
783
                          fip.handle_update, {}, {}, {})
 
784
        self.assertEqual(fip.delete(), None)
 
785
        fip.state_set(fip.CREATE, fip.COMPLETE, 'to delete again')
 
786
        self.assertEqual(fip.delete(), None)
 
787
 
 
788
        self.m.VerifyAll()
 
789
 
 
790
    def test_port(self):
 
791
 
 
792
        quantumclient.Client.create_port({'port': {
 
793
            'network_id': u'xyz1234',
 
794
            'fixed_ips': [
 
795
                {'subnet_id': u'12.12.12.0', 'ip_address': u'10.0.0.10'}
 
796
            ],
 
797
            'name': utils.PhysName('test_stack', 'port_floating'),
 
798
            'admin_state_up': True}}
 
799
        ).AndReturn({'port': {
 
800
            "status": "BUILD",
 
801
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
802
        }})
 
803
        quantumclient.Client.show_port(
 
804
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
805
        ).AndReturn({'port': {
 
806
            "status": "BUILD",
 
807
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
808
        }})
 
809
        quantumclient.Client.show_port(
 
810
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
811
        ).AndReturn({'port': {
 
812
            "status": "ACTIVE",
 
813
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
814
        }})
 
815
        quantumclient.Client.show_port(
 
816
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
817
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
818
        quantumclient.Client.show_port(
 
819
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
820
        ).MultipleTimes().AndReturn({'port': {
 
821
            "status": "ACTIVE",
 
822
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
823
        }})
 
824
 
 
825
        self.m.ReplayAll()
 
826
 
 
827
        t = template_format.parse(quantum_floating_template)
 
828
        stack = parse_stack(t)
 
829
 
 
830
        p = stack['port_floating']
 
831
        scheduler.TaskRunner(p.create)()
 
832
        self.assertEqual((p.CREATE, p.COMPLETE), p.state)
 
833
        p.validate()
 
834
 
 
835
        port_id = p.FnGetRefId()
 
836
        self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', port_id)
 
837
 
 
838
        self.assertEqual(None, p.FnGetAtt('status'))
 
839
        self.assertEqual('ACTIVE', p.FnGetAtt('status'))
 
840
        try:
 
841
            p.FnGetAtt('Foo')
 
842
            raise Exception('Expected InvalidTemplateAttribute')
 
843
        except exception.InvalidTemplateAttribute:
 
844
            pass
 
845
 
 
846
        self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766',
 
847
                         p.FnGetAtt('id'))
 
848
 
 
849
        self.assertRaises(resource.UpdateReplace,
 
850
                          p.handle_update, {}, {}, {})
 
851
 
 
852
        self.m.VerifyAll()
 
853
 
 
854
    def test_floatip_port(self):
 
855
 
 
856
        quantumclient.Client.create_floatingip({
 
857
            'floatingip': {'floating_network_id': u'abcd1234'}
 
858
        }).AndReturn({'floatingip': {
 
859
            "status": "ACTIVE",
 
860
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
861
        }})
 
862
 
 
863
        quantumclient.Client.create_port({'port': {
 
864
            'network_id': u'xyz1234',
 
865
            'fixed_ips': [
 
866
                {'subnet_id': u'12.12.12.0', 'ip_address': u'10.0.0.10'}
 
867
            ],
 
868
            'name': utils.PhysName('test_stack', 'port_floating'),
 
869
            'admin_state_up': True}}
 
870
        ).AndReturn({'port': {
 
871
            "status": "BUILD",
 
872
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
873
        }})
 
874
        quantumclient.Client.show_port(
 
875
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
876
        ).AndReturn({'port': {
 
877
            "status": "ACTIVE",
 
878
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
879
        }})
 
880
        quantumclient.Client.update_floatingip(
 
881
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
 
882
            {
 
883
                'floatingip': {
 
884
                    'port_id': u'fc68ea2c-b60b-4b4f-bd82-94ec81110766'}}
 
885
        ).AndReturn({'floatingip': {
 
886
            "status": "ACTIVE",
 
887
            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
 
888
        }})
 
889
 
 
890
        quantumclient.Client.update_floatingip(
 
891
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
 
892
            {'floatingip': {
 
893
                'port_id': None
 
894
            }}).AndReturn(None)
 
895
 
 
896
        quantumclient.Client.delete_port(
 
897
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
898
        ).AndReturn(None)
 
899
 
 
900
        quantumclient.Client.show_port(
 
901
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
902
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
903
 
 
904
        quantumclient.Client.delete_floatingip(
 
905
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
906
        ).AndReturn(None)
 
907
 
 
908
        quantumclient.Client.update_floatingip(
 
909
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
 
910
            {'floatingip': {
 
911
                'port_id': None
 
912
            }}).AndRaise(qe.QuantumClientException(status_code=404))
 
913
 
 
914
        quantumclient.Client.delete_port(
 
915
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
916
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
917
 
 
918
        quantumclient.Client.delete_floatingip(
 
919
            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
 
920
        ).AndRaise(qe.QuantumClientException(status_code=404))
 
921
 
 
922
        self.m.ReplayAll()
 
923
 
 
924
        t = template_format.parse(quantum_floating_template)
 
925
        stack = parse_stack(t)
 
926
 
 
927
        fip = stack['floating_ip']
 
928
        scheduler.TaskRunner(fip.create)()
 
929
        self.assertEqual((fip.CREATE, fip.COMPLETE), fip.state)
 
930
 
 
931
        p = stack['port_floating']
 
932
        scheduler.TaskRunner(p.create)()
 
933
        self.assertEqual((p.CREATE, p.COMPLETE), p.state)
 
934
 
 
935
        fipa = stack['floating_ip_assoc']
 
936
        scheduler.TaskRunner(fipa.create)()
 
937
        self.assertEqual((fipa.CREATE, fipa.COMPLETE), fipa.state)
 
938
 
 
939
        fipa.validate()
 
940
 
 
941
        fipa_id = fipa.FnGetRefId()
 
942
        fip_id = fip.FnGetRefId()
 
943
        port_id = p.FnGetRefId()
 
944
        self.assertEqual('%s:%s' % (fip_id, port_id), fipa_id)
 
945
        self.assertRaises(resource.UpdateReplace,
 
946
                          fipa.handle_update, {}, {}, {})
 
947
 
 
948
        self.assertEqual(fipa.delete(), None)
 
949
        self.assertEqual(scheduler.TaskRunner(p.delete)(), None)
 
950
        self.assertEqual(fip.delete(), None)
 
951
 
 
952
        fipa.state_set(fipa.CREATE, fipa.COMPLETE, 'to delete again')
 
953
        fip.state_set(fip.CREATE, fip.COMPLETE, 'to delete again')
 
954
        p.state_set(p.CREATE, p.COMPLETE, 'to delete again')
 
955
 
 
956
        self.assertEqual(fipa.delete(), None)
 
957
        self.assertEqual(scheduler.TaskRunner(p.delete)(), None)
 
958
        self.assertEqual(fip.delete(), None)
 
959
 
 
960
        self.m.VerifyAll()