Merge "Added method to OpenStackHeatStack to return OpenStackRouter objects."
[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 time
16
17 import pkg_resources
18 from heatclient.exc import HTTPBadRequest
19 from snaps import file_utils
20 from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings
21 from snaps.openstack.create_image import OpenStackImage
22
23 try:
24     from urllib.request import URLError
25 except ImportError:
26     from urllib2 import URLError
27
28 import logging
29 import unittest
30 import uuid
31
32 from snaps.openstack import create_stack
33 from snaps.openstack.create_stack import (
34     StackSettings, StackSettingsError, StackCreationError)
35 from snaps.openstack.tests import openstack_tests, create_instance_tests
36 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
37 from snaps.openstack.utils import heat_utils, neutron_utils, nova_utils
38
39 __author__ = 'spisarski'
40
41 logger = logging.getLogger('create_stack_tests')
42
43
44 class StackSettingsUnitTests(unittest.TestCase):
45     """
46     Tests the construction of the StackSettings class
47     """
48
49     def test_no_params(self):
50         with self.assertRaises(StackSettingsError):
51             StackSettings()
52
53     def test_empty_config(self):
54         with self.assertRaises(StackSettingsError):
55             StackSettings(**dict())
56
57     def test_name_only(self):
58         with self.assertRaises(StackSettingsError):
59             StackSettings(name='foo')
60
61     def test_config_with_name_only(self):
62         with self.assertRaises(StackSettingsError):
63             StackSettings(**{'name': 'foo'})
64
65     def test_config_minimum_template(self):
66         settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
67         self.assertEqual('stack', settings.name)
68         self.assertEqual('foo', settings.template)
69         self.assertIsNone(settings.template_path)
70         self.assertIsNone(settings.env_values)
71         self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
72                          settings.stack_create_timeout)
73
74     def test_config_minimum_template_path(self):
75         settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
76         self.assertEqual('stack', settings.name)
77         self.assertIsNone(settings.template)
78         self.assertEqual('foo', settings.template_path)
79         self.assertIsNone(settings.env_values)
80         self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
81                          settings.stack_create_timeout)
82
83     def test_minimum_template(self):
84         settings = StackSettings(name='stack', template='foo')
85         self.assertEqual('stack', settings.name)
86         self.assertEqual('foo', settings.template)
87         self.assertIsNone(settings.template_path)
88         self.assertIsNone(settings.env_values)
89         self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
90                          settings.stack_create_timeout)
91
92     def test_minimum_template_path(self):
93         settings = StackSettings(name='stack', template_path='foo')
94         self.assertEqual('stack', settings.name)
95         self.assertEqual('foo', settings.template_path)
96         self.assertIsNone(settings.template)
97         self.assertIsNone(settings.env_values)
98         self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
99                          settings.stack_create_timeout)
100
101     def test_all(self):
102         env_values = {'foo': 'bar'}
103         settings = StackSettings(name='stack', template='bar',
104                                  template_path='foo', env_values=env_values,
105                                  stack_create_timeout=999)
106         self.assertEqual('stack', settings.name)
107         self.assertEqual('bar', settings.template)
108         self.assertEqual('foo', settings.template_path)
109         self.assertEqual(env_values, settings.env_values)
110         self.assertEqual(999, settings.stack_create_timeout)
111
112     def test_config_all(self):
113         env_values = {'foo': 'bar'}
114         settings = StackSettings(
115             **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
116                'env_values': env_values, 'stack_create_timeout': 999})
117         self.assertEqual('stack', settings.name)
118         self.assertEqual('bar', settings.template)
119         self.assertEqual('foo', settings.template_path)
120         self.assertEqual(env_values, settings.env_values)
121         self.assertEqual(999, settings.stack_create_timeout)
122
123
124 class CreateStackSuccessTests(OSIntegrationTestCase):
125     """
126     Tests for the CreateStack class defined in create_stack.py
127     """
128
129     def setUp(self):
130         """
131         Instantiates the CreateStack object that is responsible for downloading
132         and creating an OS stack file within OpenStack
133         """
134         super(self.__class__, self).__start__()
135
136         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
137
138         self.heat_creds = self.admin_os_creds
139         self.heat_creds.project_name = self.admin_os_creds.project_name
140
141         self.heat_cli = heat_utils.heat_client(self.heat_creds)
142         self.stack_creator = None
143
144         self.image_creator = OpenStackImage(
145             self.heat_creds, openstack_tests.cirros_image_settings(
146                 name=self.guid + '-image',
147                 image_metadata=self.image_metadata))
148         self.image_creator.create()
149
150         # Create Flavor
151         self.flavor_creator = OpenStackFlavor(
152             self.admin_os_creds,
153             FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10,
154                            vcpus=1))
155         self.flavor_creator.create()
156
157         self.network_name = self.guid + '-net'
158         self.subnet_name = self.guid + '-subnet'
159         self.vm_inst_name = self.guid + '-inst'
160
161         self.env_values = {
162             'image_name': self.image_creator.image_settings.name,
163             'flavor_name': self.flavor_creator.flavor_settings.name,
164             'net_name': self.network_name,
165             'subnet_name': self.subnet_name,
166             'inst_name': self.vm_inst_name}
167
168         self.heat_tmplt_path = pkg_resources.resource_filename(
169             'snaps.openstack.tests.heat', 'test_heat_template.yaml')
170
171     def tearDown(self):
172         """
173         Cleans the stack and downloaded stack file
174         """
175         if self.stack_creator:
176             try:
177                 self.stack_creator.clean()
178             except:
179                 pass
180
181         if self.image_creator:
182             try:
183                 self.image_creator.clean()
184             except:
185                 pass
186
187         if self.flavor_creator:
188             try:
189                 self.flavor_creator.clean()
190             except:
191                 pass
192
193         super(self.__class__, self).__clean__()
194
195     def test_create_stack_template_file(self):
196         """
197         Tests the creation of an OpenStack stack from Heat template file.
198         """
199         # Create Stack
200         # Set the default stack settings, then set any custom parameters sent
201         # from the app
202         stack_settings = StackSettings(
203             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
204             template_path=self.heat_tmplt_path,
205             env_values=self.env_values)
206         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
207                                                              stack_settings)
208         created_stack = self.stack_creator.create()
209         self.assertIsNotNone(created_stack)
210
211         retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
212                                                      created_stack.id)
213         self.assertIsNotNone(retrieved_stack)
214         self.assertEqual(created_stack.name, retrieved_stack.name)
215         self.assertEqual(created_stack.id, retrieved_stack.id)
216         self.assertEqual(0, len(self.stack_creator.get_outputs()))
217
218     def test_create_stack_short_timeout(self):
219         """
220         Tests the creation of an OpenStack stack from Heat template file.
221         """
222         # Create Stack
223         # Set the default stack settings, then set any custom parameters sent
224         # from the app
225         stack_settings = StackSettings(
226             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
227             template_path=self.heat_tmplt_path,
228             env_values=self.env_values, stack_create_timeout=0)
229
230         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
231                                                              stack_settings)
232         with self.assertRaises(StackCreationError):
233             self.stack_creator.create()
234
235     def test_create_stack_template_dict(self):
236         """
237         Tests the creation of an OpenStack stack from a heat dict() object.
238         """
239         # Create Stack
240         # Set the default stack settings, then set any custom parameters sent
241         # from the app
242         template_dict = heat_utils.parse_heat_template_str(
243             file_utils.read_file(self.heat_tmplt_path))
244         stack_settings = StackSettings(
245             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
246             template=template_dict,
247             env_values=self.env_values)
248         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
249                                                              stack_settings)
250         created_stack = self.stack_creator.create()
251         self.assertIsNotNone(created_stack)
252
253         retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
254                                                      created_stack.id)
255         self.assertIsNotNone(retrieved_stack)
256         self.assertEqual(created_stack.name, retrieved_stack.name)
257         self.assertEqual(created_stack.id, retrieved_stack.id)
258         self.assertEqual(0, len(self.stack_creator.get_outputs()))
259
260     def test_create_delete_stack(self):
261         """
262         Tests the creation then deletion of an OpenStack stack to ensure
263         clean() does not raise an Exception.
264         """
265         # Create Stack
266         template_dict = heat_utils.parse_heat_template_str(
267             file_utils.read_file(self.heat_tmplt_path))
268         stack_settings = StackSettings(
269             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
270             template=template_dict,
271             env_values=self.env_values)
272         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
273                                                              stack_settings)
274         created_stack = self.stack_creator.create()
275         self.assertIsNotNone(created_stack)
276
277         retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
278                                                      created_stack.id)
279         self.assertIsNotNone(retrieved_stack)
280         self.assertEqual(created_stack.name, retrieved_stack.name)
281         self.assertEqual(created_stack.id, retrieved_stack.id)
282         self.assertEqual(0, len(self.stack_creator.get_outputs()))
283         self.assertEqual(create_stack.STATUS_CREATE_COMPLETE,
284                          self.stack_creator.get_status())
285
286         # Delete Stack manually
287         heat_utils.delete_stack(self.heat_cli, created_stack)
288
289         end_time = time.time() + 90
290         deleted = False
291         while time.time() < end_time:
292             status = heat_utils.get_stack_status(self.heat_cli,
293                                                  retrieved_stack.id)
294             if status == create_stack.STATUS_DELETE_COMPLETE:
295                 deleted = True
296                 break
297
298         self.assertTrue(deleted)
299
300         # Must not throw an exception when attempting to cleanup non-existent
301         # stack
302         self.stack_creator.clean()
303         self.assertIsNone(self.stack_creator.get_stack())
304
305     def test_create_same_stack(self):
306         """
307         Tests the creation of an OpenStack stack when the stack already exists.
308         """
309         # Create Stack
310         template_dict = heat_utils.parse_heat_template_str(
311             file_utils.read_file(self.heat_tmplt_path))
312         stack_settings = StackSettings(
313             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
314             template=template_dict,
315             env_values=self.env_values)
316         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
317                                                              stack_settings)
318         created_stack1 = self.stack_creator.create()
319
320         retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
321                                                      created_stack1.id)
322         self.assertIsNotNone(retrieved_stack)
323         self.assertEqual(created_stack1.name, retrieved_stack.name)
324         self.assertEqual(created_stack1.id, retrieved_stack.id)
325         self.assertEqual(0, len(self.stack_creator.get_outputs()))
326
327         # Should be retrieving the instance data
328         stack_creator2 = create_stack.OpenStackHeatStack(self.heat_creds,
329                                                          stack_settings)
330         stack2 = stack_creator2.create()
331         self.assertEqual(created_stack1.id, stack2.id)
332
333     def test_retrieve_network_creators(self):
334         """
335         Tests the creation of an OpenStack stack from Heat template file and
336         the retrieval of the network creator.
337         """
338         stack_settings = StackSettings(
339             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
340             template_path=self.heat_tmplt_path,
341             env_values=self.env_values)
342         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
343                                                              stack_settings)
344         created_stack = self.stack_creator.create()
345         self.assertIsNotNone(created_stack)
346
347         net_creators = self.stack_creator.get_network_creators()
348         self.assertIsNotNone(net_creators)
349         self.assertEqual(1, len(net_creators))
350         self.assertEqual(self.network_name, net_creators[0].get_network().name)
351
352         neutron = neutron_utils.neutron_client(self.os_creds)
353         net_by_name = neutron_utils.get_network(
354             neutron, network_name=net_creators[0].get_network().name)
355         self.assertEqual(net_creators[0].get_network(), net_by_name)
356         self.assertIsNotNone(neutron_utils.get_network_by_id(
357             neutron, net_creators[0].get_network().id))
358
359         self.assertEqual(1, len(net_creators[0].get_subnets()))
360         subnet = net_creators[0].get_subnets()[0]
361         subnet_by_name = neutron_utils.get_subnet(
362             neutron, subnet_name=subnet.name)
363         self.assertEqual(subnet, subnet_by_name)
364
365         subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
366         self.assertIsNotNone(subnet_by_id)
367         self.assertEqual(subnet_by_name, subnet_by_id)
368
369     def test_retrieve_vm_inst_creators(self):
370         """
371         Tests the creation of an OpenStack stack from Heat template file and
372         the retrieval of the network creator.
373         """
374         stack_settings = StackSettings(
375             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
376             template_path=self.heat_tmplt_path,
377             env_values=self.env_values)
378         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
379                                                              stack_settings)
380         created_stack = self.stack_creator.create()
381         self.assertIsNotNone(created_stack)
382
383         vm_inst_creators = self.stack_creator.get_vm_inst_creators()
384         self.assertIsNotNone(vm_inst_creators)
385         self.assertEqual(1, len(vm_inst_creators))
386         self.assertEqual(self.vm_inst_name,
387                          vm_inst_creators[0].get_vm_inst().name)
388
389         nova = nova_utils.nova_client(self.admin_os_creds)
390         vm_inst_by_name = nova_utils.get_server(
391             nova, server_name=vm_inst_creators[0].get_vm_inst().name)
392         self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
393         self.assertIsNotNone(nova_utils.get_server_object_by_id(
394             nova, vm_inst_creators[0].get_vm_inst().id))
395
396
397 class CreateStackFloatingIpTests(OSIntegrationTestCase):
398     """
399     Tests for the CreateStack class defined in create_stack.py
400     """
401
402     def setUp(self):
403         """
404         Instantiates the CreateStack object that is responsible for downloading
405         and creating an OS stack file within OpenStack
406         """
407         super(self.__class__, self).__start__()
408
409         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
410
411         self.heat_creds = self.admin_os_creds
412         self.heat_creds.project_name = self.admin_os_creds.project_name
413
414         self.heat_cli = heat_utils.heat_client(self.heat_creds)
415         self.stack_creator = None
416
417         self.image_creator = OpenStackImage(
418             self.heat_creds, openstack_tests.cirros_image_settings(
419                 name=self.guid + '-image',
420                 image_metadata=self.image_metadata))
421         self.image_creator.create()
422
423         self.network_name = self.guid + '-net'
424         self.subnet_name = self.guid + '-subnet'
425         self.flavor1_name = self.guid + '-flavor1'
426         self.flavor2_name = self.guid + '-flavor2'
427         self.sec_grp_name = self.guid + '-sec_grp'
428         self.vm_inst1_name = self.guid + '-inst1'
429         self.vm_inst2_name = self.guid + '-inst2'
430         self.keypair_name = self.guid + '-kp'
431
432         self.env_values = {
433             'image1_name': self.image_creator.image_settings.name,
434             'image2_name': self.image_creator.image_settings.name,
435             'flavor1_name': self.flavor1_name,
436             'flavor2_name': self.flavor2_name,
437             'net_name': self.network_name,
438             'subnet_name': self.subnet_name,
439             'inst1_name': self.vm_inst1_name,
440             'inst2_name': self.vm_inst2_name,
441             'keypair_name': self.keypair_name,
442             'external_net_name': self.ext_net_name,
443             'security_group_name': self.sec_grp_name}
444
445         self.heat_tmplt_path = pkg_resources.resource_filename(
446             'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
447
448     def tearDown(self):
449         """
450         Cleans the stack and downloaded stack file
451         """
452         if self.stack_creator:
453             try:
454                 self.stack_creator.clean()
455             except:
456                 pass
457
458         if self.image_creator:
459             try:
460                 self.image_creator.clean()
461             except:
462                 pass
463
464         super(self.__class__, self).__clean__()
465
466     def test_connect_via_ssh_heat_vm(self):
467         """
468         Tests the creation of an OpenStack stack from Heat template file and
469         the retrieval of two VM instance creators and attempt to connect via
470         SSH to the first one with a floating IP.
471         """
472         stack_settings = StackSettings(
473             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
474             template_path=self.heat_tmplt_path,
475             env_values=self.env_values)
476         self.stack_creator = create_stack.OpenStackHeatStack(
477             self.heat_creds, stack_settings,
478             [self.image_creator.image_settings])
479         created_stack = self.stack_creator.create()
480         self.assertIsNotNone(created_stack)
481
482         vm_inst_creators = self.stack_creator.get_vm_inst_creators(
483             heat_keypair_option='private_key')
484         self.assertIsNotNone(vm_inst_creators)
485         self.assertEqual(2, len(vm_inst_creators))
486
487         for vm_inst_creator in vm_inst_creators:
488             if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
489                 self.assertTrue(
490                     create_instance_tests.validate_ssh_client(vm_inst_creator))
491             else:
492                 vm_settings = vm_inst_creator.instance_settings
493                 self.assertEqual(0, len(vm_settings.floating_ip_settings))
494
495
496 class CreateStackRouterTests(OSIntegrationTestCase):
497     """
498     Tests for the CreateStack class defined in create_stack.py where the
499     target is a Network, Subnet, and Router
500     """
501
502     def setUp(self):
503         """
504         Instantiates the CreateStack object that is responsible for downloading
505         and creating an OS stack file within OpenStack
506         """
507         super(self.__class__, self).__start__()
508
509         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
510
511         self.heat_creds = self.admin_os_creds
512         self.heat_creds.project_name = self.admin_os_creds.project_name
513
514         self.heat_cli = heat_utils.heat_client(self.heat_creds)
515         self.neutron = neutron_utils.neutron_client(self.os_creds)
516         self.stack_creator = None
517
518         self.net_name = self.guid + '-net'
519         self.subnet_name = self.guid + '-subnet'
520         self.router_name = self.guid + '-router'
521
522         self.env_values = {
523             'net_name': self.net_name,
524             'subnet_name': self.subnet_name,
525             'router_name': self.router_name,
526             'external_net_name': self.ext_net_name}
527
528         self.heat_tmplt_path = pkg_resources.resource_filename(
529             'snaps.openstack.tests.heat', 'router_heat_template.yaml')
530
531         stack_settings = StackSettings(
532             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
533             template_path=self.heat_tmplt_path,
534             env_values=self.env_values)
535         self.stack_creator = create_stack.OpenStackHeatStack(
536             self.heat_creds, stack_settings)
537         self.created_stack = self.stack_creator.create()
538         self.assertIsNotNone(self.created_stack)
539
540     def tearDown(self):
541         """
542         Cleans the stack and downloaded stack file
543         """
544         if self.stack_creator:
545             try:
546                 self.stack_creator.clean()
547             except:
548                 pass
549
550         super(self.__class__, self).__clean__()
551
552     def test_retrieve_router_creator(self):
553         """
554         Tests the creation of an OpenStack stack from Heat template file and
555         the retrieval of an OpenStackRouter creator/state machine instance
556         """
557         router_creators = self.stack_creator.get_router_creators()
558         self.assertEqual(1, len(router_creators))
559
560         creator = router_creators[0]
561         self.assertEqual(self.router_name, creator.router_settings.name)
562
563         router = creator.get_router()
564
565         ext_net = neutron_utils.get_network(
566             self.neutron, network_name=self.ext_net_name)
567         self.assertEqual(ext_net.id, router.external_network_id)
568
569
570 class CreateStackVolumeTests(OSIntegrationTestCase):
571     """
572     Tests for the CreateStack class as they pertain to volumes
573     """
574
575     def setUp(self):
576         """
577         Instantiates the CreateStack object that is responsible for downloading
578         and creating an OS stack file within OpenStack
579         """
580         super(self.__class__, self).__start__()
581
582         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
583
584         self.heat_creds = self.admin_os_creds
585         self.heat_creds.project_name = self.admin_os_creds.project_name
586
587         self.heat_cli = heat_utils.heat_client(self.heat_creds)
588         self.stack_creator = None
589
590         self.volume_name = self.guid + '-volume'
591         self.volume_type_name = self.guid + '-volume-type'
592
593         self.env_values = {
594             'volume_name': self.volume_name,
595             'volume_type_name': self.volume_type_name}
596
597         self.heat_tmplt_path = pkg_resources.resource_filename(
598             'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
599
600         stack_settings = StackSettings(
601             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
602             template_path=self.heat_tmplt_path,
603             env_values=self.env_values)
604         self.stack_creator = create_stack.OpenStackHeatStack(
605             self.heat_creds, stack_settings)
606         self.created_stack = self.stack_creator.create()
607         self.assertIsNotNone(self.created_stack)
608
609     def tearDown(self):
610         """
611         Cleans the stack and downloaded stack file
612         """
613         if self.stack_creator:
614             try:
615                 self.stack_creator.clean()
616             except:
617                 pass
618
619         super(self.__class__, self).__clean__()
620
621     def test_retrieve_volume_creator(self):
622         """
623         Tests the creation of an OpenStack stack from Heat template file and
624         the retrieval of an OpenStackVolume creator/state machine instance
625         """
626         volume_creators = self.stack_creator.get_volume_creators()
627         self.assertEqual(1, len(volume_creators))
628
629         creator = volume_creators[0]
630         self.assertEqual(self.volume_name, creator.volume_settings.name)
631         self.assertEqual(self.volume_name, creator.get_volume().name)
632         self.assertEqual(self.volume_type_name,
633                          creator.volume_settings.type_name)
634         self.assertEqual(self.volume_type_name, creator.get_volume().type)
635         self.assertEqual(1, creator.volume_settings.size)
636         self.assertEqual(1, creator.get_volume().size)
637
638     def test_retrieve_volume_type_creator(self):
639         """
640         Tests the creation of an OpenStack stack from Heat template file and
641         the retrieval of an OpenStackVolume creator/state machine instance
642         """
643         volume_type_creators = self.stack_creator.get_volume_type_creators()
644         self.assertEqual(1, len(volume_type_creators))
645
646         creator = volume_type_creators[0]
647         self.assertIsNotNone(creator)
648
649         volume_type = creator.get_volume_type()
650         self.assertIsNotNone(volume_type)
651
652         self.assertEqual(self.volume_type_name, volume_type.name)
653         self.assertTrue(volume_type.public)
654         self.assertIsNone(volume_type.qos_spec)
655
656         encryption = volume_type.encryption
657         self.assertIsNotNone(encryption)
658         self.assertIsNone(encryption.cipher)
659         self.assertEqual('front-end', encryption.control_location)
660         self.assertIsNone(encryption.key_size)
661         self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
662                          encryption.provider)
663         self.assertEqual(volume_type.id, encryption.volume_type_id)
664
665
666 class CreateStackFlavorTests(OSIntegrationTestCase):
667     """
668     Tests for the CreateStack class defined in create_stack.py
669     """
670
671     def setUp(self):
672         """
673         Instantiates the CreateStack object that is responsible for downloading
674         and creating an OS stack file within OpenStack
675         """
676         super(self.__class__, self).__start__()
677
678         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
679
680         self.heat_creds = self.admin_os_creds
681         self.heat_creds.project_name = self.admin_os_creds.project_name
682
683         self.heat_cli = heat_utils.heat_client(self.heat_creds)
684         self.stack_creator = None
685
686         self.heat_tmplt_path = pkg_resources.resource_filename(
687             'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
688
689         stack_settings = StackSettings(
690             name=self.guid + '-stack',
691             template_path=self.heat_tmplt_path)
692         self.stack_creator = create_stack.OpenStackHeatStack(
693             self.heat_creds, stack_settings)
694         self.created_stack = self.stack_creator.create()
695         self.assertIsNotNone(self.created_stack)
696
697     def tearDown(self):
698         """
699         Cleans the stack and downloaded stack file
700         """
701         if self.stack_creator:
702             try:
703                 self.stack_creator.clean()
704             except:
705                 pass
706
707         super(self.__class__, self).__clean__()
708
709     def test_retrieve_flavor_creator(self):
710         """
711         Tests the creation of an OpenStack stack from Heat template file and
712         the retrieval of an OpenStackVolume creator/state machine instance
713         """
714         flavor_creators = self.stack_creator.get_flavor_creators()
715         self.assertEqual(1, len(flavor_creators))
716
717         creator = flavor_creators[0]
718         self.assertTrue(creator.get_flavor().name.startswith(self.guid))
719         self.assertEqual(1024, creator.get_flavor().ram)
720         self.assertEqual(200, creator.get_flavor().disk)
721         self.assertEqual(8, creator.get_flavor().vcpus)
722         self.assertEqual(0, creator.get_flavor().ephemeral)
723         self.assertIsNone(creator.get_flavor().swap)
724         self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
725         self.assertTrue(creator.get_flavor().is_public)
726
727
728 class CreateStackKeypairTests(OSIntegrationTestCase):
729     """
730     Tests for the CreateStack class as they pertain to keypairs
731     """
732
733     def setUp(self):
734         """
735         Instantiates the CreateStack object that is responsible for downloading
736         and creating an OS stack file within OpenStack
737         """
738         super(self.__class__, self).__start__()
739
740         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
741
742         self.heat_creds = self.admin_os_creds
743         self.heat_creds.project_name = self.admin_os_creds.project_name
744
745         self.heat_cli = heat_utils.heat_client(self.heat_creds)
746         self.nova = nova_utils.nova_client(self.heat_creds)
747         self.stack_creator = None
748
749         self.keypair_name = self.guid + '-kp'
750
751         self.env_values = {
752             'keypair_name': self.keypair_name}
753
754         self.heat_tmplt_path = pkg_resources.resource_filename(
755             'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
756
757         stack_settings = StackSettings(
758             name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
759             template_path=self.heat_tmplt_path,
760             env_values=self.env_values)
761         self.stack_creator = create_stack.OpenStackHeatStack(
762             self.heat_creds, stack_settings)
763         self.created_stack = self.stack_creator.create()
764         self.assertIsNotNone(self.created_stack)
765
766     def tearDown(self):
767         """
768         Cleans the stack and downloaded stack file
769         """
770         if self.stack_creator:
771             try:
772                 self.stack_creator.clean()
773             except:
774                 pass
775
776         super(self.__class__, self).__clean__()
777
778     def test_retrieve_keypair_creator(self):
779         """
780         Tests the creation of an OpenStack stack from Heat template file and
781         the retrieval of an OpenStackKeypair creator/state machine instance
782         """
783         kp_creators = self.stack_creator.get_keypair_creators('private_key')
784         self.assertEqual(1, len(kp_creators))
785
786         creator = kp_creators[0]
787
788         self.assertEqual(self.keypair_name, creator.get_keypair().name)
789         self.assertIsNotNone(creator.keypair_settings.private_filepath)
790
791         private_file_contents = file_utils.read_file(
792             creator.keypair_settings.private_filepath)
793         self.assertTrue(private_file_contents.startswith(
794             '-----BEGIN RSA PRIVATE KEY-----'))
795
796         keypair = nova_utils.get_keypair_by_id(
797             self.nova, creator.get_keypair().id)
798         self.assertIsNotNone(keypair)
799         self.assertEqual(creator.get_keypair(), keypair)
800
801
802 class CreateStackNegativeTests(OSIntegrationTestCase):
803     """
804     Negative test cases for the CreateStack class
805     """
806
807     def setUp(self):
808         super(self.__class__, self).__start__()
809
810         self.heat_creds = self.admin_os_creds
811         self.heat_creds.project_name = self.admin_os_creds.project_name
812
813         self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
814         self.stack_creator = None
815         self.heat_tmplt_path = pkg_resources.resource_filename(
816             'snaps.openstack.tests.heat', 'test_heat_template.yaml')
817
818     def tearDown(self):
819         if self.stack_creator:
820             self.stack_creator.clean()
821         super(self.__class__, self).__clean__()
822
823     def test_missing_dependencies(self):
824         """
825         Expect an StackCreationError when the stack file does not exist
826         """
827         stack_settings = StackSettings(name=self.stack_name,
828                                        template_path=self.heat_tmplt_path)
829         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
830                                                              stack_settings)
831         with self.assertRaises(HTTPBadRequest):
832             self.stack_creator.create()
833
834     def test_bad_stack_file(self):
835         """
836         Expect an StackCreationError when the stack file does not exist
837         """
838         stack_settings = StackSettings(name=self.stack_name,
839                                        template_path='foo')
840         self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
841                                                              stack_settings)
842         with self.assertRaises(IOError):
843             self.stack_creator.create()