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