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, self.os_session)
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(
355 self.os_creds, self.os_session)
356 keystone = keystone_utils.keystone_client(
357 self.os_creds, self.os_session)
358 net_by_name = neutron_utils.get_network(
359 neutron, keystone, network_name=net_creators[0].get_network().name)
360 self.assertEqual(net_creators[0].get_network(), net_by_name)
361 self.assertIsNotNone(neutron_utils.get_network_by_id(
362 neutron, net_creators[0].get_network().id))
364 self.assertEqual(1, len(net_creators[0].get_network().subnets))
365 subnet = net_creators[0].get_network().subnets[0]
366 subnet_by_name = neutron_utils.get_subnet(
367 neutron, subnet_name=subnet.name)
368 self.assertEqual(subnet, subnet_by_name)
370 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
371 self.assertIsNotNone(subnet_by_id)
372 self.assertEqual(subnet_by_name, subnet_by_id)
374 def test_retrieve_vm_inst_creators(self):
376 Tests the creation of an OpenStack stack from Heat template file and
377 the retrieval of the network creator.
379 stack_settings = StackConfig(
380 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
381 template_path=self.heat_tmplt_path,
382 env_values=self.env_values)
383 self.stack_creator = OpenStackHeatStack(
384 self.os_creds, stack_settings)
385 created_stack = self.stack_creator.create()
386 self.assertIsNotNone(created_stack)
388 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
389 self.assertIsNotNone(vm_inst_creators)
390 self.assertEqual(1, len(vm_inst_creators))
391 self.assertEqual(self.vm_inst_name,
392 vm_inst_creators[0].get_vm_inst().name)
394 nova = nova_utils.nova_client(self.os_creds, self.os_session)
395 neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
396 keystone = keystone_utils.keystone_client(self.os_creds, self.os_session)
397 vm_inst_by_name = nova_utils.get_server(
398 nova, neutron, keystone,
399 server_name=vm_inst_creators[0].get_vm_inst().name)
401 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
402 self.assertIsNotNone(nova_utils.get_server_object_by_id(
403 nova, neutron, keystone, vm_inst_creators[0].get_vm_inst().id))
406 class CreateStackFloatingIpTests(OSIntegrationTestCase):
408 Tests to ensure that floating IPs can be accessed via an
409 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
413 self.user_roles = ['heat_stack_owner', 'admin']
415 super(self.__class__, self).__start__()
417 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
419 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
420 self.stack_creator = None
422 self.image_creator = OpenStackImage(
423 self.os_creds, openstack_tests.cirros_image_settings(
424 name=self.guid + '-image',
425 image_metadata=self.image_metadata))
426 self.image_creator.create()
428 self.network_name = self.guid + '-net'
429 self.subnet_name = self.guid + '-subnet'
430 self.flavor1_name = self.guid + '-flavor1'
431 self.flavor2_name = self.guid + '-flavor2'
432 self.sec_grp_name = self.guid + '-sec_grp'
433 self.vm_inst1_name = self.guid + '-inst1'
434 self.vm_inst2_name = self.guid + '-inst2'
435 self.keypair_name = self.guid + '-kp'
438 'image1_name': self.image_creator.image_settings.name,
439 'image2_name': self.image_creator.image_settings.name,
440 'flavor1_name': self.flavor1_name,
441 'flavor2_name': self.flavor2_name,
442 'net_name': self.network_name,
443 'subnet_name': self.subnet_name,
444 'inst1_name': self.vm_inst1_name,
445 'inst2_name': self.vm_inst2_name,
446 'keypair_name': self.keypair_name,
447 'external_net_name': self.ext_net_name,
448 'security_group_name': self.sec_grp_name}
450 self.heat_tmplt_path = pkg_resources.resource_filename(
451 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
453 self.vm_inst_creators = list()
457 Cleans the stack and downloaded stack file
459 if self.stack_creator:
461 self.stack_creator.clean()
465 if self.image_creator:
467 self.image_creator.clean()
471 for vm_inst_creator in self.vm_inst_creators:
473 keypair_settings = vm_inst_creator.keypair_settings
474 if keypair_settings and keypair_settings.private_filepath:
475 expanded_path = os.path.expanduser(
476 keypair_settings.private_filepath)
477 os.chmod(expanded_path, 0o755)
478 os.remove(expanded_path)
482 super(self.__class__, self).__clean__()
484 def test_connect_via_ssh_heat_vm(self):
486 Tests the creation of an OpenStack stack from Heat template file and
487 the retrieval of two VM instance creators and attempt to connect via
488 SSH to the first one with a floating IP.
490 stack_settings = StackConfig(
491 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
492 template_path=self.heat_tmplt_path,
493 env_values=self.env_values)
494 self.stack_creator = OpenStackHeatStack(
495 self.os_creds, stack_settings,
496 [self.image_creator.image_settings])
497 created_stack = self.stack_creator.create()
498 self.assertIsNotNone(created_stack)
500 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
501 heat_keypair_option='private_key')
502 self.assertIsNotNone(self.vm_inst_creators)
503 self.assertEqual(2, len(self.vm_inst_creators))
505 for vm_inst_creator in self.vm_inst_creators:
506 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
508 create_instance_tests.validate_ssh_client(vm_inst_creator))
510 vm_settings = vm_inst_creator.instance_settings
511 self.assertEqual(0, len(vm_settings.floating_ip_settings))
514 class CreateStackNestedResourceTests(OSIntegrationTestCase):
516 Tests to ensure that nested heat templates work
520 self.user_roles = ['heat_stack_owner']
522 super(self.__class__, self).__start__()
524 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
526 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
527 self.stack_creator = None
529 self.image_creator = OpenStackImage(
530 self.os_creds, openstack_tests.cirros_image_settings(
531 name=self.guid + '-image',
532 image_metadata=self.image_metadata))
533 self.image_creator.create()
535 self.flavor_creator = OpenStackFlavor(
538 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
539 self.flavor_creator.create()
542 'network_name': self.guid + '-network',
543 'public_network': self.ext_net_name,
544 'agent_image': self.image_creator.image_settings.name,
545 'agent_flavor': self.flavor_creator.flavor_settings.name,
546 'key_name': self.guid + '-key',
549 heat_tmplt_path = pkg_resources.resource_filename(
550 'snaps.openstack.tests.heat', 'agent-group.yaml')
551 heat_resource_path = pkg_resources.resource_filename(
552 'snaps.openstack.tests.heat', 'agent.yaml')
554 stack_settings = StackConfig(
555 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
556 template_path=heat_tmplt_path,
557 resource_files=[heat_resource_path],
558 env_values=env_values)
560 self.stack_creator = OpenStackHeatStack(
561 self.os_creds, stack_settings,
562 [self.image_creator.image_settings])
564 self.vm_inst_creators = list()
568 Cleans the stack and downloaded stack file
570 if self.stack_creator:
572 self.stack_creator.clean()
576 if self.image_creator:
578 self.image_creator.clean()
582 if self.flavor_creator:
584 self.flavor_creator.clean()
588 for vm_inst_creator in self.vm_inst_creators:
590 keypair_settings = vm_inst_creator.keypair_settings
591 if keypair_settings and keypair_settings.private_filepath:
592 expanded_path = os.path.expanduser(
593 keypair_settings.private_filepath)
594 os.chmod(expanded_path, 0o755)
595 os.remove(expanded_path)
599 super(self.__class__, self).__clean__()
601 def test_nested(self):
603 Tests the creation of an OpenStack stack from Heat template file and
604 the retrieval of two VM instance creators and attempt to connect via
605 SSH to the first one with a floating IP.
607 created_stack = self.stack_creator.create()
608 self.assertIsNotNone(created_stack)
610 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
611 heat_keypair_option='private_key')
612 self.assertIsNotNone(self.vm_inst_creators)
613 self.assertEqual(1, len(self.vm_inst_creators))
615 for vm_inst_creator in self.vm_inst_creators:
617 create_instance_tests.validate_ssh_client(vm_inst_creator))
620 class CreateStackRouterTests(OSIntegrationTestCase):
622 Tests for the CreateStack class defined in create_stack.py where the
623 target is a Network, Subnet, and Router
628 Instantiates the CreateStack object that is responsible for downloading
629 and creating an OS stack file within OpenStack
631 self.user_roles = ['heat_stack_owner']
633 super(self.__class__, self).__start__()
635 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
637 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
638 self.neutron = neutron_utils.neutron_client(
639 self.os_creds, self.os_session)
640 self.stack_creator = None
642 self.net_name = self.guid + '-net'
643 self.subnet_name = self.guid + '-subnet'
644 self.router_name = self.guid + '-router'
647 'net_name': self.net_name,
648 'subnet_name': self.subnet_name,
649 'router_name': self.router_name,
650 'external_net_name': self.ext_net_name}
652 self.heat_tmplt_path = pkg_resources.resource_filename(
653 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
655 stack_settings = StackConfig(
656 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
657 template_path=self.heat_tmplt_path,
658 env_values=self.env_values)
659 self.stack_creator = OpenStackHeatStack(
660 self.os_creds, stack_settings)
661 self.created_stack = self.stack_creator.create()
662 self.assertIsNotNone(self.created_stack)
666 Cleans the stack and downloaded stack file
668 if self.stack_creator:
670 self.stack_creator.clean()
674 super(self.__class__, self).__clean__()
676 def test_retrieve_router_creator(self):
678 Tests the creation of an OpenStack stack from Heat template file and
679 the retrieval of an OpenStackRouter creator/state machine instance
681 router_creators = self.stack_creator.get_router_creators()
682 self.assertEqual(1, len(router_creators))
684 creator = router_creators[0]
685 self.assertEqual(self.router_name, creator.router_settings.name)
687 router = creator.get_router()
689 ext_net = neutron_utils.get_network(
690 self.neutron, self.keystone, network_name=self.ext_net_name)
691 self.assertEqual(ext_net.id, router.external_network_id)
694 class CreateStackVolumeTests(OSIntegrationTestCase):
696 Tests to ensure that floating IPs can be accessed via an
697 OpenStackVolume object obtained from the OpenStackHeatStack instance
702 self.user_roles = ['heat_stack_owner', 'admin']
704 super(self.__class__, self).__start__()
706 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
708 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
709 self.stack_creator = None
711 self.volume_name = self.guid + '-volume'
712 self.volume_type_name = self.guid + '-volume-type'
715 'volume_name': self.volume_name,
716 'volume_type_name': self.volume_type_name}
718 self.heat_tmplt_path = pkg_resources.resource_filename(
719 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
721 stack_settings = StackConfig(
722 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
723 template_path=self.heat_tmplt_path,
724 env_values=self.env_values)
725 self.stack_creator = OpenStackHeatStack(
726 self.os_creds, stack_settings)
727 self.created_stack = self.stack_creator.create()
728 self.assertIsNotNone(self.created_stack)
732 Cleans the stack and downloaded stack file
734 if self.stack_creator:
736 self.stack_creator.clean()
740 super(self.__class__, self).__clean__()
742 def test_retrieve_volume_creator(self):
744 Tests the creation of an OpenStack stack from Heat template file and
745 the retrieval of an OpenStackVolume creator/state machine instance
747 volume_creators = self.stack_creator.get_volume_creators()
748 self.assertEqual(1, len(volume_creators))
750 creator = volume_creators[0]
751 self.assertEqual(self.volume_name, creator.volume_settings.name)
752 self.assertEqual(self.volume_name, creator.get_volume().name)
753 self.assertEqual(self.volume_type_name,
754 creator.volume_settings.type_name)
755 self.assertEqual(self.volume_type_name, creator.get_volume().type)
756 self.assertEqual(1, creator.volume_settings.size)
757 self.assertEqual(1, creator.get_volume().size)
759 def test_retrieve_volume_type_creator(self):
761 Tests the creation of an OpenStack stack from Heat template file and
762 the retrieval of an OpenStackVolume creator/state machine instance
764 volume_type_creators = self.stack_creator.get_volume_type_creators()
765 self.assertEqual(1, len(volume_type_creators))
767 creator = volume_type_creators[0]
768 self.assertIsNotNone(creator)
770 volume_type = creator.get_volume_type()
771 self.assertIsNotNone(volume_type)
773 self.assertEqual(self.volume_type_name, volume_type.name)
774 self.assertTrue(volume_type.public)
775 self.assertIsNone(volume_type.qos_spec)
777 # TODO - Add encryption back and find out why it broke in Pike
778 # encryption = volume_type.encryption
779 # self.assertIsNotNone(encryption)
780 # self.assertIsNone(encryption.cipher)
781 # self.assertEqual('front-end', encryption.control_location)
782 # self.assertIsNone(encryption.key_size)
783 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
784 # encryption.provider)
785 # self.assertEqual(volume_type.id, encryption.volume_type_id)
788 class CreateStackFlavorTests(OSIntegrationTestCase):
790 Tests to ensure that floating IPs can be accessed via an
791 OpenStackFlavor object obtained from the OpenStackHeatStack instance
796 self.user_roles = ['heat_stack_owner', 'admin']
798 super(self.__class__, self).__start__()
800 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
802 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
803 self.stack_creator = None
805 self.heat_tmplt_path = pkg_resources.resource_filename(
806 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
808 stack_settings = StackConfig(
809 name=self.guid + '-stack',
810 template_path=self.heat_tmplt_path)
811 self.stack_creator = OpenStackHeatStack(
812 self.os_creds, stack_settings)
813 self.created_stack = self.stack_creator.create()
814 self.assertIsNotNone(self.created_stack)
818 Cleans the stack and downloaded stack file
820 if self.stack_creator:
822 self.stack_creator.clean()
826 super(self.__class__, self).__clean__()
828 def test_retrieve_flavor_creator(self):
830 Tests the creation of an OpenStack stack from Heat template file and
831 the retrieval of an OpenStackVolume creator/state machine instance
833 flavor_creators = self.stack_creator.get_flavor_creators()
834 self.assertEqual(1, len(flavor_creators))
836 creator = flavor_creators[0]
837 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
838 self.assertEqual(1024, creator.get_flavor().ram)
839 self.assertEqual(200, creator.get_flavor().disk)
840 self.assertEqual(8, creator.get_flavor().vcpus)
841 self.assertEqual(0, creator.get_flavor().ephemeral)
842 self.assertIsNone(creator.get_flavor().swap)
843 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
844 self.assertTrue(creator.get_flavor().is_public)
847 class CreateStackKeypairTests(OSIntegrationTestCase):
849 Tests to ensure that floating IPs can be accessed via an
850 OpenStackKeypair object obtained from the OpenStackHeatStack instance
855 self.user_roles = ['heat_stack_owner']
857 super(self.__class__, self).__start__()
859 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
861 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
862 self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
863 self.stack_creator = None
865 self.keypair_name = self.guid + '-kp'
868 'keypair_name': self.keypair_name}
870 self.heat_tmplt_path = pkg_resources.resource_filename(
871 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
873 stack_settings = StackConfig(
874 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
875 template_path=self.heat_tmplt_path,
876 env_values=self.env_values)
877 self.stack_creator = OpenStackHeatStack(
878 self.os_creds, stack_settings)
879 self.created_stack = self.stack_creator.create()
880 self.assertIsNotNone(self.created_stack)
882 self.keypair_creators = list()
886 Cleans the stack and downloaded stack file
888 if self.stack_creator:
890 self.stack_creator.clean()
893 for keypair_creator in self.keypair_creators:
895 keypair_creator.clean()
899 super(self.__class__, self).__clean__()
901 def test_retrieve_keypair_creator(self):
903 Tests the creation of an OpenStack stack from Heat template file and
904 the retrieval of an OpenStackKeypair creator/state machine instance
906 self.kp_creators = self.stack_creator.get_keypair_creators(
908 self.assertEqual(1, len(self.kp_creators))
910 self.keypair_creator = self.kp_creators[0]
912 self.assertEqual(self.keypair_name,
913 self.keypair_creator.get_keypair().name)
914 self.assertIsNotNone(
915 self.keypair_creator.keypair_settings.private_filepath)
917 private_file_contents = file_utils.read_file(
918 self.keypair_creator.keypair_settings.private_filepath)
919 self.assertTrue(private_file_contents.startswith(
920 '-----BEGIN RSA PRIVATE KEY-----'))
922 keypair = nova_utils.get_keypair_by_id(
923 self.nova, self.keypair_creator.get_keypair().id)
924 self.assertIsNotNone(keypair)
925 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
928 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
930 Tests for the OpenStackHeatStack class to ensure it returns an
931 OpenStackSecurityGroup object
936 Instantiates the CreateStack object that is responsible for downloading
937 and creating an OS stack file within OpenStack
939 self.user_roles = ['heat_stack_owner']
941 super(self.__class__, self).__start__()
943 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
945 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
946 self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
947 self.stack_creator = None
949 self.security_group_name = self.guid + '-sec-grp'
952 'security_group_name': self.security_group_name}
954 self.heat_tmplt_path = pkg_resources.resource_filename(
955 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
957 stack_settings = StackConfig(
958 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
959 template_path=self.heat_tmplt_path,
960 env_values=self.env_values)
961 self.stack_creator = OpenStackHeatStack(
962 self.os_creds, stack_settings)
963 self.created_stack = self.stack_creator.create()
964 self.assertIsNotNone(self.created_stack)
968 Cleans the stack and downloaded stack file
970 if self.stack_creator:
972 self.stack_creator.clean()
976 super(self.__class__, self).__clean__()
978 def test_retrieve_security_group_creator(self):
980 Tests the creation of an OpenStack stack from Heat template file and
981 the retrieval of an OpenStackSecurityGroup creator/state machine
984 sec_grp_creators = self.stack_creator.get_security_group_creators()
985 self.assertEqual(1, len(sec_grp_creators))
987 creator = sec_grp_creators[0]
988 sec_grp = creator.get_security_group()
990 self.assertEqual(self.security_group_name, sec_grp.name)
991 self.assertEqual('Test description', sec_grp.description)
992 self.assertEqual(2, len(sec_grp.rules))
995 has_icmp_rule = False
997 for rule in sec_grp.rules:
998 if (rule.security_group_id == sec_grp.id
999 and rule.direction == 'egress'
1000 and rule.ethertype == 'IPv4'
1001 and rule.port_range_min == 22
1002 and rule.port_range_max == 22
1003 and rule.protocol == 'tcp'
1004 and rule.remote_group_id is None
1005 and rule.remote_ip_prefix == '0.0.0.0/0'):
1007 if (rule.security_group_id == sec_grp.id
1008 and rule.direction == 'ingress'
1009 and rule.ethertype == 'IPv4'
1010 and rule.port_range_min is None
1011 and rule.port_range_max is None
1012 and rule.protocol == 'icmp'
1013 and rule.remote_group_id is None
1014 and rule.remote_ip_prefix == '0.0.0.0/0'):
1015 has_icmp_rule = True
1017 self.assertTrue(has_ssh_rule)
1018 self.assertTrue(has_icmp_rule)
1021 class CreateStackNegativeTests(OSIntegrationTestCase):
1023 Negative test cases for the OpenStackHeatStack class with poor
1028 self.user_roles = ['heat_stack_owner']
1030 super(self.__class__, self).__start__()
1032 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1033 self.stack_creator = None
1034 self.heat_tmplt_path = pkg_resources.resource_filename(
1035 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1038 if self.stack_creator:
1039 self.stack_creator.clean()
1041 super(self.__class__, self).__clean__()
1043 def test_missing_dependencies(self):
1045 Expect an StackCreationError when the stack file does not exist
1047 stack_settings = StackConfig(name=self.stack_name,
1048 template_path=self.heat_tmplt_path)
1049 self.stack_creator = OpenStackHeatStack(
1050 self.os_creds, stack_settings)
1051 with self.assertRaises(HTTPBadRequest):
1052 self.stack_creator.create()
1054 def test_bad_stack_file(self):
1056 Expect an StackCreationError when the stack file does not exist
1058 stack_settings = StackConfig(
1059 name=self.stack_name, template_path='foo')
1060 self.stack_creator = OpenStackHeatStack(
1061 self.os_creds, stack_settings)
1062 with self.assertRaises(IOError):
1063 self.stack_creator.create()
1066 class CreateStackFailureTests(OSIntegrationTestCase):
1068 Tests for the OpenStackHeatStack class defined in create_stack.py for
1069 when failures occur. Failures are being triggered by allocating 1 million
1074 self.user_roles = ['heat_stack_owner']
1076 super(self.__class__, self).__start__()
1078 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1080 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
1081 self.stack_creator = None
1083 self.tmp_file = file_utils.save_string_to_file(
1084 ' ', str(uuid.uuid4()) + '-bad-image')
1085 self.image_creator = OpenStackImage(
1086 self.os_creds, ImageConfig(
1087 name=self.guid + 'image', image_file=self.tmp_file.name,
1088 image_user='foo', img_format='qcow2'))
1089 self.image_creator.create()
1092 self.flavor_creator = OpenStackFlavor(
1093 self.admin_os_creds,
1095 name=self.guid + '-flavor-name', ram=256, disk=10,
1097 self.flavor_creator.create()
1099 self.network_name = self.guid + '-net'
1100 self.subnet_name = self.guid + '-subnet'
1101 self.vm_inst_name = self.guid + '-inst'
1104 'image_name': self.image_creator.image_settings.name,
1105 'flavor_name': self.flavor_creator.flavor_settings.name,
1106 'net_name': self.network_name,
1107 'subnet_name': self.subnet_name,
1108 'inst_name': self.vm_inst_name}
1110 self.heat_tmplt_path = pkg_resources.resource_filename(
1111 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1115 Cleans the stack and downloaded stack file
1117 if self.stack_creator:
1119 self.stack_creator.clean()
1123 if self.image_creator:
1125 self.image_creator.clean()
1129 if self.flavor_creator:
1131 self.flavor_creator.clean()
1137 os.remove(self.tmp_file.name)
1141 super(self.__class__, self).__clean__()
1143 def test_stack_failure(self):
1145 Tests the creation of an OpenStack stack from Heat template file that
1146 should always fail due to too many CPU cores
1149 # Set the default stack settings, then set any custom parameters sent
1151 stack_settings = StackConfig(
1152 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1153 template_path=self.heat_tmplt_path,
1154 env_values=self.env_values)
1155 self.stack_creator = OpenStackHeatStack(
1156 self.os_creds, stack_settings)
1158 with self.assertRaises(StackError):
1160 self.stack_creator.create()
1162 resources = heat_utils.get_resources(
1163 self.heat_cli, self.stack_creator.get_stack().id)
1166 for resource in resources:
1167 if (resource.status ==
1168 snaps.config.stack.STATUS_CREATE_COMPLETE):
1170 self.assertTrue(found)