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
137 super(self.__class__, self).__start__()
139 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
141 self.heat_creds = self.admin_os_creds
142 self.heat_creds.project_name = self.admin_os_creds.project_name
144 self.heat_cli = heat_utils.heat_client(self.heat_creds)
145 self.stack_creator = None
147 self.image_creator = OpenStackImage(
148 self.heat_creds, openstack_tests.cirros_image_settings(
149 name=self.guid + '-image',
150 image_metadata=self.image_metadata))
151 self.image_creator.create()
154 self.flavor_creator = OpenStackFlavor(
157 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
158 self.flavor_creator.create()
160 self.network_name = self.guid + '-net'
161 self.subnet_name = self.guid + '-subnet'
162 self.vm_inst_name = self.guid + '-inst'
165 'image_name': self.image_creator.image_settings.name,
166 'flavor_name': self.flavor_creator.flavor_settings.name,
167 'net_name': self.network_name,
168 'subnet_name': self.subnet_name,
169 'inst_name': self.vm_inst_name}
171 self.heat_tmplt_path = pkg_resources.resource_filename(
172 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
176 Cleans the stack and downloaded stack file
178 if self.stack_creator:
180 self.stack_creator.clean()
184 if self.image_creator:
186 self.image_creator.clean()
190 if self.flavor_creator:
192 self.flavor_creator.clean()
196 super(self.__class__, self).__clean__()
198 def test_create_stack_template_file(self):
200 Tests the creation of an OpenStack stack from Heat template file.
203 # Set the default stack settings, then set any custom parameters sent
205 stack_settings = StackConfig(
206 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
207 template_path=self.heat_tmplt_path,
208 env_values=self.env_values)
209 self.stack_creator = OpenStackHeatStack(
210 self.heat_creds, stack_settings)
211 created_stack = self.stack_creator.create()
212 self.assertIsNotNone(created_stack)
214 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
216 self.assertIsNotNone(retrieved_stack)
217 self.assertEqual(created_stack.name, retrieved_stack.name)
218 self.assertEqual(created_stack.id, retrieved_stack.id)
219 self.assertEqual(0, len(self.stack_creator.get_outputs()))
221 def test_create_stack_short_timeout(self):
223 Tests the creation of an OpenStack stack from Heat template file.
226 # Set the default stack settings, then set any custom parameters sent
228 stack_settings = StackConfig(
229 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
230 template_path=self.heat_tmplt_path,
231 env_values=self.env_values, stack_create_timeout=0)
233 self.stack_creator = OpenStackHeatStack(
234 self.heat_creds, stack_settings)
235 with self.assertRaises(StackCreationError):
236 self.stack_creator.create()
238 def test_create_stack_template_dict(self):
240 Tests the creation of an OpenStack stack from a heat dict() object.
243 # Set the default stack settings, then set any custom parameters sent
245 template_dict = heat_utils.parse_heat_template_str(
246 file_utils.read_file(self.heat_tmplt_path))
247 stack_settings = StackConfig(
248 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
249 template=template_dict,
250 env_values=self.env_values)
251 self.stack_creator = OpenStackHeatStack(
252 self.heat_creds, stack_settings)
253 created_stack = self.stack_creator.create()
254 self.assertIsNotNone(created_stack)
256 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
258 self.assertIsNotNone(retrieved_stack)
259 self.assertEqual(created_stack.name, retrieved_stack.name)
260 self.assertEqual(created_stack.id, retrieved_stack.id)
261 self.assertEqual(0, len(self.stack_creator.get_outputs()))
263 def test_create_delete_stack(self):
265 Tests the creation then deletion of an OpenStack stack to ensure
266 clean() does not raise an Exception.
269 template_dict = heat_utils.parse_heat_template_str(
270 file_utils.read_file(self.heat_tmplt_path))
271 stack_settings = StackConfig(
272 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
273 template=template_dict,
274 env_values=self.env_values)
275 self.stack_creator = OpenStackHeatStack(
276 self.heat_creds, stack_settings)
277 created_stack = self.stack_creator.create()
278 self.assertIsNotNone(created_stack)
280 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
282 self.assertIsNotNone(retrieved_stack)
283 self.assertEqual(created_stack.name, retrieved_stack.name)
284 self.assertEqual(created_stack.id, retrieved_stack.id)
285 self.assertEqual(0, len(self.stack_creator.get_outputs()))
286 self.assertEqual(snaps.config.stack.STATUS_CREATE_COMPLETE,
287 self.stack_creator.get_status())
289 # Delete Stack manually
290 heat_utils.delete_stack(self.heat_cli, created_stack)
292 end_time = time.time() + 90
294 while time.time() < end_time:
295 status = heat_utils.get_stack_status(self.heat_cli,
297 if status == snaps.config.stack.STATUS_DELETE_COMPLETE:
301 self.assertTrue(deleted)
303 # Must not throw an exception when attempting to cleanup non-existent
305 self.stack_creator.clean()
306 self.assertIsNone(self.stack_creator.get_stack())
308 def test_create_same_stack(self):
310 Tests the creation of an OpenStack stack when the stack already exists.
313 template_dict = heat_utils.parse_heat_template_str(
314 file_utils.read_file(self.heat_tmplt_path))
315 stack_settings = StackConfig(
316 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
317 template=template_dict,
318 env_values=self.env_values)
319 self.stack_creator = OpenStackHeatStack(
320 self.heat_creds, stack_settings)
321 created_stack1 = self.stack_creator.create()
323 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
325 self.assertIsNotNone(retrieved_stack)
326 self.assertEqual(created_stack1.name, retrieved_stack.name)
327 self.assertEqual(created_stack1.id, retrieved_stack.id)
328 self.assertEqual(0, len(self.stack_creator.get_outputs()))
330 # Should be retrieving the instance data
331 stack_creator2 = OpenStackHeatStack(self.heat_creds, stack_settings)
332 stack2 = stack_creator2.create()
333 self.assertEqual(created_stack1.id, stack2.id)
335 def test_retrieve_network_creators(self):
337 Tests the creation of an OpenStack stack from Heat template file and
338 the retrieval of the network creator.
340 stack_settings = StackConfig(
341 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
342 template_path=self.heat_tmplt_path,
343 env_values=self.env_values)
344 self.stack_creator = OpenStackHeatStack(
345 self.heat_creds, stack_settings)
346 created_stack = self.stack_creator.create()
347 self.assertIsNotNone(created_stack)
349 net_creators = self.stack_creator.get_network_creators()
350 self.assertIsNotNone(net_creators)
351 self.assertEqual(1, len(net_creators))
352 self.assertEqual(self.network_name, net_creators[0].get_network().name)
354 # Need to use 'admin' creds as heat creates objects under it's own
356 neutron = neutron_utils.neutron_client(self.admin_os_creds)
357 keystone = keystone_utils.keystone_client(self.admin_os_creds)
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.heat_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.admin_os_creds)
395 neutron = neutron_utils.neutron_client(self.admin_os_creds)
396 keystone = keystone_utils.keystone_client(self.admin_os_creds)
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
414 super(self.__class__, self).__start__()
416 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
418 self.heat_creds = self.admin_os_creds
419 self.heat_creds.project_name = self.admin_os_creds.project_name
421 self.heat_cli = heat_utils.heat_client(self.heat_creds)
422 self.stack_creator = None
424 self.image_creator = OpenStackImage(
425 self.heat_creds, openstack_tests.cirros_image_settings(
426 name=self.guid + '-image',
427 image_metadata=self.image_metadata))
428 self.image_creator.create()
430 self.network_name = self.guid + '-net'
431 self.subnet_name = self.guid + '-subnet'
432 self.flavor1_name = self.guid + '-flavor1'
433 self.flavor2_name = self.guid + '-flavor2'
434 self.sec_grp_name = self.guid + '-sec_grp'
435 self.vm_inst1_name = self.guid + '-inst1'
436 self.vm_inst2_name = self.guid + '-inst2'
437 self.keypair_name = self.guid + '-kp'
440 'image1_name': self.image_creator.image_settings.name,
441 'image2_name': self.image_creator.image_settings.name,
442 'flavor1_name': self.flavor1_name,
443 'flavor2_name': self.flavor2_name,
444 'net_name': self.network_name,
445 'subnet_name': self.subnet_name,
446 'inst1_name': self.vm_inst1_name,
447 'inst2_name': self.vm_inst2_name,
448 'keypair_name': self.keypair_name,
449 'external_net_name': self.ext_net_name,
450 'security_group_name': self.sec_grp_name}
452 self.heat_tmplt_path = pkg_resources.resource_filename(
453 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
455 self.vm_inst_creators = list()
459 Cleans the stack and downloaded stack file
461 if self.stack_creator:
463 self.stack_creator.clean()
467 if self.image_creator:
469 self.image_creator.clean()
473 for vm_inst_creator in self.vm_inst_creators:
475 keypair_settings = vm_inst_creator.keypair_settings
476 if keypair_settings and keypair_settings.private_filepath:
477 expanded_path = os.path.expanduser(
478 keypair_settings.private_filepath)
479 os.chmod(expanded_path, 0o755)
480 os.remove(expanded_path)
484 super(self.__class__, self).__clean__()
486 def test_connect_via_ssh_heat_vm(self):
488 Tests the creation of an OpenStack stack from Heat template file and
489 the retrieval of two VM instance creators and attempt to connect via
490 SSH to the first one with a floating IP.
492 stack_settings = StackConfig(
493 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
494 template_path=self.heat_tmplt_path,
495 env_values=self.env_values)
496 self.stack_creator = OpenStackHeatStack(
497 self.heat_creds, stack_settings,
498 [self.image_creator.image_settings])
499 created_stack = self.stack_creator.create()
500 self.assertIsNotNone(created_stack)
502 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
503 heat_keypair_option='private_key')
504 self.assertIsNotNone(self.vm_inst_creators)
505 self.assertEqual(2, len(self.vm_inst_creators))
507 for vm_inst_creator in self.vm_inst_creators:
508 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
510 create_instance_tests.validate_ssh_client(vm_inst_creator))
512 vm_settings = vm_inst_creator.instance_settings
513 self.assertEqual(0, len(vm_settings.floating_ip_settings))
516 class CreateStackNestedResourceTests(OSIntegrationTestCase):
518 Tests to ensure that nested heat templates work
523 super(self.__class__, self).__start__()
525 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
527 self.heat_creds = self.admin_os_creds
528 self.heat_creds.project_name = self.admin_os_creds.project_name
530 self.heat_cli = heat_utils.heat_client(self.heat_creds)
531 self.stack_creator = None
533 self.image_creator = OpenStackImage(
534 self.heat_creds, openstack_tests.cirros_image_settings(
535 name=self.guid + '-image',
536 image_metadata=self.image_metadata))
537 self.image_creator.create()
539 self.flavor_creator = OpenStackFlavor(
542 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
543 self.flavor_creator.create()
546 'network_name': self.guid + '-network',
547 'public_network': self.ext_net_name,
548 'agent_image': self.image_creator.image_settings.name,
549 'agent_flavor': self.flavor_creator.flavor_settings.name,
550 'key_name': self.guid + '-key',
553 heat_tmplt_path = pkg_resources.resource_filename(
554 'snaps.openstack.tests.heat', 'agent-group.yaml')
555 heat_resource_path = pkg_resources.resource_filename(
556 'snaps.openstack.tests.heat', 'agent.yaml')
558 stack_settings = StackConfig(
559 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
560 template_path=heat_tmplt_path,
561 resource_files=[heat_resource_path],
562 env_values=env_values)
564 self.stack_creator = OpenStackHeatStack(
565 self.heat_creds, stack_settings,
566 [self.image_creator.image_settings])
568 self.vm_inst_creators = list()
572 Cleans the stack and downloaded stack file
574 if self.stack_creator:
576 self.stack_creator.clean()
580 if self.image_creator:
582 self.image_creator.clean()
586 if self.flavor_creator:
588 self.flavor_creator.clean()
592 for vm_inst_creator in self.vm_inst_creators:
594 keypair_settings = vm_inst_creator.keypair_settings
595 if keypair_settings and keypair_settings.private_filepath:
596 expanded_path = os.path.expanduser(
597 keypair_settings.private_filepath)
598 os.chmod(expanded_path, 0o755)
599 os.remove(expanded_path)
603 super(self.__class__, self).__clean__()
605 def test_nested(self):
607 Tests the creation of an OpenStack stack from Heat template file and
608 the retrieval of two VM instance creators and attempt to connect via
609 SSH to the first one with a floating IP.
611 created_stack = self.stack_creator.create()
612 self.assertIsNotNone(created_stack)
614 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
615 heat_keypair_option='private_key')
616 self.assertIsNotNone(self.vm_inst_creators)
617 self.assertEqual(1, len(self.vm_inst_creators))
619 for vm_inst_creator in self.vm_inst_creators:
621 create_instance_tests.validate_ssh_client(vm_inst_creator))
624 class CreateStackRouterTests(OSIntegrationTestCase):
626 Tests for the CreateStack class defined in create_stack.py where the
627 target is a Network, Subnet, and Router
632 Instantiates the CreateStack object that is responsible for downloading
633 and creating an OS stack file within OpenStack
635 super(self.__class__, self).__start__()
637 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
639 self.heat_creds = self.admin_os_creds
640 self.heat_creds.project_name = self.admin_os_creds.project_name
642 self.heat_cli = heat_utils.heat_client(self.heat_creds)
643 self.neutron = neutron_utils.neutron_client(self.os_creds)
644 self.stack_creator = None
646 self.net_name = self.guid + '-net'
647 self.subnet_name = self.guid + '-subnet'
648 self.router_name = self.guid + '-router'
651 'net_name': self.net_name,
652 'subnet_name': self.subnet_name,
653 'router_name': self.router_name,
654 'external_net_name': self.ext_net_name}
656 self.heat_tmplt_path = pkg_resources.resource_filename(
657 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
659 stack_settings = StackConfig(
660 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
661 template_path=self.heat_tmplt_path,
662 env_values=self.env_values)
663 self.stack_creator = OpenStackHeatStack(
664 self.heat_creds, stack_settings)
665 self.created_stack = self.stack_creator.create()
666 self.assertIsNotNone(self.created_stack)
670 Cleans the stack and downloaded stack file
672 if self.stack_creator:
674 self.stack_creator.clean()
678 super(self.__class__, self).__clean__()
680 def test_retrieve_router_creator(self):
682 Tests the creation of an OpenStack stack from Heat template file and
683 the retrieval of an OpenStackRouter creator/state machine instance
685 router_creators = self.stack_creator.get_router_creators()
686 self.assertEqual(1, len(router_creators))
688 creator = router_creators[0]
689 self.assertEqual(self.router_name, creator.router_settings.name)
691 router = creator.get_router()
693 ext_net = neutron_utils.get_network(
694 self.neutron, self.keystone, network_name=self.ext_net_name)
695 self.assertEqual(ext_net.id, router.external_network_id)
698 class CreateStackVolumeTests(OSIntegrationTestCase):
700 Tests to ensure that floating IPs can be accessed via an
701 OpenStackVolume object obtained from the OpenStackHeatStack instance
706 super(self.__class__, self).__start__()
708 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
710 self.heat_creds = self.admin_os_creds
711 self.heat_creds.project_name = self.admin_os_creds.project_name
713 self.heat_cli = heat_utils.heat_client(self.heat_creds)
714 self.stack_creator = None
716 self.volume_name = self.guid + '-volume'
717 self.volume_type_name = self.guid + '-volume-type'
720 'volume_name': self.volume_name,
721 'volume_type_name': self.volume_type_name}
723 self.heat_tmplt_path = pkg_resources.resource_filename(
724 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
726 stack_settings = StackConfig(
727 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
728 template_path=self.heat_tmplt_path,
729 env_values=self.env_values)
730 self.stack_creator = OpenStackHeatStack(
731 self.heat_creds, stack_settings)
732 self.created_stack = self.stack_creator.create()
733 self.assertIsNotNone(self.created_stack)
737 Cleans the stack and downloaded stack file
739 if self.stack_creator:
741 self.stack_creator.clean()
745 super(self.__class__, self).__clean__()
747 def test_retrieve_volume_creator(self):
749 Tests the creation of an OpenStack stack from Heat template file and
750 the retrieval of an OpenStackVolume creator/state machine instance
752 volume_creators = self.stack_creator.get_volume_creators()
753 self.assertEqual(1, len(volume_creators))
755 creator = volume_creators[0]
756 self.assertEqual(self.volume_name, creator.volume_settings.name)
757 self.assertEqual(self.volume_name, creator.get_volume().name)
758 self.assertEqual(self.volume_type_name,
759 creator.volume_settings.type_name)
760 self.assertEqual(self.volume_type_name, creator.get_volume().type)
761 self.assertEqual(1, creator.volume_settings.size)
762 self.assertEqual(1, creator.get_volume().size)
764 def test_retrieve_volume_type_creator(self):
766 Tests the creation of an OpenStack stack from Heat template file and
767 the retrieval of an OpenStackVolume creator/state machine instance
769 volume_type_creators = self.stack_creator.get_volume_type_creators()
770 self.assertEqual(1, len(volume_type_creators))
772 creator = volume_type_creators[0]
773 self.assertIsNotNone(creator)
775 volume_type = creator.get_volume_type()
776 self.assertIsNotNone(volume_type)
778 self.assertEqual(self.volume_type_name, volume_type.name)
779 self.assertTrue(volume_type.public)
780 self.assertIsNone(volume_type.qos_spec)
782 # TODO - Add encryption back and find out why it broke in Pike
783 # encryption = volume_type.encryption
784 # self.assertIsNotNone(encryption)
785 # self.assertIsNone(encryption.cipher)
786 # self.assertEqual('front-end', encryption.control_location)
787 # self.assertIsNone(encryption.key_size)
788 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
789 # encryption.provider)
790 # self.assertEqual(volume_type.id, encryption.volume_type_id)
793 class CreateStackFlavorTests(OSIntegrationTestCase):
795 Tests to ensure that floating IPs can be accessed via an
796 OpenStackFlavor object obtained from the OpenStackHeatStack instance
801 super(self.__class__, self).__start__()
803 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
805 self.heat_creds = self.admin_os_creds
806 self.heat_creds.project_name = self.admin_os_creds.project_name
808 self.heat_cli = heat_utils.heat_client(self.heat_creds)
809 self.stack_creator = None
811 self.heat_tmplt_path = pkg_resources.resource_filename(
812 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
814 stack_settings = StackConfig(
815 name=self.guid + '-stack',
816 template_path=self.heat_tmplt_path)
817 self.stack_creator = OpenStackHeatStack(
818 self.heat_creds, stack_settings)
819 self.created_stack = self.stack_creator.create()
820 self.assertIsNotNone(self.created_stack)
824 Cleans the stack and downloaded stack file
826 if self.stack_creator:
828 self.stack_creator.clean()
832 super(self.__class__, self).__clean__()
834 def test_retrieve_flavor_creator(self):
836 Tests the creation of an OpenStack stack from Heat template file and
837 the retrieval of an OpenStackVolume creator/state machine instance
839 flavor_creators = self.stack_creator.get_flavor_creators()
840 self.assertEqual(1, len(flavor_creators))
842 creator = flavor_creators[0]
843 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
844 self.assertEqual(1024, creator.get_flavor().ram)
845 self.assertEqual(200, creator.get_flavor().disk)
846 self.assertEqual(8, creator.get_flavor().vcpus)
847 self.assertEqual(0, creator.get_flavor().ephemeral)
848 self.assertIsNone(creator.get_flavor().swap)
849 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
850 self.assertTrue(creator.get_flavor().is_public)
853 class CreateStackKeypairTests(OSIntegrationTestCase):
855 Tests to ensure that floating IPs can be accessed via an
856 OpenStackKeypair object obtained from the OpenStackHeatStack instance
861 super(self.__class__, self).__start__()
863 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
865 self.heat_creds = self.admin_os_creds
866 self.heat_creds.project_name = self.admin_os_creds.project_name
868 self.heat_cli = heat_utils.heat_client(self.heat_creds)
869 self.nova = nova_utils.nova_client(self.heat_creds)
870 self.stack_creator = None
872 self.keypair_name = self.guid + '-kp'
875 'keypair_name': self.keypair_name}
877 self.heat_tmplt_path = pkg_resources.resource_filename(
878 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
880 stack_settings = StackConfig(
881 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
882 template_path=self.heat_tmplt_path,
883 env_values=self.env_values)
884 self.stack_creator = OpenStackHeatStack(
885 self.heat_creds, stack_settings)
886 self.created_stack = self.stack_creator.create()
887 self.assertIsNotNone(self.created_stack)
889 self.keypair_creators = list()
893 Cleans the stack and downloaded stack file
895 if self.stack_creator:
897 self.stack_creator.clean()
900 for keypair_creator in self.keypair_creators:
902 keypair_creator.clean()
906 super(self.__class__, self).__clean__()
908 def test_retrieve_keypair_creator(self):
910 Tests the creation of an OpenStack stack from Heat template file and
911 the retrieval of an OpenStackKeypair creator/state machine instance
913 self.kp_creators = self.stack_creator.get_keypair_creators(
915 self.assertEqual(1, len(self.kp_creators))
917 self.keypair_creator = self.kp_creators[0]
919 self.assertEqual(self.keypair_name,
920 self.keypair_creator.get_keypair().name)
921 self.assertIsNotNone(
922 self.keypair_creator.keypair_settings.private_filepath)
924 private_file_contents = file_utils.read_file(
925 self.keypair_creator.keypair_settings.private_filepath)
926 self.assertTrue(private_file_contents.startswith(
927 '-----BEGIN RSA PRIVATE KEY-----'))
929 keypair = nova_utils.get_keypair_by_id(
930 self.nova, self.keypair_creator.get_keypair().id)
931 self.assertIsNotNone(keypair)
932 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
935 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
937 Tests for the OpenStackHeatStack class to ensure it returns an
938 OpenStackSecurityGroup object
943 Instantiates the CreateStack object that is responsible for downloading
944 and creating an OS stack file within OpenStack
946 super(self.__class__, self).__start__()
948 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
950 self.heat_creds = self.admin_os_creds
951 self.heat_creds.project_name = self.admin_os_creds.project_name
953 self.heat_cli = heat_utils.heat_client(self.heat_creds)
954 self.nova = nova_utils.nova_client(self.heat_creds)
955 self.stack_creator = None
957 self.security_group_name = self.guid + '-sec-grp'
960 'security_group_name': self.security_group_name}
962 self.heat_tmplt_path = pkg_resources.resource_filename(
963 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
965 stack_settings = StackConfig(
966 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
967 template_path=self.heat_tmplt_path,
968 env_values=self.env_values)
969 self.stack_creator = OpenStackHeatStack(
970 self.heat_creds, stack_settings)
971 self.created_stack = self.stack_creator.create()
972 self.assertIsNotNone(self.created_stack)
976 Cleans the stack and downloaded stack file
978 if self.stack_creator:
980 self.stack_creator.clean()
984 super(self.__class__, self).__clean__()
986 def test_retrieve_security_group_creator(self):
988 Tests the creation of an OpenStack stack from Heat template file and
989 the retrieval of an OpenStackSecurityGroup creator/state machine
992 sec_grp_creators = self.stack_creator.get_security_group_creators()
993 self.assertEqual(1, len(sec_grp_creators))
995 creator = sec_grp_creators[0]
996 sec_grp = creator.get_security_group()
998 self.assertEqual(self.security_group_name, sec_grp.name)
999 self.assertEqual('Test description', sec_grp.description)
1000 self.assertEqual(2, len(sec_grp.rules))
1002 has_ssh_rule = False
1003 has_icmp_rule = False
1005 for rule in sec_grp.rules:
1006 if (rule.security_group_id == sec_grp.id
1007 and rule.direction == 'egress'
1008 and rule.ethertype == 'IPv4'
1009 and rule.port_range_min == 22
1010 and rule.port_range_max == 22
1011 and rule.protocol == 'tcp'
1012 and rule.remote_group_id is None
1013 and rule.remote_ip_prefix == '0.0.0.0/0'):
1015 if (rule.security_group_id == sec_grp.id
1016 and rule.direction == 'ingress'
1017 and rule.ethertype == 'IPv4'
1018 and rule.port_range_min is None
1019 and rule.port_range_max is None
1020 and rule.protocol == 'icmp'
1021 and rule.remote_group_id is None
1022 and rule.remote_ip_prefix == '0.0.0.0/0'):
1023 has_icmp_rule = True
1025 self.assertTrue(has_ssh_rule)
1026 self.assertTrue(has_icmp_rule)
1029 class CreateStackNegativeTests(OSIntegrationTestCase):
1031 Negative test cases for the OpenStackHeatStack class with poor
1037 super(self.__class__, self).__start__()
1039 self.heat_creds = self.admin_os_creds
1040 self.heat_creds.project_name = self.admin_os_creds.project_name
1042 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1043 self.stack_creator = None
1044 self.heat_tmplt_path = pkg_resources.resource_filename(
1045 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1048 if self.stack_creator:
1049 self.stack_creator.clean()
1050 super(self.__class__, self).__clean__()
1052 def test_missing_dependencies(self):
1054 Expect an StackCreationError when the stack file does not exist
1056 stack_settings = StackConfig(name=self.stack_name,
1057 template_path=self.heat_tmplt_path)
1058 self.stack_creator = OpenStackHeatStack(
1059 self.heat_creds, stack_settings)
1060 with self.assertRaises(HTTPBadRequest):
1061 self.stack_creator.create()
1063 def test_bad_stack_file(self):
1065 Expect an StackCreationError when the stack file does not exist
1067 stack_settings = StackConfig(
1068 name=self.stack_name, template_path='foo')
1069 self.stack_creator = OpenStackHeatStack(
1070 self.heat_creds, stack_settings)
1071 with self.assertRaises(IOError):
1072 self.stack_creator.create()
1075 class CreateStackFailureTests(OSIntegrationTestCase):
1077 Tests for the OpenStackHeatStack class defined in create_stack.py for
1078 when failures occur. Failures are being triggered by allocating 1 million
1084 super(self.__class__, self).__start__()
1086 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1088 self.heat_creds = self.admin_os_creds
1089 self.heat_creds.project_name = self.admin_os_creds.project_name
1091 self.heat_cli = heat_utils.heat_client(self.heat_creds)
1092 self.stack_creator = None
1094 self.tmp_file = file_utils.save_string_to_file(
1095 ' ', str(uuid.uuid4()) + '-bad-image')
1096 self.image_creator = OpenStackImage(
1097 self.heat_creds, ImageConfig(
1098 name=self.guid + 'image', image_file=self.tmp_file.name,
1099 image_user='foo', img_format='qcow2'))
1100 self.image_creator.create()
1103 self.flavor_creator = OpenStackFlavor(
1104 self.admin_os_creds,
1106 name=self.guid + '-flavor-name', ram=256, disk=10,
1108 self.flavor_creator.create()
1110 self.network_name = self.guid + '-net'
1111 self.subnet_name = self.guid + '-subnet'
1112 self.vm_inst_name = self.guid + '-inst'
1115 'image_name': self.image_creator.image_settings.name,
1116 'flavor_name': self.flavor_creator.flavor_settings.name,
1117 'net_name': self.network_name,
1118 'subnet_name': self.subnet_name,
1119 'inst_name': self.vm_inst_name}
1121 self.heat_tmplt_path = pkg_resources.resource_filename(
1122 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1126 Cleans the stack and downloaded stack file
1128 if self.stack_creator:
1130 self.stack_creator.clean()
1134 if self.image_creator:
1136 self.image_creator.clean()
1140 if self.flavor_creator:
1142 self.flavor_creator.clean()
1148 os.remove(self.tmp_file.name)
1152 super(self.__class__, self).__clean__()
1154 def test_stack_failure(self):
1156 Tests the creation of an OpenStack stack from Heat template file that
1157 should always fail due to too many CPU cores
1160 # Set the default stack settings, then set any custom parameters sent
1162 stack_settings = StackConfig(
1163 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1164 template_path=self.heat_tmplt_path,
1165 env_values=self.env_values)
1166 self.stack_creator = OpenStackHeatStack(
1167 self.heat_creds, stack_settings)
1169 with self.assertRaises(StackError):
1171 self.stack_creator.create()
1173 resources = heat_utils.get_resources(
1174 self.heat_cli, self.stack_creator.get_stack().id)
1177 for resource in resources:
1178 if (resource.status ==
1179 snaps.config.stack.STATUS_CREATE_COMPLETE):
1181 self.assertTrue(found)