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 (heat_utils, neutron_utils, nova_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 neutron = neutron_utils.neutron_client(self.os_creds)
355 admin_proj_id = keystone_utils.get_project(
356 self.keystone, self.admin_os_creds.project_name)
357 net_by_name = neutron_utils.get_network(
358 neutron, network_name=net_creators[0].get_network().name,
359 project_id=admin_proj_id)
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 vm_inst_by_name = nova_utils.get_server(
397 nova, neutron, server_name=vm_inst_creators[0].get_vm_inst().name)
398 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
399 self.assertIsNotNone(nova_utils.get_server_object_by_id(
400 nova, neutron, vm_inst_creators[0].get_vm_inst().id,
401 vm_inst_creators[0].project_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
412 super(self.__class__, self).__start__()
414 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
416 self.heat_creds = self.admin_os_creds
417 self.heat_creds.project_name = self.admin_os_creds.project_name
419 self.heat_cli = heat_utils.heat_client(self.heat_creds)
420 self.stack_creator = None
422 self.image_creator = OpenStackImage(
423 self.heat_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.heat_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
521 super(self.__class__, self).__start__()
523 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
525 self.heat_creds = self.admin_os_creds
526 self.heat_creds.project_name = self.admin_os_creds.project_name
528 self.heat_cli = heat_utils.heat_client(self.heat_creds)
529 self.stack_creator = None
531 self.image_creator = OpenStackImage(
532 self.heat_creds, openstack_tests.cirros_image_settings(
533 name=self.guid + '-image',
534 image_metadata=self.image_metadata))
535 self.image_creator.create()
537 self.flavor_creator = OpenStackFlavor(
540 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
541 self.flavor_creator.create()
544 'network_name': self.guid + '-network',
545 'public_network': self.ext_net_name,
546 'agent_image': self.image_creator.image_settings.name,
547 'agent_flavor': self.flavor_creator.flavor_settings.name,
548 'key_name': self.guid + '-key',
551 heat_tmplt_path = pkg_resources.resource_filename(
552 'snaps.openstack.tests.heat', 'agent-group.yaml')
553 heat_resource_path = pkg_resources.resource_filename(
554 'snaps.openstack.tests.heat', 'agent.yaml')
556 stack_settings = StackConfig(
557 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
558 template_path=heat_tmplt_path,
559 resource_files=[heat_resource_path],
560 env_values=env_values)
562 self.stack_creator = OpenStackHeatStack(
563 self.heat_creds, stack_settings,
564 [self.image_creator.image_settings])
566 self.vm_inst_creators = list()
570 Cleans the stack and downloaded stack file
572 if self.stack_creator:
574 self.stack_creator.clean()
578 if self.image_creator:
580 self.image_creator.clean()
584 if self.flavor_creator:
586 self.flavor_creator.clean()
590 for vm_inst_creator in self.vm_inst_creators:
592 keypair_settings = vm_inst_creator.keypair_settings
593 if keypair_settings and keypair_settings.private_filepath:
594 expanded_path = os.path.expanduser(
595 keypair_settings.private_filepath)
596 os.chmod(expanded_path, 0o755)
597 os.remove(expanded_path)
601 super(self.__class__, self).__clean__()
603 def test_nested(self):
605 Tests the creation of an OpenStack stack from Heat template file and
606 the retrieval of two VM instance creators and attempt to connect via
607 SSH to the first one with a floating IP.
609 created_stack = self.stack_creator.create()
610 self.assertIsNotNone(created_stack)
612 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
613 heat_keypair_option='private_key')
614 self.assertIsNotNone(self.vm_inst_creators)
615 self.assertEqual(1, len(self.vm_inst_creators))
617 for vm_inst_creator in self.vm_inst_creators:
619 create_instance_tests.validate_ssh_client(vm_inst_creator))
622 class CreateStackRouterTests(OSIntegrationTestCase):
624 Tests for the CreateStack class defined in create_stack.py where the
625 target is a Network, Subnet, and Router
630 Instantiates the CreateStack object that is responsible for downloading
631 and creating an OS stack file within OpenStack
633 super(self.__class__, self).__start__()
635 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
637 self.heat_creds = self.admin_os_creds
638 self.heat_creds.project_name = self.admin_os_creds.project_name
640 self.heat_cli = heat_utils.heat_client(self.heat_creds)
641 self.neutron = neutron_utils.neutron_client(self.os_creds)
642 self.stack_creator = None
644 self.net_name = self.guid + '-net'
645 self.subnet_name = self.guid + '-subnet'
646 self.router_name = self.guid + '-router'
649 'net_name': self.net_name,
650 'subnet_name': self.subnet_name,
651 'router_name': self.router_name,
652 'external_net_name': self.ext_net_name}
654 self.heat_tmplt_path = pkg_resources.resource_filename(
655 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
657 stack_settings = StackConfig(
658 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
659 template_path=self.heat_tmplt_path,
660 env_values=self.env_values)
661 self.stack_creator = OpenStackHeatStack(
662 self.heat_creds, stack_settings)
663 self.created_stack = self.stack_creator.create()
664 self.assertIsNotNone(self.created_stack)
668 Cleans the stack and downloaded stack file
670 if self.stack_creator:
672 self.stack_creator.clean()
676 super(self.__class__, self).__clean__()
678 def test_retrieve_router_creator(self):
680 Tests the creation of an OpenStack stack from Heat template file and
681 the retrieval of an OpenStackRouter creator/state machine instance
683 router_creators = self.stack_creator.get_router_creators()
684 self.assertEqual(1, len(router_creators))
686 creator = router_creators[0]
687 self.assertEqual(self.router_name, creator.router_settings.name)
689 router = creator.get_router()
691 ext_net = neutron_utils.get_network(
692 self.neutron, network_name=self.ext_net_name,
693 project_id=self.project_id)
694 self.assertEqual(ext_net.id, router.external_network_id)
697 class CreateStackVolumeTests(OSIntegrationTestCase):
699 Tests to ensure that floating IPs can be accessed via an
700 OpenStackVolume object obtained from the OpenStackHeatStack instance
705 super(self.__class__, self).__start__()
707 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
709 self.heat_creds = self.admin_os_creds
710 self.heat_creds.project_name = self.admin_os_creds.project_name
712 self.heat_cli = heat_utils.heat_client(self.heat_creds)
713 self.stack_creator = None
715 self.volume_name = self.guid + '-volume'
716 self.volume_type_name = self.guid + '-volume-type'
719 'volume_name': self.volume_name,
720 'volume_type_name': self.volume_type_name}
722 self.heat_tmplt_path = pkg_resources.resource_filename(
723 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
725 stack_settings = StackConfig(
726 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
727 template_path=self.heat_tmplt_path,
728 env_values=self.env_values)
729 self.stack_creator = OpenStackHeatStack(
730 self.heat_creds, stack_settings)
731 self.created_stack = self.stack_creator.create()
732 self.assertIsNotNone(self.created_stack)
736 Cleans the stack and downloaded stack file
738 if self.stack_creator:
740 self.stack_creator.clean()
744 super(self.__class__, self).__clean__()
746 def test_retrieve_volume_creator(self):
748 Tests the creation of an OpenStack stack from Heat template file and
749 the retrieval of an OpenStackVolume creator/state machine instance
751 volume_creators = self.stack_creator.get_volume_creators()
752 self.assertEqual(1, len(volume_creators))
754 creator = volume_creators[0]
755 self.assertEqual(self.volume_name, creator.volume_settings.name)
756 self.assertEqual(self.volume_name, creator.get_volume().name)
757 self.assertEqual(self.volume_type_name,
758 creator.volume_settings.type_name)
759 self.assertEqual(self.volume_type_name, creator.get_volume().type)
760 self.assertEqual(1, creator.volume_settings.size)
761 self.assertEqual(1, creator.get_volume().size)
763 def test_retrieve_volume_type_creator(self):
765 Tests the creation of an OpenStack stack from Heat template file and
766 the retrieval of an OpenStackVolume creator/state machine instance
768 volume_type_creators = self.stack_creator.get_volume_type_creators()
769 self.assertEqual(1, len(volume_type_creators))
771 creator = volume_type_creators[0]
772 self.assertIsNotNone(creator)
774 volume_type = creator.get_volume_type()
775 self.assertIsNotNone(volume_type)
777 self.assertEqual(self.volume_type_name, volume_type.name)
778 self.assertTrue(volume_type.public)
779 self.assertIsNone(volume_type.qos_spec)
781 # TODO - Add encryption back and find out why it broke in Pike
782 # encryption = volume_type.encryption
783 # self.assertIsNotNone(encryption)
784 # self.assertIsNone(encryption.cipher)
785 # self.assertEqual('front-end', encryption.control_location)
786 # self.assertIsNone(encryption.key_size)
787 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
788 # encryption.provider)
789 # self.assertEqual(volume_type.id, encryption.volume_type_id)
792 class CreateStackFlavorTests(OSIntegrationTestCase):
794 Tests to ensure that floating IPs can be accessed via an
795 OpenStackFlavor object obtained from the OpenStackHeatStack instance
800 super(self.__class__, self).__start__()
802 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
804 self.heat_creds = self.admin_os_creds
805 self.heat_creds.project_name = self.admin_os_creds.project_name
807 self.heat_cli = heat_utils.heat_client(self.heat_creds)
808 self.stack_creator = None
810 self.heat_tmplt_path = pkg_resources.resource_filename(
811 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
813 stack_settings = StackConfig(
814 name=self.guid + '-stack',
815 template_path=self.heat_tmplt_path)
816 self.stack_creator = OpenStackHeatStack(
817 self.heat_creds, stack_settings)
818 self.created_stack = self.stack_creator.create()
819 self.assertIsNotNone(self.created_stack)
823 Cleans the stack and downloaded stack file
825 if self.stack_creator:
827 self.stack_creator.clean()
831 super(self.__class__, self).__clean__()
833 def test_retrieve_flavor_creator(self):
835 Tests the creation of an OpenStack stack from Heat template file and
836 the retrieval of an OpenStackVolume creator/state machine instance
838 flavor_creators = self.stack_creator.get_flavor_creators()
839 self.assertEqual(1, len(flavor_creators))
841 creator = flavor_creators[0]
842 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
843 self.assertEqual(1024, creator.get_flavor().ram)
844 self.assertEqual(200, creator.get_flavor().disk)
845 self.assertEqual(8, creator.get_flavor().vcpus)
846 self.assertEqual(0, creator.get_flavor().ephemeral)
847 self.assertIsNone(creator.get_flavor().swap)
848 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
849 self.assertTrue(creator.get_flavor().is_public)
852 class CreateStackKeypairTests(OSIntegrationTestCase):
854 Tests to ensure that floating IPs can be accessed via an
855 OpenStackKeypair object obtained from the OpenStackHeatStack instance
860 super(self.__class__, self).__start__()
862 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
864 self.heat_creds = self.admin_os_creds
865 self.heat_creds.project_name = self.admin_os_creds.project_name
867 self.heat_cli = heat_utils.heat_client(self.heat_creds)
868 self.nova = nova_utils.nova_client(self.heat_creds)
869 self.stack_creator = None
871 self.keypair_name = self.guid + '-kp'
874 'keypair_name': self.keypair_name}
876 self.heat_tmplt_path = pkg_resources.resource_filename(
877 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
879 stack_settings = StackConfig(
880 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
881 template_path=self.heat_tmplt_path,
882 env_values=self.env_values)
883 self.stack_creator = OpenStackHeatStack(
884 self.heat_creds, stack_settings)
885 self.created_stack = self.stack_creator.create()
886 self.assertIsNotNone(self.created_stack)
888 self.keypair_creators = list()
892 Cleans the stack and downloaded stack file
894 if self.stack_creator:
896 self.stack_creator.clean()
899 for keypair_creator in self.keypair_creators:
901 keypair_creator.clean()
905 super(self.__class__, self).__clean__()
907 def test_retrieve_keypair_creator(self):
909 Tests the creation of an OpenStack stack from Heat template file and
910 the retrieval of an OpenStackKeypair creator/state machine instance
912 self.kp_creators = self.stack_creator.get_keypair_creators(
914 self.assertEqual(1, len(self.kp_creators))
916 self.keypair_creator = self.kp_creators[0]
918 self.assertEqual(self.keypair_name,
919 self.keypair_creator.get_keypair().name)
920 self.assertIsNotNone(
921 self.keypair_creator.keypair_settings.private_filepath)
923 private_file_contents = file_utils.read_file(
924 self.keypair_creator.keypair_settings.private_filepath)
925 self.assertTrue(private_file_contents.startswith(
926 '-----BEGIN RSA PRIVATE KEY-----'))
928 keypair = nova_utils.get_keypair_by_id(
929 self.nova, self.keypair_creator.get_keypair().id)
930 self.assertIsNotNone(keypair)
931 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
934 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
936 Tests for the OpenStackHeatStack class to ensure it returns an
937 OpenStackSecurityGroup object
942 Instantiates the CreateStack object that is responsible for downloading
943 and creating an OS stack file within OpenStack
945 super(self.__class__, self).__start__()
947 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
949 self.heat_creds = self.admin_os_creds
950 self.heat_creds.project_name = self.admin_os_creds.project_name
952 self.heat_cli = heat_utils.heat_client(self.heat_creds)
953 self.nova = nova_utils.nova_client(self.heat_creds)
954 self.stack_creator = None
956 self.security_group_name = self.guid + '-sec-grp'
959 'security_group_name': self.security_group_name}
961 self.heat_tmplt_path = pkg_resources.resource_filename(
962 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
964 stack_settings = StackConfig(
965 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
966 template_path=self.heat_tmplt_path,
967 env_values=self.env_values)
968 self.stack_creator = OpenStackHeatStack(
969 self.heat_creds, stack_settings)
970 self.created_stack = self.stack_creator.create()
971 self.assertIsNotNone(self.created_stack)
975 Cleans the stack and downloaded stack file
977 if self.stack_creator:
979 self.stack_creator.clean()
983 super(self.__class__, self).__clean__()
985 def test_retrieve_security_group_creator(self):
987 Tests the creation of an OpenStack stack from Heat template file and
988 the retrieval of an OpenStackSecurityGroup creator/state machine
991 sec_grp_creators = self.stack_creator.get_security_group_creators()
992 self.assertEqual(1, len(sec_grp_creators))
994 creator = sec_grp_creators[0]
995 sec_grp = creator.get_security_group()
997 self.assertEqual(self.security_group_name, sec_grp.name)
998 self.assertEqual('Test description', sec_grp.description)
999 self.assertEqual(2, len(sec_grp.rules))
1001 has_ssh_rule = False
1002 has_icmp_rule = False
1004 for rule in sec_grp.rules:
1005 if (rule.security_group_id == sec_grp.id
1006 and rule.direction == 'egress'
1007 and rule.ethertype == 'IPv4'
1008 and rule.port_range_min == 22
1009 and rule.port_range_max == 22
1010 and rule.protocol == 'tcp'
1011 and rule.remote_group_id is None
1012 and rule.remote_ip_prefix == '0.0.0.0/0'):
1014 if (rule.security_group_id == sec_grp.id
1015 and rule.direction == 'ingress'
1016 and rule.ethertype == 'IPv4'
1017 and rule.port_range_min is None
1018 and rule.port_range_max is None
1019 and rule.protocol == 'icmp'
1020 and rule.remote_group_id is None
1021 and rule.remote_ip_prefix == '0.0.0.0/0'):
1022 has_icmp_rule = True
1024 self.assertTrue(has_ssh_rule)
1025 self.assertTrue(has_icmp_rule)
1028 class CreateStackNegativeTests(OSIntegrationTestCase):
1030 Negative test cases for the OpenStackHeatStack class with poor
1036 super(self.__class__, self).__start__()
1038 self.heat_creds = self.admin_os_creds
1039 self.heat_creds.project_name = self.admin_os_creds.project_name
1041 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1042 self.stack_creator = None
1043 self.heat_tmplt_path = pkg_resources.resource_filename(
1044 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1047 if self.stack_creator:
1048 self.stack_creator.clean()
1049 super(self.__class__, self).__clean__()
1051 def test_missing_dependencies(self):
1053 Expect an StackCreationError when the stack file does not exist
1055 stack_settings = StackConfig(name=self.stack_name,
1056 template_path=self.heat_tmplt_path)
1057 self.stack_creator = OpenStackHeatStack(
1058 self.heat_creds, stack_settings)
1059 with self.assertRaises(HTTPBadRequest):
1060 self.stack_creator.create()
1062 def test_bad_stack_file(self):
1064 Expect an StackCreationError when the stack file does not exist
1066 stack_settings = StackConfig(
1067 name=self.stack_name, template_path='foo')
1068 self.stack_creator = OpenStackHeatStack(
1069 self.heat_creds, stack_settings)
1070 with self.assertRaises(IOError):
1071 self.stack_creator.create()
1074 class CreateStackFailureTests(OSIntegrationTestCase):
1076 Tests for the OpenStackHeatStack class defined in create_stack.py for
1077 when failures occur. Failures are being triggered by allocating 1 million
1083 super(self.__class__, self).__start__()
1085 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1087 self.heat_creds = self.admin_os_creds
1088 self.heat_creds.project_name = self.admin_os_creds.project_name
1090 self.heat_cli = heat_utils.heat_client(self.heat_creds)
1091 self.stack_creator = None
1093 self.tmp_file = file_utils.save_string_to_file(
1094 ' ', str(uuid.uuid4()) + '-bad-image')
1095 self.image_creator = OpenStackImage(
1096 self.heat_creds, ImageConfig(
1097 name=self.guid + 'image', image_file=self.tmp_file.name,
1098 image_user='foo', img_format='qcow2'))
1099 self.image_creator.create()
1102 self.flavor_creator = OpenStackFlavor(
1103 self.admin_os_creds,
1105 name=self.guid + '-flavor-name', ram=256, disk=10,
1107 self.flavor_creator.create()
1109 self.network_name = self.guid + '-net'
1110 self.subnet_name = self.guid + '-subnet'
1111 self.vm_inst_name = self.guid + '-inst'
1114 'image_name': self.image_creator.image_settings.name,
1115 'flavor_name': self.flavor_creator.flavor_settings.name,
1116 'net_name': self.network_name,
1117 'subnet_name': self.subnet_name,
1118 'inst_name': self.vm_inst_name}
1120 self.heat_tmplt_path = pkg_resources.resource_filename(
1121 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1125 Cleans the stack and downloaded stack file
1127 if self.stack_creator:
1129 self.stack_creator.clean()
1133 if self.image_creator:
1135 self.image_creator.clean()
1139 if self.flavor_creator:
1141 self.flavor_creator.clean()
1147 os.remove(self.tmp_file.name)
1151 super(self.__class__, self).__clean__()
1153 def test_stack_failure(self):
1155 Tests the creation of an OpenStack stack from Heat template file that
1156 should always fail due to too many CPU cores
1159 # Set the default stack settings, then set any custom parameters sent
1161 stack_settings = StackConfig(
1162 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1163 template_path=self.heat_tmplt_path,
1164 env_values=self.env_values)
1165 self.stack_creator = OpenStackHeatStack(
1166 self.heat_creds, stack_settings)
1168 with self.assertRaises(StackError):
1170 self.stack_creator.create()
1172 resources = heat_utils.get_resources(
1173 self.heat_cli, self.stack_creator.get_stack().id)
1176 for resource in resources:
1177 if (resource.status ==
1178 snaps.config.stack.STATUS_CREATE_COMPLETE):
1180 self.assertTrue(found)