Adding tests for IPv6.
[snaps.git] / snaps / openstack / tests / create_stack_tests.py
1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 #                    and others.  All rights reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 import os
16 import time
17
18 import pkg_resources
19 from heatclient.exc import HTTPBadRequest
20 from snaps import file_utils
21 from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings
22 from snaps.openstack.create_image import OpenStackImage, ImageSettings
23
24 try:
25     from urllib.request import URLError
26 except ImportError:
27     from urllib2 import URLError
28
29 import logging
30 import unittest
31 import uuid
32
33 from snaps.openstack import create_stack
34 from snaps.openstack.create_stack import (
35     StackSettings, StackSettingsError, StackCreationError, StackError)
36 from snaps.openstack.tests import openstack_tests, create_instance_tests
37 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
38 from snaps.openstack.utils import heat_utils, neutron_utils, nova_utils
39
40 __author__ = 'spisarski'
41
42 logger = logging.getLogger('create_stack_tests')
43
44
45 class StackSettingsUnitTests(unittest.TestCase):
46     """
47     Tests the construction of the StackSettings class
48     """
49
50     def test_no_params(self):
51         with self.assertRaises(StackSettingsError):
52             StackSettings()
53
54     def test_empty_config(self):
55         with self.assertRaises(StackSettingsError):
56             StackSettings(**dict())
57
58     def test_name_only(self):
59         with self.assertRaises(StackSettingsError):
60             StackSettings(name='foo')
61
62     def test_config_with_name_only(self):
63         with self.assertRaises(StackSettingsError):
64             StackSettings(**{'name': 'foo'})
65
66     def test_config_minimum_template(self):
67         settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
68         self.assertEqual('stack', settings.name)
69         self.assertEqual('foo', settings.template)
70         self.assertIsNone(settings.template_path)
71         self.assertIsNone(settings.env_values)
72         self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
73                          settings.stack_create_timeout)
74
75     def test_config_minimum_template_path(self):
76         settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
77         self.assertEqual('stack', settings.name)
78         self.assertIsNone(settings.template)
79         self.assertEqual('foo', settings.template_path)
80         self.assertIsNone(settings.env_values)
81         self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
82                          settings.stack_create_timeout)
83
84     def test_minimum_template(self):
85         settings = StackSettings(name='stack', template='foo')
86         self.assertEqual('stack', settings.name)
87         self.assertEqual('foo', settings.template)
88         self.assertIsNone(settings.template_path)
89         self.assertIsNone(settings.env_values)
90         self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
91                          settings.stack_create_timeout)
92
93     def test_minimum_template_path(self):
94         settings = StackSettings(name='stack', template_path='foo')
95         self.assertEqual('stack', settings.name)
96         self.assertEqual('foo', settings.template_path)
97         self.assertIsNone(settings.template)
98         self.assertIsNone(settings.env_values)
99         self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
100                          settings.stack_create_timeout)
101
102     def test_all(self):
103         env_values = {'foo': 'bar'}
104         settings = StackSettings(name='stack', template='bar',
105                                  template_path='foo', env_values=env_values,
106                                  stack_create_timeout=999)
107         self.assertEqual('stack', settings.name)
108         self.assertEqual('bar', settings.template)
109         self.assertEqual('foo', settings.template_path)
110         self.assertEqual(env_values, settings.env_values)
111         self.assertEqual(999, settings.stack_create_timeout)
112
113     def test_config_all(self):
114         env_values = {'foo': 'bar'}
115         settings = StackSettings(
116             **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
117                'env_values': env_values, 'stack_create_timeout': 999})
118         self.assertEqual('stack', settings.name)
119         self.assertEqual('bar', settings.template)
120         self.assertEqual('foo', settings.template_path)
121         self.assertEqual(env_values, settings.env_values)
122         self.assertEqual(999, settings.stack_create_timeout)
123
124
125 class CreateStackSuccessTests(OSIntegrationTestCase):
126     """
127     Tests for the OpenStackHeatStack class defined in create_stack.py
128     """
129
130     def setUp(self):
131
132         super(self.__class__, self).__start__()
133
134         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
135
136         self.heat_creds = self.admin_os_creds
137         self.heat_creds.project_name = self.admin_os_creds.project_name
138
139         self.heat_cli = heat_utils.heat_client(self.heat_creds)
140         self.stack_creator = None
141
142         self.image_creator = OpenStackImage(
143             self.heat_creds, openstack_tests.cirros_image_settings(
144                 name=self.guid + '-image',
145                 image_metadata=self.image_metadata))
146         self.image_creator.create()
147
148         # Create Flavor
149         self.flavor_creator = OpenStackFlavor(
150             self.admin_os_creds,
151             FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10,
152                            vcpus=1))
153         self.flavor_creator.create()
154
155         self.network_name = self.guid + '-net'
156         self.subnet_name = self.guid + '-subnet'
157         self.vm_inst_name = self.guid + '-inst'
158
159         self.env_values = {
160             'image_name': self.image_creator.image_settings.name,
161             'flavor_name': self.flavor_creator.flavor_settings.name,
162             'net_name': self.network_name,
163             'subnet_name': self.subnet_name,
164             'inst_name': self.vm_inst_name}
165
166         self.heat_tmplt_path = pkg_resources.resource_filename(
167             'snaps.openstack.tests.heat', 'test_heat_template.yaml')
168
169     def tearDown(self):
170         """
171         Cleans the stack and downloaded stack file
172         """
173         if self.stack_creator:
174             try:
175                 self.stack_creator.clean()
176             except:
177                 pass
178
179         if self.image_creator:
180             try:
181                 self.image_creator.clean()
182             except:
183                 pass
184
185         if self.flavor_creator:
186             try:
187                 self.flavor_creator.clean()
188             except:
189                 pass
190
191         super(self.__class__, self).__clean__()
192
193     def test_create_stack_template_file(self):
194         """
195         Tests the creation of an OpenStack stack from Heat template file.
196         """
197         # Create Stack
198         # Set the default stack settings, then set any custom parameters sent
199         # from the app
200         stack_settings = StackSettings(
201             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
202             template_path=self.heat_tmplt_path,
203             env_values=self.env_values)
204         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
205                                                              stack_settings)
206         created_stack = self.stack_creator.create()
207         self.assertIsNotNone(created_stack)
208
209         retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
210                                                      created_stack.id)
211         self.assertIsNotNone(retrieved_stack)
212         self.assertEqual(created_stack.name, retrieved_stack.name)
213         self.assertEqual(created_stack.id, retrieved_stack.id)
214         self.assertEqual(0, len(self.stack_creator.get_outputs()))
215
216     def test_create_stack_short_timeout(self):
217         """
218         Tests the creation of an OpenStack stack from Heat template file.
219         """
220         # Create Stack
221         # Set the default stack settings, then set any custom parameters sent
222         # from the app
223         stack_settings = StackSettings(
224             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
225             template_path=self.heat_tmplt_path,
226             env_values=self.env_values, stack_create_timeout=0)
227
228         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
229                                                              stack_settings)
230         with self.assertRaises(StackCreationError):
231             self.stack_creator.create()
232
233     def test_create_stack_template_dict(self):
234         """
235         Tests the creation of an OpenStack stack from a heat dict() object.
236         """
237         # Create Stack
238         # Set the default stack settings, then set any custom parameters sent
239         # from the app
240         template_dict = heat_utils.parse_heat_template_str(
241             file_utils.read_file(self.heat_tmplt_path))
242         stack_settings = StackSettings(
243             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
244             template=template_dict,
245             env_values=self.env_values)
246         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
247                                                              stack_settings)
248         created_stack = self.stack_creator.create()
249         self.assertIsNotNone(created_stack)
250
251         retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
252                                                      created_stack.id)
253         self.assertIsNotNone(retrieved_stack)
254         self.assertEqual(created_stack.name, retrieved_stack.name)
255         self.assertEqual(created_stack.id, retrieved_stack.id)
256         self.assertEqual(0, len(self.stack_creator.get_outputs()))
257
258     def test_create_delete_stack(self):
259         """
260         Tests the creation then deletion of an OpenStack stack to ensure
261         clean() does not raise an Exception.
262         """
263         # Create Stack
264         template_dict = heat_utils.parse_heat_template_str(
265             file_utils.read_file(self.heat_tmplt_path))
266         stack_settings = StackSettings(
267             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
268             template=template_dict,
269             env_values=self.env_values)
270         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
271                                                              stack_settings)
272         created_stack = self.stack_creator.create()
273         self.assertIsNotNone(created_stack)
274
275         retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
276                                                      created_stack.id)
277         self.assertIsNotNone(retrieved_stack)
278         self.assertEqual(created_stack.name, retrieved_stack.name)
279         self.assertEqual(created_stack.id, retrieved_stack.id)
280         self.assertEqual(0, len(self.stack_creator.get_outputs()))
281         self.assertEqual(create_stack.STATUS_CREATE_COMPLETE,
282                          self.stack_creator.get_status())
283
284         # Delete Stack manually
285         heat_utils.delete_stack(self.heat_cli, created_stack)
286
287         end_time = time.time() + 90
288         deleted = False
289         while time.time() < end_time:
290             status = heat_utils.get_stack_status(self.heat_cli,
291                                                  retrieved_stack.id)
292             if status == create_stack.STATUS_DELETE_COMPLETE:
293                 deleted = True
294                 break
295
296         self.assertTrue(deleted)
297
298         # Must not throw an exception when attempting to cleanup non-existent
299         # stack
300         self.stack_creator.clean()
301         self.assertIsNone(self.stack_creator.get_stack())
302
303     def test_create_same_stack(self):
304         """
305         Tests the creation of an OpenStack stack when the stack already exists.
306         """
307         # Create Stack
308         template_dict = heat_utils.parse_heat_template_str(
309             file_utils.read_file(self.heat_tmplt_path))
310         stack_settings = StackSettings(
311             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
312             template=template_dict,
313             env_values=self.env_values)
314         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
315                                                              stack_settings)
316         created_stack1 = self.stack_creator.create()
317
318         retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
319                                                      created_stack1.id)
320         self.assertIsNotNone(retrieved_stack)
321         self.assertEqual(created_stack1.name, retrieved_stack.name)
322         self.assertEqual(created_stack1.id, retrieved_stack.id)
323         self.assertEqual(0, len(self.stack_creator.get_outputs()))
324
325         # Should be retrieving the instance data
326         stack_creator2 = create_stack.OpenStackHeatStack(self.heat_creds,
327                                                          stack_settings)
328         stack2 = stack_creator2.create()
329         self.assertEqual(created_stack1.id, stack2.id)
330
331     def test_retrieve_network_creators(self):
332         """
333         Tests the creation of an OpenStack stack from Heat template file and
334         the retrieval of the network creator.
335         """
336         stack_settings = StackSettings(
337             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
338             template_path=self.heat_tmplt_path,
339             env_values=self.env_values)
340         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
341                                                              stack_settings)
342         created_stack = self.stack_creator.create()
343         self.assertIsNotNone(created_stack)
344
345         net_creators = self.stack_creator.get_network_creators()
346         self.assertIsNotNone(net_creators)
347         self.assertEqual(1, len(net_creators))
348         self.assertEqual(self.network_name, net_creators[0].get_network().name)
349
350         neutron = neutron_utils.neutron_client(self.os_creds)
351         net_by_name = neutron_utils.get_network(
352             neutron, network_name=net_creators[0].get_network().name)
353         self.assertEqual(net_creators[0].get_network(), net_by_name)
354         self.assertIsNotNone(neutron_utils.get_network_by_id(
355             neutron, net_creators[0].get_network().id))
356
357         self.assertEqual(1, len(net_creators[0].get_network().subnets))
358         subnet = net_creators[0].get_network().subnets[0]
359         subnet_by_name = neutron_utils.get_subnet(
360             neutron, subnet_name=subnet.name)
361         self.assertEqual(subnet, subnet_by_name)
362
363         subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
364         self.assertIsNotNone(subnet_by_id)
365         self.assertEqual(subnet_by_name, subnet_by_id)
366
367     def test_retrieve_vm_inst_creators(self):
368         """
369         Tests the creation of an OpenStack stack from Heat template file and
370         the retrieval of the network creator.
371         """
372         stack_settings = StackSettings(
373             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
374             template_path=self.heat_tmplt_path,
375             env_values=self.env_values)
376         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
377                                                              stack_settings)
378         created_stack = self.stack_creator.create()
379         self.assertIsNotNone(created_stack)
380
381         vm_inst_creators = self.stack_creator.get_vm_inst_creators()
382         self.assertIsNotNone(vm_inst_creators)
383         self.assertEqual(1, len(vm_inst_creators))
384         self.assertEqual(self.vm_inst_name,
385                          vm_inst_creators[0].get_vm_inst().name)
386
387         nova = nova_utils.nova_client(self.admin_os_creds)
388         vm_inst_by_name = nova_utils.get_server(
389             nova, server_name=vm_inst_creators[0].get_vm_inst().name)
390         self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
391         self.assertIsNotNone(nova_utils.get_server_object_by_id(
392             nova, vm_inst_creators[0].get_vm_inst().id))
393
394
395 class CreateStackFloatingIpTests(OSIntegrationTestCase):
396     """
397     Tests to ensure that floating IPs can be accessed via an
398     OpenStackVmInstance object obtained from the OpenStackHeatStack instance
399     """
400
401     def setUp(self):
402
403         super(self.__class__, self).__start__()
404
405         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
406
407         self.heat_creds = self.admin_os_creds
408         self.heat_creds.project_name = self.admin_os_creds.project_name
409
410         self.heat_cli = heat_utils.heat_client(self.heat_creds)
411         self.stack_creator = None
412
413         self.image_creator = OpenStackImage(
414             self.heat_creds, openstack_tests.cirros_image_settings(
415                 name=self.guid + '-image',
416                 image_metadata=self.image_metadata))
417         self.image_creator.create()
418
419         self.network_name = self.guid + '-net'
420         self.subnet_name = self.guid + '-subnet'
421         self.flavor1_name = self.guid + '-flavor1'
422         self.flavor2_name = self.guid + '-flavor2'
423         self.sec_grp_name = self.guid + '-sec_grp'
424         self.vm_inst1_name = self.guid + '-inst1'
425         self.vm_inst2_name = self.guid + '-inst2'
426         self.keypair_name = self.guid + '-kp'
427
428         self.env_values = {
429             'image1_name': self.image_creator.image_settings.name,
430             'image2_name': self.image_creator.image_settings.name,
431             'flavor1_name': self.flavor1_name,
432             'flavor2_name': self.flavor2_name,
433             'net_name': self.network_name,
434             'subnet_name': self.subnet_name,
435             'inst1_name': self.vm_inst1_name,
436             'inst2_name': self.vm_inst2_name,
437             'keypair_name': self.keypair_name,
438             'external_net_name': self.ext_net_name,
439             'security_group_name': self.sec_grp_name}
440
441         self.heat_tmplt_path = pkg_resources.resource_filename(
442             'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
443
444     def tearDown(self):
445         """
446         Cleans the stack and downloaded stack file
447         """
448         if self.stack_creator:
449             try:
450                 self.stack_creator.clean()
451             except:
452                 pass
453
454         if self.image_creator:
455             try:
456                 self.image_creator.clean()
457             except:
458                 pass
459
460         super(self.__class__, self).__clean__()
461
462     def test_connect_via_ssh_heat_vm(self):
463         """
464         Tests the creation of an OpenStack stack from Heat template file and
465         the retrieval of two VM instance creators and attempt to connect via
466         SSH to the first one with a floating IP.
467         """
468         stack_settings = StackSettings(
469             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
470             template_path=self.heat_tmplt_path,
471             env_values=self.env_values)
472         self.stack_creator = create_stack.OpenStackHeatStack(
473             self.heat_creds, stack_settings,
474             [self.image_creator.image_settings])
475         created_stack = self.stack_creator.create()
476         self.assertIsNotNone(created_stack)
477
478         vm_inst_creators = self.stack_creator.get_vm_inst_creators(
479             heat_keypair_option='private_key')
480         self.assertIsNotNone(vm_inst_creators)
481         self.assertEqual(2, len(vm_inst_creators))
482
483         for vm_inst_creator in vm_inst_creators:
484             if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
485                 self.assertTrue(
486                     create_instance_tests.validate_ssh_client(vm_inst_creator))
487             else:
488                 vm_settings = vm_inst_creator.instance_settings
489                 self.assertEqual(0, len(vm_settings.floating_ip_settings))
490
491
492 class CreateStackRouterTests(OSIntegrationTestCase):
493     """
494     Tests for the CreateStack class defined in create_stack.py where the
495     target is a Network, Subnet, and Router
496     """
497
498     def setUp(self):
499         """
500         Instantiates the CreateStack object that is responsible for downloading
501         and creating an OS stack file within OpenStack
502         """
503         super(self.__class__, self).__start__()
504
505         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
506
507         self.heat_creds = self.admin_os_creds
508         self.heat_creds.project_name = self.admin_os_creds.project_name
509
510         self.heat_cli = heat_utils.heat_client(self.heat_creds)
511         self.neutron = neutron_utils.neutron_client(self.os_creds)
512         self.stack_creator = None
513
514         self.net_name = self.guid + '-net'
515         self.subnet_name = self.guid + '-subnet'
516         self.router_name = self.guid + '-router'
517
518         self.env_values = {
519             'net_name': self.net_name,
520             'subnet_name': self.subnet_name,
521             'router_name': self.router_name,
522             'external_net_name': self.ext_net_name}
523
524         self.heat_tmplt_path = pkg_resources.resource_filename(
525             'snaps.openstack.tests.heat', 'router_heat_template.yaml')
526
527         stack_settings = StackSettings(
528             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
529             template_path=self.heat_tmplt_path,
530             env_values=self.env_values)
531         self.stack_creator = create_stack.OpenStackHeatStack(
532             self.heat_creds, stack_settings)
533         self.created_stack = self.stack_creator.create()
534         self.assertIsNotNone(self.created_stack)
535
536     def tearDown(self):
537         """
538         Cleans the stack and downloaded stack file
539         """
540         if self.stack_creator:
541             try:
542                 self.stack_creator.clean()
543             except:
544                 pass
545
546         super(self.__class__, self).__clean__()
547
548     def test_retrieve_router_creator(self):
549         """
550         Tests the creation of an OpenStack stack from Heat template file and
551         the retrieval of an OpenStackRouter creator/state machine instance
552         """
553         router_creators = self.stack_creator.get_router_creators()
554         self.assertEqual(1, len(router_creators))
555
556         creator = router_creators[0]
557         self.assertEqual(self.router_name, creator.router_settings.name)
558
559         router = creator.get_router()
560
561         ext_net = neutron_utils.get_network(
562             self.neutron, network_name=self.ext_net_name)
563         self.assertEqual(ext_net.id, router.external_network_id)
564
565
566 class CreateStackVolumeTests(OSIntegrationTestCase):
567     """
568     Tests to ensure that floating IPs can be accessed via an
569     OpenStackVolume object obtained from the OpenStackHeatStack instance
570     """
571
572     def setUp(self):
573
574         super(self.__class__, self).__start__()
575
576         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
577
578         self.heat_creds = self.admin_os_creds
579         self.heat_creds.project_name = self.admin_os_creds.project_name
580
581         self.heat_cli = heat_utils.heat_client(self.heat_creds)
582         self.stack_creator = None
583
584         self.volume_name = self.guid + '-volume'
585         self.volume_type_name = self.guid + '-volume-type'
586
587         self.env_values = {
588             'volume_name': self.volume_name,
589             'volume_type_name': self.volume_type_name}
590
591         self.heat_tmplt_path = pkg_resources.resource_filename(
592             'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
593
594         stack_settings = StackSettings(
595             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
596             template_path=self.heat_tmplt_path,
597             env_values=self.env_values)
598         self.stack_creator = create_stack.OpenStackHeatStack(
599             self.heat_creds, stack_settings)
600         self.created_stack = self.stack_creator.create()
601         self.assertIsNotNone(self.created_stack)
602
603     def tearDown(self):
604         """
605         Cleans the stack and downloaded stack file
606         """
607         if self.stack_creator:
608             try:
609                 self.stack_creator.clean()
610             except:
611                 pass
612
613         super(self.__class__, self).__clean__()
614
615     def test_retrieve_volume_creator(self):
616         """
617         Tests the creation of an OpenStack stack from Heat template file and
618         the retrieval of an OpenStackVolume creator/state machine instance
619         """
620         volume_creators = self.stack_creator.get_volume_creators()
621         self.assertEqual(1, len(volume_creators))
622
623         creator = volume_creators[0]
624         self.assertEqual(self.volume_name, creator.volume_settings.name)
625         self.assertEqual(self.volume_name, creator.get_volume().name)
626         self.assertEqual(self.volume_type_name,
627                          creator.volume_settings.type_name)
628         self.assertEqual(self.volume_type_name, creator.get_volume().type)
629         self.assertEqual(1, creator.volume_settings.size)
630         self.assertEqual(1, creator.get_volume().size)
631
632     def test_retrieve_volume_type_creator(self):
633         """
634         Tests the creation of an OpenStack stack from Heat template file and
635         the retrieval of an OpenStackVolume creator/state machine instance
636         """
637         volume_type_creators = self.stack_creator.get_volume_type_creators()
638         self.assertEqual(1, len(volume_type_creators))
639
640         creator = volume_type_creators[0]
641         self.assertIsNotNone(creator)
642
643         volume_type = creator.get_volume_type()
644         self.assertIsNotNone(volume_type)
645
646         self.assertEqual(self.volume_type_name, volume_type.name)
647         self.assertTrue(volume_type.public)
648         self.assertIsNone(volume_type.qos_spec)
649
650         encryption = volume_type.encryption
651         self.assertIsNotNone(encryption)
652         self.assertIsNone(encryption.cipher)
653         self.assertEqual('front-end', encryption.control_location)
654         self.assertIsNone(encryption.key_size)
655         self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
656                          encryption.provider)
657         self.assertEqual(volume_type.id, encryption.volume_type_id)
658
659
660 class CreateStackFlavorTests(OSIntegrationTestCase):
661     """
662     Tests to ensure that floating IPs can be accessed via an
663     OpenStackFlavor object obtained from the OpenStackHeatStack instance
664     """
665
666     def setUp(self):
667
668         super(self.__class__, self).__start__()
669
670         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
671
672         self.heat_creds = self.admin_os_creds
673         self.heat_creds.project_name = self.admin_os_creds.project_name
674
675         self.heat_cli = heat_utils.heat_client(self.heat_creds)
676         self.stack_creator = None
677
678         self.heat_tmplt_path = pkg_resources.resource_filename(
679             'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
680
681         stack_settings = StackSettings(
682             name=self.guid + '-stack',
683             template_path=self.heat_tmplt_path)
684         self.stack_creator = create_stack.OpenStackHeatStack(
685             self.heat_creds, stack_settings)
686         self.created_stack = self.stack_creator.create()
687         self.assertIsNotNone(self.created_stack)
688
689     def tearDown(self):
690         """
691         Cleans the stack and downloaded stack file
692         """
693         if self.stack_creator:
694             try:
695                 self.stack_creator.clean()
696             except:
697                 pass
698
699         super(self.__class__, self).__clean__()
700
701     def test_retrieve_flavor_creator(self):
702         """
703         Tests the creation of an OpenStack stack from Heat template file and
704         the retrieval of an OpenStackVolume creator/state machine instance
705         """
706         flavor_creators = self.stack_creator.get_flavor_creators()
707         self.assertEqual(1, len(flavor_creators))
708
709         creator = flavor_creators[0]
710         self.assertTrue(creator.get_flavor().name.startswith(self.guid))
711         self.assertEqual(1024, creator.get_flavor().ram)
712         self.assertEqual(200, creator.get_flavor().disk)
713         self.assertEqual(8, creator.get_flavor().vcpus)
714         self.assertEqual(0, creator.get_flavor().ephemeral)
715         self.assertIsNone(creator.get_flavor().swap)
716         self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
717         self.assertTrue(creator.get_flavor().is_public)
718
719
720 class CreateStackKeypairTests(OSIntegrationTestCase):
721     """
722     Tests to ensure that floating IPs can be accessed via an
723     OpenStackKeypair object obtained from the OpenStackHeatStack instance
724     """
725
726     def setUp(self):
727
728         super(self.__class__, self).__start__()
729
730         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
731
732         self.heat_creds = self.admin_os_creds
733         self.heat_creds.project_name = self.admin_os_creds.project_name
734
735         self.heat_cli = heat_utils.heat_client(self.heat_creds)
736         self.nova = nova_utils.nova_client(self.heat_creds)
737         self.stack_creator = None
738
739         self.keypair_name = self.guid + '-kp'
740
741         self.env_values = {
742             'keypair_name': self.keypair_name}
743
744         self.heat_tmplt_path = pkg_resources.resource_filename(
745             'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
746
747         stack_settings = StackSettings(
748             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
749             template_path=self.heat_tmplt_path,
750             env_values=self.env_values)
751         self.stack_creator = create_stack.OpenStackHeatStack(
752             self.heat_creds, stack_settings)
753         self.created_stack = self.stack_creator.create()
754         self.assertIsNotNone(self.created_stack)
755
756     def tearDown(self):
757         """
758         Cleans the stack and downloaded stack file
759         """
760         if self.stack_creator:
761             try:
762                 self.stack_creator.clean()
763             except:
764                 pass
765
766         super(self.__class__, self).__clean__()
767
768     def test_retrieve_keypair_creator(self):
769         """
770         Tests the creation of an OpenStack stack from Heat template file and
771         the retrieval of an OpenStackKeypair creator/state machine instance
772         """
773         kp_creators = self.stack_creator.get_keypair_creators('private_key')
774         self.assertEqual(1, len(kp_creators))
775
776         creator = kp_creators[0]
777
778         self.assertEqual(self.keypair_name, creator.get_keypair().name)
779         self.assertIsNotNone(creator.keypair_settings.private_filepath)
780
781         private_file_contents = file_utils.read_file(
782             creator.keypair_settings.private_filepath)
783         self.assertTrue(private_file_contents.startswith(
784             '-----BEGIN RSA PRIVATE KEY-----'))
785
786         keypair = nova_utils.get_keypair_by_id(
787             self.nova, creator.get_keypair().id)
788         self.assertIsNotNone(keypair)
789         self.assertEqual(creator.get_keypair(), keypair)
790
791
792 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
793     """
794     Tests for the OpenStackHeatStack class to ensure it returns an
795     OpenStackSecurityGroup object
796     """
797
798     def setUp(self):
799         """
800         Instantiates the CreateStack object that is responsible for downloading
801         and creating an OS stack file within OpenStack
802         """
803         super(self.__class__, self).__start__()
804
805         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
806
807         self.heat_creds = self.admin_os_creds
808         self.heat_creds.project_name = self.admin_os_creds.project_name
809
810         self.heat_cli = heat_utils.heat_client(self.heat_creds)
811         self.nova = nova_utils.nova_client(self.heat_creds)
812         self.stack_creator = None
813
814         self.security_group_name = self.guid + '-sec-grp'
815
816         self.env_values = {
817             'security_group_name': self.security_group_name}
818
819         self.heat_tmplt_path = pkg_resources.resource_filename(
820             'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
821
822         stack_settings = StackSettings(
823             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
824             template_path=self.heat_tmplt_path,
825             env_values=self.env_values)
826         self.stack_creator = create_stack.OpenStackHeatStack(
827             self.heat_creds, stack_settings)
828         self.created_stack = self.stack_creator.create()
829         self.assertIsNotNone(self.created_stack)
830
831     def tearDown(self):
832         """
833         Cleans the stack and downloaded stack file
834         """
835         if self.stack_creator:
836             try:
837                 self.stack_creator.clean()
838             except:
839                 pass
840
841         super(self.__class__, self).__clean__()
842
843     def test_retrieve_security_group_creator(self):
844         """
845         Tests the creation of an OpenStack stack from Heat template file and
846         the retrieval of an OpenStackSecurityGroup creator/state machine
847         instance
848         """
849         sec_grp_creators = self.stack_creator.get_security_group_creators()
850         self.assertEqual(1, len(sec_grp_creators))
851
852         creator = sec_grp_creators[0]
853         sec_grp = creator.get_security_group()
854
855         self.assertEqual(self.security_group_name, sec_grp.name)
856         self.assertEqual('Test description', sec_grp.description)
857         self.assertEqual(2, len(sec_grp.rules))
858
859         has_ssh_rule = False
860         has_icmp_rule = False
861
862         for rule in sec_grp.rules:
863             if (rule.security_group_id == sec_grp.id
864                     and rule.direction == 'egress'
865                     and rule.ethertype == 'IPv4'
866                     and rule.port_range_min == 22
867                     and rule.port_range_max == 22
868                     and rule.protocol == 'tcp'
869                     and rule.remote_group_id is None
870                     and rule.remote_ip_prefix == '0.0.0.0/0'):
871                 has_ssh_rule = True
872             if (rule.security_group_id == sec_grp.id
873                     and rule.direction == 'ingress'
874                     and rule.ethertype == 'IPv4'
875                     and rule.port_range_min is None
876                     and rule.port_range_max is None
877                     and rule.protocol == 'icmp'
878                     and rule.remote_group_id is None
879                     and rule.remote_ip_prefix == '0.0.0.0/0'):
880                 has_icmp_rule = True
881
882         self.assertTrue(has_ssh_rule)
883         self.assertTrue(has_icmp_rule)
884
885
886 class CreateStackNegativeTests(OSIntegrationTestCase):
887     """
888     Negative test cases for the OpenStackHeatStack class with poor
889     configuration
890     """
891
892     def setUp(self):
893
894         super(self.__class__, self).__start__()
895
896         self.heat_creds = self.admin_os_creds
897         self.heat_creds.project_name = self.admin_os_creds.project_name
898
899         self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
900         self.stack_creator = None
901         self.heat_tmplt_path = pkg_resources.resource_filename(
902             'snaps.openstack.tests.heat', 'test_heat_template.yaml')
903
904     def tearDown(self):
905         if self.stack_creator:
906             self.stack_creator.clean()
907         super(self.__class__, self).__clean__()
908
909     def test_missing_dependencies(self):
910         """
911         Expect an StackCreationError when the stack file does not exist
912         """
913         stack_settings = StackSettings(name=self.stack_name,
914                                        template_path=self.heat_tmplt_path)
915         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
916                                                              stack_settings)
917         with self.assertRaises(HTTPBadRequest):
918             self.stack_creator.create()
919
920     def test_bad_stack_file(self):
921         """
922         Expect an StackCreationError when the stack file does not exist
923         """
924         stack_settings = StackSettings(name=self.stack_name,
925                                        template_path='foo')
926         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
927                                                              stack_settings)
928         with self.assertRaises(IOError):
929             self.stack_creator.create()
930
931
932 class CreateStackFailureTests(OSIntegrationTestCase):
933     """
934     Tests for the OpenStackHeatStack class defined in create_stack.py for
935     when failures occur. Failures are being triggered by allocating 1 million
936     CPUs.
937     """
938
939     def setUp(self):
940
941         super(self.__class__, self).__start__()
942
943         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
944
945         self.heat_creds = self.admin_os_creds
946         self.heat_creds.project_name = self.admin_os_creds.project_name
947
948         self.heat_cli = heat_utils.heat_client(self.heat_creds)
949         self.stack_creator = None
950
951         self.tmp_file = file_utils.save_string_to_file(
952             ' ', str(uuid.uuid4()) + '-bad-image')
953         self.image_creator = OpenStackImage(
954             self.heat_creds, ImageSettings(
955                 name=self.guid + 'image', image_file=self.tmp_file.name,
956                 image_user='foo', img_format='qcow2'))
957         self.image_creator.create()
958
959         # Create Flavor
960         self.flavor_creator = OpenStackFlavor(
961             self.admin_os_creds,
962             FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10,
963                            vcpus=1000000))
964         self.flavor_creator.create()
965
966         self.network_name = self.guid + '-net'
967         self.subnet_name = self.guid + '-subnet'
968         self.vm_inst_name = self.guid + '-inst'
969
970         self.env_values = {
971             'image_name': self.image_creator.image_settings.name,
972             'flavor_name': self.flavor_creator.flavor_settings.name,
973             'net_name': self.network_name,
974             'subnet_name': self.subnet_name,
975             'inst_name': self.vm_inst_name}
976
977         self.heat_tmplt_path = pkg_resources.resource_filename(
978             'snaps.openstack.tests.heat', 'test_heat_template.yaml')
979
980     def tearDown(self):
981         """
982         Cleans the stack and downloaded stack file
983         """
984         if self.stack_creator:
985             try:
986                 self.stack_creator.clean()
987             except:
988                 pass
989
990         if self.image_creator:
991             try:
992                 self.image_creator.clean()
993             except:
994                 pass
995
996         if self.flavor_creator:
997             try:
998                 self.flavor_creator.clean()
999             except:
1000                 pass
1001
1002         if self.tmp_file:
1003             try:
1004                 os.remove(self.tmp_file.name)
1005             except:
1006                 pass
1007
1008         super(self.__class__, self).__clean__()
1009
1010     def test_stack_failure(self):
1011         """
1012         Tests the creation of an OpenStack stack from Heat template file that
1013         should always fail due to too many CPU cores
1014         """
1015         # Create Stack
1016         # Set the default stack settings, then set any custom parameters sent
1017         # from the app
1018         stack_settings = StackSettings(
1019             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1020             template_path=self.heat_tmplt_path,
1021             env_values=self.env_values)
1022         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
1023                                                              stack_settings)
1024
1025         with self.assertRaises(StackError):
1026             try:
1027                 self.stack_creator.create()
1028             except StackError:
1029                 resources = heat_utils.get_resources(
1030                     self.heat_cli, self.stack_creator.get_stack())
1031
1032                 found = False
1033                 for resource in resources:
1034                     if resource.status == create_stack.STATUS_CREATE_COMPLETE:
1035                         found = True
1036                 self.assertTrue(found)
1037                 raise