1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
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:
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
19 from heatclient.exc import HTTPBadRequest
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
30 from urllib.request import URLError
32 from urllib2 import URLError
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 (
43 heat_utils, neutron_utils, nova_utils, keystone_utils)
45 __author__ = 'spisarski'
47 logger = logging.getLogger('create_stack_tests')
50 class StackSettingsUnitTests(unittest.TestCase):
52 Tests the construction of the StackSettings class
55 def test_no_params(self):
56 with self.assertRaises(StackConfigError):
59 def test_empty_config(self):
60 with self.assertRaises(StackConfigError):
61 StackSettings(**dict())
63 def test_name_only(self):
64 with self.assertRaises(StackConfigError):
65 StackSettings(name='foo')
67 def test_config_with_name_only(self):
68 with self.assertRaises(StackConfigError):
69 StackSettings(**{'name': 'foo'})
71 def test_config_minimum_template(self):
72 settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
73 self.assertEqual('stack', settings.name)
74 self.assertEqual('foo', settings.template)
75 self.assertIsNone(settings.template_path)
76 self.assertIsNone(settings.env_values)
77 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
78 settings.stack_create_timeout)
80 def test_config_minimum_template_path(self):
81 settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
82 self.assertEqual('stack', settings.name)
83 self.assertIsNone(settings.template)
84 self.assertEqual('foo', settings.template_path)
85 self.assertIsNone(settings.env_values)
86 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
87 settings.stack_create_timeout)
89 def test_minimum_template(self):
90 settings = StackSettings(name='stack', template='foo')
91 self.assertEqual('stack', settings.name)
92 self.assertEqual('foo', settings.template)
93 self.assertIsNone(settings.template_path)
94 self.assertIsNone(settings.env_values)
95 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
96 settings.stack_create_timeout)
98 def test_minimum_template_path(self):
99 settings = StackSettings(name='stack', template_path='foo')
100 self.assertEqual('stack', settings.name)
101 self.assertEqual('foo', settings.template_path)
102 self.assertIsNone(settings.template)
103 self.assertIsNone(settings.env_values)
104 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
105 settings.stack_create_timeout)
108 env_values = {'foo': 'bar'}
109 settings = StackSettings(name='stack', template='bar',
110 template_path='foo', env_values=env_values,
111 stack_create_timeout=999)
112 self.assertEqual('stack', settings.name)
113 self.assertEqual('bar', settings.template)
114 self.assertEqual('foo', settings.template_path)
115 self.assertEqual(env_values, settings.env_values)
116 self.assertEqual(999, settings.stack_create_timeout)
118 def test_config_all(self):
119 env_values = {'foo': 'bar'}
120 settings = StackSettings(
121 **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
122 'env_values': env_values, 'stack_create_timeout': 999})
123 self.assertEqual('stack', settings.name)
124 self.assertEqual('bar', settings.template)
125 self.assertEqual('foo', settings.template_path)
126 self.assertEqual(env_values, settings.env_values)
127 self.assertEqual(999, settings.stack_create_timeout)
130 class CreateStackSuccessTests(OSIntegrationTestCase):
132 Tests for the OpenStackHeatStack class defined in create_stack.py
136 self.user_roles = ['heat_stack_owner']
138 super(self.__class__, self).__start__()
140 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
142 self.heat_cli = heat_utils.heat_client(self.os_creds)
143 self.stack_creator = None
145 self.image_creator = OpenStackImage(
146 self.os_creds, openstack_tests.cirros_image_settings(
147 name=self.guid + '-image',
148 image_metadata=self.image_metadata))
149 self.image_creator.create()
152 self.flavor_creator = OpenStackFlavor(
155 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
156 self.flavor_creator.create()
158 self.network_name = self.guid + '-net'
159 self.subnet_name = self.guid + '-subnet'
160 self.vm_inst_name = self.guid + '-inst'
163 'image_name': self.image_creator.image_settings.name,
164 'flavor_name': self.flavor_creator.flavor_settings.name,
165 'net_name': self.network_name,
166 'subnet_name': self.subnet_name,
167 'inst_name': self.vm_inst_name}
169 self.heat_tmplt_path = pkg_resources.resource_filename(
170 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
174 Cleans the stack and downloaded stack file
176 if self.stack_creator:
178 self.stack_creator.clean()
182 if self.image_creator:
184 self.image_creator.clean()
188 if self.flavor_creator:
190 self.flavor_creator.clean()
194 super(self.__class__, self).__clean__()
196 def test_create_stack_template_file(self):
198 Tests the creation of an OpenStack stack from Heat template file.
201 # Set the default stack settings, then set any custom parameters sent
203 stack_settings = StackConfig(
204 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
205 template_path=self.heat_tmplt_path,
206 env_values=self.env_values)
207 self.stack_creator = OpenStackHeatStack(
208 self.os_creds, stack_settings)
209 created_stack = self.stack_creator.create()
210 self.assertIsNotNone(created_stack)
212 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
214 self.assertIsNotNone(retrieved_stack)
215 self.assertEqual(created_stack.name, retrieved_stack.name)
216 self.assertEqual(created_stack.id, retrieved_stack.id)
217 self.assertEqual(0, len(self.stack_creator.get_outputs()))
219 def test_create_stack_short_timeout(self):
221 Tests the creation of an OpenStack stack from Heat template file.
224 # Set the default stack settings, then set any custom parameters sent
226 stack_settings = StackConfig(
227 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
228 template_path=self.heat_tmplt_path,
229 env_values=self.env_values, stack_create_timeout=0)
231 self.stack_creator = OpenStackHeatStack(
232 self.os_creds, stack_settings)
233 with self.assertRaises(StackCreationError):
234 self.stack_creator.create()
236 def test_create_stack_template_dict(self):
238 Tests the creation of an OpenStack stack from a heat dict() object.
241 # Set the default stack settings, then set any custom parameters sent
243 template_dict = heat_utils.parse_heat_template_str(
244 file_utils.read_file(self.heat_tmplt_path))
245 stack_settings = StackConfig(
246 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
247 template=template_dict,
248 env_values=self.env_values)
249 self.stack_creator = OpenStackHeatStack(
250 self.os_creds, stack_settings)
251 created_stack = self.stack_creator.create()
252 self.assertIsNotNone(created_stack)
254 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
256 self.assertIsNotNone(retrieved_stack)
257 self.assertEqual(created_stack.name, retrieved_stack.name)
258 self.assertEqual(created_stack.id, retrieved_stack.id)
259 self.assertEqual(0, len(self.stack_creator.get_outputs()))
261 def test_create_delete_stack(self):
263 Tests the creation then deletion of an OpenStack stack to ensure
264 clean() does not raise an Exception.
267 template_dict = heat_utils.parse_heat_template_str(
268 file_utils.read_file(self.heat_tmplt_path))
269 stack_settings = StackConfig(
270 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
271 template=template_dict,
272 env_values=self.env_values)
273 self.stack_creator = OpenStackHeatStack(
274 self.os_creds, stack_settings)
275 created_stack = self.stack_creator.create()
276 self.assertIsNotNone(created_stack)
278 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
280 self.assertIsNotNone(retrieved_stack)
281 self.assertEqual(created_stack.name, retrieved_stack.name)
282 self.assertEqual(created_stack.id, retrieved_stack.id)
283 self.assertEqual(0, len(self.stack_creator.get_outputs()))
284 self.assertEqual(snaps.config.stack.STATUS_CREATE_COMPLETE,
285 self.stack_creator.get_status())
287 # Delete Stack manually
288 heat_utils.delete_stack(self.heat_cli, created_stack)
290 end_time = time.time() + 90
292 while time.time() < end_time:
293 status = heat_utils.get_stack_status(self.heat_cli,
295 if status == snaps.config.stack.STATUS_DELETE_COMPLETE:
299 self.assertTrue(deleted)
301 # Must not throw an exception when attempting to cleanup non-existent
303 self.stack_creator.clean()
304 self.assertIsNone(self.stack_creator.get_stack())
306 def test_create_same_stack(self):
308 Tests the creation of an OpenStack stack when the stack already exists.
311 template_dict = heat_utils.parse_heat_template_str(
312 file_utils.read_file(self.heat_tmplt_path))
313 stack_settings = StackConfig(
314 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
315 template=template_dict,
316 env_values=self.env_values)
317 self.stack_creator = OpenStackHeatStack(
318 self.os_creds, stack_settings)
319 created_stack1 = self.stack_creator.create()
321 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
323 self.assertIsNotNone(retrieved_stack)
324 self.assertEqual(created_stack1.name, retrieved_stack.name)
325 self.assertEqual(created_stack1.id, retrieved_stack.id)
326 self.assertEqual(0, len(self.stack_creator.get_outputs()))
328 # Should be retrieving the instance data
329 stack_creator2 = OpenStackHeatStack(self.os_creds, stack_settings)
330 stack2 = stack_creator2.create()
331 self.assertEqual(created_stack1.id, stack2.id)
333 def test_retrieve_network_creators(self):
335 Tests the creation of an OpenStack stack from Heat template file and
336 the retrieval of the network creator.
338 stack_settings = StackConfig(
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 = OpenStackHeatStack(
343 self.os_creds, stack_settings)
344 created_stack = self.stack_creator.create()
345 self.assertIsNotNone(created_stack)
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)
352 # Need to use 'admin' creds as heat creates objects under it's own
354 neutron = neutron_utils.neutron_client(self.os_creds)
355 keystone = keystone_utils.keystone_client(self.os_creds)
356 net_by_name = neutron_utils.get_network(
357 neutron, keystone, network_name=net_creators[0].get_network().name)
358 self.assertEqual(net_creators[0].get_network(), net_by_name)
359 self.assertIsNotNone(neutron_utils.get_network_by_id(
360 neutron, net_creators[0].get_network().id))
362 self.assertEqual(1, len(net_creators[0].get_network().subnets))
363 subnet = net_creators[0].get_network().subnets[0]
364 subnet_by_name = neutron_utils.get_subnet(
365 neutron, subnet_name=subnet.name)
366 self.assertEqual(subnet, subnet_by_name)
368 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
369 self.assertIsNotNone(subnet_by_id)
370 self.assertEqual(subnet_by_name, subnet_by_id)
372 def test_retrieve_vm_inst_creators(self):
374 Tests the creation of an OpenStack stack from Heat template file and
375 the retrieval of the network creator.
377 stack_settings = StackConfig(
378 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
379 template_path=self.heat_tmplt_path,
380 env_values=self.env_values)
381 self.stack_creator = OpenStackHeatStack(
382 self.os_creds, stack_settings)
383 created_stack = self.stack_creator.create()
384 self.assertIsNotNone(created_stack)
386 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
387 self.assertIsNotNone(vm_inst_creators)
388 self.assertEqual(1, len(vm_inst_creators))
389 self.assertEqual(self.vm_inst_name,
390 vm_inst_creators[0].get_vm_inst().name)
392 nova = nova_utils.nova_client(self.os_creds)
393 neutron = neutron_utils.neutron_client(self.os_creds)
394 keystone = keystone_utils.keystone_client(self.os_creds)
395 vm_inst_by_name = nova_utils.get_server(
396 nova, neutron, keystone,
397 server_name=vm_inst_creators[0].get_vm_inst().name)
399 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
400 self.assertIsNotNone(nova_utils.get_server_object_by_id(
401 nova, neutron, keystone, vm_inst_creators[0].get_vm_inst().id))
404 class CreateStackFloatingIpTests(OSIntegrationTestCase):
406 Tests to ensure that floating IPs can be accessed via an
407 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
411 self.user_roles = ['heat_stack_owner', 'admin']
413 super(self.__class__, self).__start__()
415 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
417 self.heat_cli = heat_utils.heat_client(self.os_creds)
418 self.stack_creator = None
420 self.image_creator = OpenStackImage(
421 self.os_creds, openstack_tests.cirros_image_settings(
422 name=self.guid + '-image',
423 image_metadata=self.image_metadata))
424 self.image_creator.create()
426 self.network_name = self.guid + '-net'
427 self.subnet_name = self.guid + '-subnet'
428 self.flavor1_name = self.guid + '-flavor1'
429 self.flavor2_name = self.guid + '-flavor2'
430 self.sec_grp_name = self.guid + '-sec_grp'
431 self.vm_inst1_name = self.guid + '-inst1'
432 self.vm_inst2_name = self.guid + '-inst2'
433 self.keypair_name = self.guid + '-kp'
436 'image1_name': self.image_creator.image_settings.name,
437 'image2_name': self.image_creator.image_settings.name,
438 'flavor1_name': self.flavor1_name,
439 'flavor2_name': self.flavor2_name,
440 'net_name': self.network_name,
441 'subnet_name': self.subnet_name,
442 'inst1_name': self.vm_inst1_name,
443 'inst2_name': self.vm_inst2_name,
444 'keypair_name': self.keypair_name,
445 'external_net_name': self.ext_net_name,
446 'security_group_name': self.sec_grp_name}
448 self.heat_tmplt_path = pkg_resources.resource_filename(
449 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
451 self.vm_inst_creators = list()
455 Cleans the stack and downloaded stack file
457 if self.stack_creator:
459 self.stack_creator.clean()
463 if self.image_creator:
465 self.image_creator.clean()
469 for vm_inst_creator in self.vm_inst_creators:
471 keypair_settings = vm_inst_creator.keypair_settings
472 if keypair_settings and keypair_settings.private_filepath:
473 expanded_path = os.path.expanduser(
474 keypair_settings.private_filepath)
475 os.chmod(expanded_path, 0o755)
476 os.remove(expanded_path)
480 super(self.__class__, self).__clean__()
482 def test_connect_via_ssh_heat_vm(self):
484 Tests the creation of an OpenStack stack from Heat template file and
485 the retrieval of two VM instance creators and attempt to connect via
486 SSH to the first one with a floating IP.
488 stack_settings = StackConfig(
489 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
490 template_path=self.heat_tmplt_path,
491 env_values=self.env_values)
492 self.stack_creator = OpenStackHeatStack(
493 self.os_creds, stack_settings,
494 [self.image_creator.image_settings])
495 created_stack = self.stack_creator.create()
496 self.assertIsNotNone(created_stack)
498 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
499 heat_keypair_option='private_key')
500 self.assertIsNotNone(self.vm_inst_creators)
501 self.assertEqual(2, len(self.vm_inst_creators))
503 for vm_inst_creator in self.vm_inst_creators:
504 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
506 create_instance_tests.validate_ssh_client(vm_inst_creator))
508 vm_settings = vm_inst_creator.instance_settings
509 self.assertEqual(0, len(vm_settings.floating_ip_settings))
512 class CreateStackNestedResourceTests(OSIntegrationTestCase):
514 Tests to ensure that nested heat templates work
518 self.user_roles = ['heat_stack_owner']
520 super(self.__class__, self).__start__()
522 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
524 self.heat_cli = heat_utils.heat_client(self.os_creds)
525 self.stack_creator = None
527 self.image_creator = OpenStackImage(
528 self.os_creds, openstack_tests.cirros_image_settings(
529 name=self.guid + '-image',
530 image_metadata=self.image_metadata))
531 self.image_creator.create()
533 self.flavor_creator = OpenStackFlavor(
536 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
537 self.flavor_creator.create()
540 'network_name': self.guid + '-network',
541 'public_network': self.ext_net_name,
542 'agent_image': self.image_creator.image_settings.name,
543 'agent_flavor': self.flavor_creator.flavor_settings.name,
544 'key_name': self.guid + '-key',
547 heat_tmplt_path = pkg_resources.resource_filename(
548 'snaps.openstack.tests.heat', 'agent-group.yaml')
549 heat_resource_path = pkg_resources.resource_filename(
550 'snaps.openstack.tests.heat', 'agent.yaml')
552 stack_settings = StackConfig(
553 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
554 template_path=heat_tmplt_path,
555 resource_files=[heat_resource_path],
556 env_values=env_values)
558 self.stack_creator = OpenStackHeatStack(
559 self.os_creds, stack_settings,
560 [self.image_creator.image_settings])
562 self.vm_inst_creators = list()
566 Cleans the stack and downloaded stack file
568 if self.stack_creator:
570 self.stack_creator.clean()
574 if self.image_creator:
576 self.image_creator.clean()
580 if self.flavor_creator:
582 self.flavor_creator.clean()
586 for vm_inst_creator in self.vm_inst_creators:
588 keypair_settings = vm_inst_creator.keypair_settings
589 if keypair_settings and keypair_settings.private_filepath:
590 expanded_path = os.path.expanduser(
591 keypair_settings.private_filepath)
592 os.chmod(expanded_path, 0o755)
593 os.remove(expanded_path)
597 super(self.__class__, self).__clean__()
599 def test_nested(self):
601 Tests the creation of an OpenStack stack from Heat template file and
602 the retrieval of two VM instance creators and attempt to connect via
603 SSH to the first one with a floating IP.
605 created_stack = self.stack_creator.create()
606 self.assertIsNotNone(created_stack)
608 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
609 heat_keypair_option='private_key')
610 self.assertIsNotNone(self.vm_inst_creators)
611 self.assertEqual(1, len(self.vm_inst_creators))
613 for vm_inst_creator in self.vm_inst_creators:
615 create_instance_tests.validate_ssh_client(vm_inst_creator))
618 class CreateStackRouterTests(OSIntegrationTestCase):
620 Tests for the CreateStack class defined in create_stack.py where the
621 target is a Network, Subnet, and Router
626 Instantiates the CreateStack object that is responsible for downloading
627 and creating an OS stack file within OpenStack
629 self.user_roles = ['heat_stack_owner']
631 super(self.__class__, self).__start__()
633 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
635 self.heat_cli = heat_utils.heat_client(self.os_creds)
636 self.neutron = neutron_utils.neutron_client(self.os_creds)
637 self.stack_creator = None
639 self.net_name = self.guid + '-net'
640 self.subnet_name = self.guid + '-subnet'
641 self.router_name = self.guid + '-router'
644 'net_name': self.net_name,
645 'subnet_name': self.subnet_name,
646 'router_name': self.router_name,
647 'external_net_name': self.ext_net_name}
649 self.heat_tmplt_path = pkg_resources.resource_filename(
650 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
652 stack_settings = StackConfig(
653 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
654 template_path=self.heat_tmplt_path,
655 env_values=self.env_values)
656 self.stack_creator = OpenStackHeatStack(
657 self.os_creds, stack_settings)
658 self.created_stack = self.stack_creator.create()
659 self.assertIsNotNone(self.created_stack)
663 Cleans the stack and downloaded stack file
665 if self.stack_creator:
667 self.stack_creator.clean()
671 super(self.__class__, self).__clean__()
673 def test_retrieve_router_creator(self):
675 Tests the creation of an OpenStack stack from Heat template file and
676 the retrieval of an OpenStackRouter creator/state machine instance
678 router_creators = self.stack_creator.get_router_creators()
679 self.assertEqual(1, len(router_creators))
681 creator = router_creators[0]
682 self.assertEqual(self.router_name, creator.router_settings.name)
684 router = creator.get_router()
686 ext_net = neutron_utils.get_network(
687 self.neutron, self.keystone, network_name=self.ext_net_name)
688 self.assertEqual(ext_net.id, router.external_network_id)
691 class CreateStackVolumeTests(OSIntegrationTestCase):
693 Tests to ensure that floating IPs can be accessed via an
694 OpenStackVolume object obtained from the OpenStackHeatStack instance
699 self.user_roles = ['heat_stack_owner', 'admin']
701 super(self.__class__, self).__start__()
703 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
705 self.heat_cli = heat_utils.heat_client(self.os_creds)
706 self.stack_creator = None
708 self.volume_name = self.guid + '-volume'
709 self.volume_type_name = self.guid + '-volume-type'
712 'volume_name': self.volume_name,
713 'volume_type_name': self.volume_type_name}
715 self.heat_tmplt_path = pkg_resources.resource_filename(
716 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
718 stack_settings = StackConfig(
719 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
720 template_path=self.heat_tmplt_path,
721 env_values=self.env_values)
722 self.stack_creator = OpenStackHeatStack(
723 self.os_creds, stack_settings)
724 self.created_stack = self.stack_creator.create()
725 self.assertIsNotNone(self.created_stack)
729 Cleans the stack and downloaded stack file
731 if self.stack_creator:
733 self.stack_creator.clean()
737 super(self.__class__, self).__clean__()
739 def test_retrieve_volume_creator(self):
741 Tests the creation of an OpenStack stack from Heat template file and
742 the retrieval of an OpenStackVolume creator/state machine instance
744 volume_creators = self.stack_creator.get_volume_creators()
745 self.assertEqual(1, len(volume_creators))
747 creator = volume_creators[0]
748 self.assertEqual(self.volume_name, creator.volume_settings.name)
749 self.assertEqual(self.volume_name, creator.get_volume().name)
750 self.assertEqual(self.volume_type_name,
751 creator.volume_settings.type_name)
752 self.assertEqual(self.volume_type_name, creator.get_volume().type)
753 self.assertEqual(1, creator.volume_settings.size)
754 self.assertEqual(1, creator.get_volume().size)
756 def test_retrieve_volume_type_creator(self):
758 Tests the creation of an OpenStack stack from Heat template file and
759 the retrieval of an OpenStackVolume creator/state machine instance
761 volume_type_creators = self.stack_creator.get_volume_type_creators()
762 self.assertEqual(1, len(volume_type_creators))
764 creator = volume_type_creators[0]
765 self.assertIsNotNone(creator)
767 volume_type = creator.get_volume_type()
768 self.assertIsNotNone(volume_type)
770 self.assertEqual(self.volume_type_name, volume_type.name)
771 self.assertTrue(volume_type.public)
772 self.assertIsNone(volume_type.qos_spec)
774 # TODO - Add encryption back and find out why it broke in Pike
775 # encryption = volume_type.encryption
776 # self.assertIsNotNone(encryption)
777 # self.assertIsNone(encryption.cipher)
778 # self.assertEqual('front-end', encryption.control_location)
779 # self.assertIsNone(encryption.key_size)
780 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
781 # encryption.provider)
782 # self.assertEqual(volume_type.id, encryption.volume_type_id)
785 class CreateStackFlavorTests(OSIntegrationTestCase):
787 Tests to ensure that floating IPs can be accessed via an
788 OpenStackFlavor object obtained from the OpenStackHeatStack instance
793 self.user_roles = ['heat_stack_owner', 'admin']
795 super(self.__class__, self).__start__()
797 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
799 self.heat_cli = heat_utils.heat_client(self.os_creds)
800 self.stack_creator = None
802 self.heat_tmplt_path = pkg_resources.resource_filename(
803 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
805 stack_settings = StackConfig(
806 name=self.guid + '-stack',
807 template_path=self.heat_tmplt_path)
808 self.stack_creator = OpenStackHeatStack(
809 self.os_creds, stack_settings)
810 self.created_stack = self.stack_creator.create()
811 self.assertIsNotNone(self.created_stack)
815 Cleans the stack and downloaded stack file
817 if self.stack_creator:
819 self.stack_creator.clean()
823 super(self.__class__, self).__clean__()
825 def test_retrieve_flavor_creator(self):
827 Tests the creation of an OpenStack stack from Heat template file and
828 the retrieval of an OpenStackVolume creator/state machine instance
830 flavor_creators = self.stack_creator.get_flavor_creators()
831 self.assertEqual(1, len(flavor_creators))
833 creator = flavor_creators[0]
834 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
835 self.assertEqual(1024, creator.get_flavor().ram)
836 self.assertEqual(200, creator.get_flavor().disk)
837 self.assertEqual(8, creator.get_flavor().vcpus)
838 self.assertEqual(0, creator.get_flavor().ephemeral)
839 self.assertIsNone(creator.get_flavor().swap)
840 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
841 self.assertTrue(creator.get_flavor().is_public)
844 class CreateStackKeypairTests(OSIntegrationTestCase):
846 Tests to ensure that floating IPs can be accessed via an
847 OpenStackKeypair object obtained from the OpenStackHeatStack instance
852 self.user_roles = ['heat_stack_owner']
854 super(self.__class__, self).__start__()
856 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
858 self.heat_cli = heat_utils.heat_client(self.os_creds)
859 self.nova = nova_utils.nova_client(self.os_creds)
860 self.stack_creator = None
862 self.keypair_name = self.guid + '-kp'
865 'keypair_name': self.keypair_name}
867 self.heat_tmplt_path = pkg_resources.resource_filename(
868 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
870 stack_settings = StackConfig(
871 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
872 template_path=self.heat_tmplt_path,
873 env_values=self.env_values)
874 self.stack_creator = OpenStackHeatStack(
875 self.os_creds, stack_settings)
876 self.created_stack = self.stack_creator.create()
877 self.assertIsNotNone(self.created_stack)
879 self.keypair_creators = list()
883 Cleans the stack and downloaded stack file
885 if self.stack_creator:
887 self.stack_creator.clean()
890 for keypair_creator in self.keypair_creators:
892 keypair_creator.clean()
896 super(self.__class__, self).__clean__()
898 def test_retrieve_keypair_creator(self):
900 Tests the creation of an OpenStack stack from Heat template file and
901 the retrieval of an OpenStackKeypair creator/state machine instance
903 self.kp_creators = self.stack_creator.get_keypair_creators(
905 self.assertEqual(1, len(self.kp_creators))
907 self.keypair_creator = self.kp_creators[0]
909 self.assertEqual(self.keypair_name,
910 self.keypair_creator.get_keypair().name)
911 self.assertIsNotNone(
912 self.keypair_creator.keypair_settings.private_filepath)
914 private_file_contents = file_utils.read_file(
915 self.keypair_creator.keypair_settings.private_filepath)
916 self.assertTrue(private_file_contents.startswith(
917 '-----BEGIN RSA PRIVATE KEY-----'))
919 keypair = nova_utils.get_keypair_by_id(
920 self.nova, self.keypair_creator.get_keypair().id)
921 self.assertIsNotNone(keypair)
922 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
925 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
927 Tests for the OpenStackHeatStack class to ensure it returns an
928 OpenStackSecurityGroup object
933 Instantiates the CreateStack object that is responsible for downloading
934 and creating an OS stack file within OpenStack
936 self.user_roles = ['heat_stack_owner']
938 super(self.__class__, self).__start__()
940 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
942 self.heat_cli = heat_utils.heat_client(self.os_creds)
943 self.nova = nova_utils.nova_client(self.os_creds)
944 self.stack_creator = None
946 self.security_group_name = self.guid + '-sec-grp'
949 'security_group_name': self.security_group_name}
951 self.heat_tmplt_path = pkg_resources.resource_filename(
952 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
954 stack_settings = StackConfig(
955 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
956 template_path=self.heat_tmplt_path,
957 env_values=self.env_values)
958 self.stack_creator = OpenStackHeatStack(
959 self.os_creds, stack_settings)
960 self.created_stack = self.stack_creator.create()
961 self.assertIsNotNone(self.created_stack)
965 Cleans the stack and downloaded stack file
967 if self.stack_creator:
969 self.stack_creator.clean()
973 super(self.__class__, self).__clean__()
975 def test_retrieve_security_group_creator(self):
977 Tests the creation of an OpenStack stack from Heat template file and
978 the retrieval of an OpenStackSecurityGroup creator/state machine
981 sec_grp_creators = self.stack_creator.get_security_group_creators()
982 self.assertEqual(1, len(sec_grp_creators))
984 creator = sec_grp_creators[0]
985 sec_grp = creator.get_security_group()
987 self.assertEqual(self.security_group_name, sec_grp.name)
988 self.assertEqual('Test description', sec_grp.description)
989 self.assertEqual(2, len(sec_grp.rules))
992 has_icmp_rule = False
994 for rule in sec_grp.rules:
995 if (rule.security_group_id == sec_grp.id
996 and rule.direction == 'egress'
997 and rule.ethertype == 'IPv4'
998 and rule.port_range_min == 22
999 and rule.port_range_max == 22
1000 and rule.protocol == 'tcp'
1001 and rule.remote_group_id is None
1002 and rule.remote_ip_prefix == '0.0.0.0/0'):
1004 if (rule.security_group_id == sec_grp.id
1005 and rule.direction == 'ingress'
1006 and rule.ethertype == 'IPv4'
1007 and rule.port_range_min is None
1008 and rule.port_range_max is None
1009 and rule.protocol == 'icmp'
1010 and rule.remote_group_id is None
1011 and rule.remote_ip_prefix == '0.0.0.0/0'):
1012 has_icmp_rule = True
1014 self.assertTrue(has_ssh_rule)
1015 self.assertTrue(has_icmp_rule)
1018 class CreateStackNegativeTests(OSIntegrationTestCase):
1020 Negative test cases for the OpenStackHeatStack class with poor
1025 self.user_roles = ['heat_stack_owner']
1027 super(self.__class__, self).__start__()
1029 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1030 self.stack_creator = None
1031 self.heat_tmplt_path = pkg_resources.resource_filename(
1032 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1035 if self.stack_creator:
1036 self.stack_creator.clean()
1037 super(self.__class__, self).__clean__()
1039 def test_missing_dependencies(self):
1041 Expect an StackCreationError when the stack file does not exist
1043 stack_settings = StackConfig(name=self.stack_name,
1044 template_path=self.heat_tmplt_path)
1045 self.stack_creator = OpenStackHeatStack(
1046 self.os_creds, stack_settings)
1047 with self.assertRaises(HTTPBadRequest):
1048 self.stack_creator.create()
1050 def test_bad_stack_file(self):
1052 Expect an StackCreationError when the stack file does not exist
1054 stack_settings = StackConfig(
1055 name=self.stack_name, template_path='foo')
1056 self.stack_creator = OpenStackHeatStack(
1057 self.os_creds, stack_settings)
1058 with self.assertRaises(IOError):
1059 self.stack_creator.create()
1062 class CreateStackFailureTests(OSIntegrationTestCase):
1064 Tests for the OpenStackHeatStack class defined in create_stack.py for
1065 when failures occur. Failures are being triggered by allocating 1 million
1070 self.user_roles = ['heat_stack_owner']
1072 super(self.__class__, self).__start__()
1074 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1076 self.heat_cli = heat_utils.heat_client(self.os_creds)
1077 self.stack_creator = None
1079 self.tmp_file = file_utils.save_string_to_file(
1080 ' ', str(uuid.uuid4()) + '-bad-image')
1081 self.image_creator = OpenStackImage(
1082 self.os_creds, ImageConfig(
1083 name=self.guid + 'image', image_file=self.tmp_file.name,
1084 image_user='foo', img_format='qcow2'))
1085 self.image_creator.create()
1088 self.flavor_creator = OpenStackFlavor(
1089 self.admin_os_creds,
1091 name=self.guid + '-flavor-name', ram=256, disk=10,
1093 self.flavor_creator.create()
1095 self.network_name = self.guid + '-net'
1096 self.subnet_name = self.guid + '-subnet'
1097 self.vm_inst_name = self.guid + '-inst'
1100 'image_name': self.image_creator.image_settings.name,
1101 'flavor_name': self.flavor_creator.flavor_settings.name,
1102 'net_name': self.network_name,
1103 'subnet_name': self.subnet_name,
1104 'inst_name': self.vm_inst_name}
1106 self.heat_tmplt_path = pkg_resources.resource_filename(
1107 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1111 Cleans the stack and downloaded stack file
1113 if self.stack_creator:
1115 self.stack_creator.clean()
1119 if self.image_creator:
1121 self.image_creator.clean()
1125 if self.flavor_creator:
1127 self.flavor_creator.clean()
1133 os.remove(self.tmp_file.name)
1137 super(self.__class__, self).__clean__()
1139 def test_stack_failure(self):
1141 Tests the creation of an OpenStack stack from Heat template file that
1142 should always fail due to too many CPU cores
1145 # Set the default stack settings, then set any custom parameters sent
1147 stack_settings = StackConfig(
1148 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1149 template_path=self.heat_tmplt_path,
1150 env_values=self.env_values)
1151 self.stack_creator = OpenStackHeatStack(
1152 self.os_creds, stack_settings)
1154 with self.assertRaises(StackError):
1156 self.stack_creator.create()
1158 resources = heat_utils.get_resources(
1159 self.heat_cli, self.stack_creator.get_stack().id)
1162 for resource in resources:
1163 if (resource.status ==
1164 snaps.config.stack.STATUS_CREATE_COMPLETE):
1166 self.assertTrue(found)