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
44 __author__ = 'spisarski'
46 logger = logging.getLogger('create_stack_tests')
49 class StackSettingsUnitTests(unittest.TestCase):
51 Tests the construction of the StackSettings class
54 def test_no_params(self):
55 with self.assertRaises(StackConfigError):
58 def test_empty_config(self):
59 with self.assertRaises(StackConfigError):
60 StackSettings(**dict())
62 def test_name_only(self):
63 with self.assertRaises(StackConfigError):
64 StackSettings(name='foo')
66 def test_config_with_name_only(self):
67 with self.assertRaises(StackConfigError):
68 StackSettings(**{'name': 'foo'})
70 def test_config_minimum_template(self):
71 settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
72 self.assertEqual('stack', settings.name)
73 self.assertEqual('foo', settings.template)
74 self.assertIsNone(settings.template_path)
75 self.assertIsNone(settings.env_values)
76 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
77 settings.stack_create_timeout)
79 def test_config_minimum_template_path(self):
80 settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
81 self.assertEqual('stack', settings.name)
82 self.assertIsNone(settings.template)
83 self.assertEqual('foo', settings.template_path)
84 self.assertIsNone(settings.env_values)
85 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
86 settings.stack_create_timeout)
88 def test_minimum_template(self):
89 settings = StackSettings(name='stack', template='foo')
90 self.assertEqual('stack', settings.name)
91 self.assertEqual('foo', settings.template)
92 self.assertIsNone(settings.template_path)
93 self.assertIsNone(settings.env_values)
94 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
95 settings.stack_create_timeout)
97 def test_minimum_template_path(self):
98 settings = StackSettings(name='stack', template_path='foo')
99 self.assertEqual('stack', settings.name)
100 self.assertEqual('foo', settings.template_path)
101 self.assertIsNone(settings.template)
102 self.assertIsNone(settings.env_values)
103 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
104 settings.stack_create_timeout)
107 env_values = {'foo': 'bar'}
108 settings = StackSettings(name='stack', template='bar',
109 template_path='foo', env_values=env_values,
110 stack_create_timeout=999)
111 self.assertEqual('stack', settings.name)
112 self.assertEqual('bar', settings.template)
113 self.assertEqual('foo', settings.template_path)
114 self.assertEqual(env_values, settings.env_values)
115 self.assertEqual(999, settings.stack_create_timeout)
117 def test_config_all(self):
118 env_values = {'foo': 'bar'}
119 settings = StackSettings(
120 **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
121 'env_values': env_values, 'stack_create_timeout': 999})
122 self.assertEqual('stack', settings.name)
123 self.assertEqual('bar', settings.template)
124 self.assertEqual('foo', settings.template_path)
125 self.assertEqual(env_values, settings.env_values)
126 self.assertEqual(999, settings.stack_create_timeout)
129 class CreateStackSuccessTests(OSIntegrationTestCase):
131 Tests for the OpenStackHeatStack class defined in create_stack.py
136 super(self.__class__, self).__start__()
138 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
140 self.heat_creds = self.admin_os_creds
141 self.heat_creds.project_name = self.admin_os_creds.project_name
143 self.heat_cli = heat_utils.heat_client(self.heat_creds)
144 self.stack_creator = None
146 self.image_creator = OpenStackImage(
147 self.heat_creds, openstack_tests.cirros_image_settings(
148 name=self.guid + '-image',
149 image_metadata=self.image_metadata))
150 self.image_creator.create()
153 self.flavor_creator = OpenStackFlavor(
156 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
157 self.flavor_creator.create()
159 self.network_name = self.guid + '-net'
160 self.subnet_name = self.guid + '-subnet'
161 self.vm_inst_name = self.guid + '-inst'
164 'image_name': self.image_creator.image_settings.name,
165 'flavor_name': self.flavor_creator.flavor_settings.name,
166 'net_name': self.network_name,
167 'subnet_name': self.subnet_name,
168 'inst_name': self.vm_inst_name}
170 self.heat_tmplt_path = pkg_resources.resource_filename(
171 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
175 Cleans the stack and downloaded stack file
177 if self.stack_creator:
179 self.stack_creator.clean()
183 if self.image_creator:
185 self.image_creator.clean()
189 if self.flavor_creator:
191 self.flavor_creator.clean()
195 super(self.__class__, self).__clean__()
197 def test_create_stack_template_file(self):
199 Tests the creation of an OpenStack stack from Heat template file.
202 # Set the default stack settings, then set any custom parameters sent
204 stack_settings = StackConfig(
205 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
206 template_path=self.heat_tmplt_path,
207 env_values=self.env_values)
208 self.stack_creator = OpenStackHeatStack(
209 self.heat_creds, stack_settings)
210 created_stack = self.stack_creator.create()
211 self.assertIsNotNone(created_stack)
213 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
215 self.assertIsNotNone(retrieved_stack)
216 self.assertEqual(created_stack.name, retrieved_stack.name)
217 self.assertEqual(created_stack.id, retrieved_stack.id)
218 self.assertEqual(0, len(self.stack_creator.get_outputs()))
220 def test_create_stack_short_timeout(self):
222 Tests the creation of an OpenStack stack from Heat template file.
225 # Set the default stack settings, then set any custom parameters sent
227 stack_settings = StackConfig(
228 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
229 template_path=self.heat_tmplt_path,
230 env_values=self.env_values, stack_create_timeout=0)
232 self.stack_creator = OpenStackHeatStack(
233 self.heat_creds, stack_settings)
234 with self.assertRaises(StackCreationError):
235 self.stack_creator.create()
237 def test_create_stack_template_dict(self):
239 Tests the creation of an OpenStack stack from a heat dict() object.
242 # Set the default stack settings, then set any custom parameters sent
244 template_dict = heat_utils.parse_heat_template_str(
245 file_utils.read_file(self.heat_tmplt_path))
246 stack_settings = StackConfig(
247 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
248 template=template_dict,
249 env_values=self.env_values)
250 self.stack_creator = OpenStackHeatStack(
251 self.heat_creds, stack_settings)
252 created_stack = self.stack_creator.create()
253 self.assertIsNotNone(created_stack)
255 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
257 self.assertIsNotNone(retrieved_stack)
258 self.assertEqual(created_stack.name, retrieved_stack.name)
259 self.assertEqual(created_stack.id, retrieved_stack.id)
260 self.assertEqual(0, len(self.stack_creator.get_outputs()))
262 def test_create_delete_stack(self):
264 Tests the creation then deletion of an OpenStack stack to ensure
265 clean() does not raise an Exception.
268 template_dict = heat_utils.parse_heat_template_str(
269 file_utils.read_file(self.heat_tmplt_path))
270 stack_settings = StackConfig(
271 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
272 template=template_dict,
273 env_values=self.env_values)
274 self.stack_creator = OpenStackHeatStack(
275 self.heat_creds, stack_settings)
276 created_stack = self.stack_creator.create()
277 self.assertIsNotNone(created_stack)
279 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
281 self.assertIsNotNone(retrieved_stack)
282 self.assertEqual(created_stack.name, retrieved_stack.name)
283 self.assertEqual(created_stack.id, retrieved_stack.id)
284 self.assertEqual(0, len(self.stack_creator.get_outputs()))
285 self.assertEqual(snaps.config.stack.STATUS_CREATE_COMPLETE,
286 self.stack_creator.get_status())
288 # Delete Stack manually
289 heat_utils.delete_stack(self.heat_cli, created_stack)
291 end_time = time.time() + 90
293 while time.time() < end_time:
294 status = heat_utils.get_stack_status(self.heat_cli,
296 if status == snaps.config.stack.STATUS_DELETE_COMPLETE:
300 self.assertTrue(deleted)
302 # Must not throw an exception when attempting to cleanup non-existent
304 self.stack_creator.clean()
305 self.assertIsNone(self.stack_creator.get_stack())
307 def test_create_same_stack(self):
309 Tests the creation of an OpenStack stack when the stack already exists.
312 template_dict = heat_utils.parse_heat_template_str(
313 file_utils.read_file(self.heat_tmplt_path))
314 stack_settings = StackConfig(
315 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
316 template=template_dict,
317 env_values=self.env_values)
318 self.stack_creator = OpenStackHeatStack(
319 self.heat_creds, stack_settings)
320 created_stack1 = self.stack_creator.create()
322 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
324 self.assertIsNotNone(retrieved_stack)
325 self.assertEqual(created_stack1.name, retrieved_stack.name)
326 self.assertEqual(created_stack1.id, retrieved_stack.id)
327 self.assertEqual(0, len(self.stack_creator.get_outputs()))
329 # Should be retrieving the instance data
330 stack_creator2 = OpenStackHeatStack(self.heat_creds, stack_settings)
331 stack2 = stack_creator2.create()
332 self.assertEqual(created_stack1.id, stack2.id)
334 def test_retrieve_network_creators(self):
336 Tests the creation of an OpenStack stack from Heat template file and
337 the retrieval of the network creator.
339 stack_settings = StackConfig(
340 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
341 template_path=self.heat_tmplt_path,
342 env_values=self.env_values)
343 self.stack_creator = OpenStackHeatStack(
344 self.heat_creds, stack_settings)
345 created_stack = self.stack_creator.create()
346 self.assertIsNotNone(created_stack)
348 net_creators = self.stack_creator.get_network_creators()
349 self.assertIsNotNone(net_creators)
350 self.assertEqual(1, len(net_creators))
351 self.assertEqual(self.network_name, net_creators[0].get_network().name)
353 neutron = neutron_utils.neutron_client(self.os_creds)
354 net_by_name = neutron_utils.get_network(
355 neutron, network_name=net_creators[0].get_network().name)
356 self.assertEqual(net_creators[0].get_network(), net_by_name)
357 self.assertIsNotNone(neutron_utils.get_network_by_id(
358 neutron, net_creators[0].get_network().id))
360 self.assertEqual(1, len(net_creators[0].get_network().subnets))
361 subnet = net_creators[0].get_network().subnets[0]
362 subnet_by_name = neutron_utils.get_subnet(
363 neutron, subnet_name=subnet.name)
364 self.assertEqual(subnet, subnet_by_name)
366 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
367 self.assertIsNotNone(subnet_by_id)
368 self.assertEqual(subnet_by_name, subnet_by_id)
370 def test_retrieve_vm_inst_creators(self):
372 Tests the creation of an OpenStack stack from Heat template file and
373 the retrieval of the network creator.
375 stack_settings = StackConfig(
376 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
377 template_path=self.heat_tmplt_path,
378 env_values=self.env_values)
379 self.stack_creator = OpenStackHeatStack(
380 self.heat_creds, stack_settings)
381 created_stack = self.stack_creator.create()
382 self.assertIsNotNone(created_stack)
384 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
385 self.assertIsNotNone(vm_inst_creators)
386 self.assertEqual(1, len(vm_inst_creators))
387 self.assertEqual(self.vm_inst_name,
388 vm_inst_creators[0].get_vm_inst().name)
390 nova = nova_utils.nova_client(self.admin_os_creds)
391 neutron = neutron_utils.neutron_client(self.admin_os_creds)
392 vm_inst_by_name = nova_utils.get_server(
393 nova, neutron, server_name=vm_inst_creators[0].get_vm_inst().name)
394 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
395 self.assertIsNotNone(nova_utils.get_server_object_by_id(
396 nova, neutron, vm_inst_creators[0].get_vm_inst().id))
399 class CreateStackFloatingIpTests(OSIntegrationTestCase):
401 Tests to ensure that floating IPs can be accessed via an
402 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
407 super(self.__class__, self).__start__()
409 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
411 self.heat_creds = self.admin_os_creds
412 self.heat_creds.project_name = self.admin_os_creds.project_name
414 self.heat_cli = heat_utils.heat_client(self.heat_creds)
415 self.stack_creator = None
417 self.image_creator = OpenStackImage(
418 self.heat_creds, openstack_tests.cirros_image_settings(
419 name=self.guid + '-image',
420 image_metadata=self.image_metadata))
421 self.image_creator.create()
423 self.network_name = self.guid + '-net'
424 self.subnet_name = self.guid + '-subnet'
425 self.flavor1_name = self.guid + '-flavor1'
426 self.flavor2_name = self.guid + '-flavor2'
427 self.sec_grp_name = self.guid + '-sec_grp'
428 self.vm_inst1_name = self.guid + '-inst1'
429 self.vm_inst2_name = self.guid + '-inst2'
430 self.keypair_name = self.guid + '-kp'
433 'image1_name': self.image_creator.image_settings.name,
434 'image2_name': self.image_creator.image_settings.name,
435 'flavor1_name': self.flavor1_name,
436 'flavor2_name': self.flavor2_name,
437 'net_name': self.network_name,
438 'subnet_name': self.subnet_name,
439 'inst1_name': self.vm_inst1_name,
440 'inst2_name': self.vm_inst2_name,
441 'keypair_name': self.keypair_name,
442 'external_net_name': self.ext_net_name,
443 'security_group_name': self.sec_grp_name}
445 self.heat_tmplt_path = pkg_resources.resource_filename(
446 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
448 self.vm_inst_creators = list()
452 Cleans the stack and downloaded stack file
454 if self.stack_creator:
456 self.stack_creator.clean()
460 if self.image_creator:
462 self.image_creator.clean()
466 for vm_inst_creator in self.vm_inst_creators:
468 keypair_settings = vm_inst_creator.keypair_settings
469 if keypair_settings and keypair_settings.private_filepath:
470 expanded_path = os.path.expanduser(
471 keypair_settings.private_filepath)
472 os.chmod(expanded_path, 0o755)
473 os.remove(expanded_path)
477 super(self.__class__, self).__clean__()
479 def test_connect_via_ssh_heat_vm(self):
481 Tests the creation of an OpenStack stack from Heat template file and
482 the retrieval of two VM instance creators and attempt to connect via
483 SSH to the first one with a floating IP.
485 stack_settings = StackConfig(
486 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
487 template_path=self.heat_tmplt_path,
488 env_values=self.env_values)
489 self.stack_creator = OpenStackHeatStack(
490 self.heat_creds, stack_settings,
491 [self.image_creator.image_settings])
492 created_stack = self.stack_creator.create()
493 self.assertIsNotNone(created_stack)
495 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
496 heat_keypair_option='private_key')
497 self.assertIsNotNone(self.vm_inst_creators)
498 self.assertEqual(2, len(self.vm_inst_creators))
500 for vm_inst_creator in self.vm_inst_creators:
501 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
503 create_instance_tests.validate_ssh_client(vm_inst_creator))
505 vm_settings = vm_inst_creator.instance_settings
506 self.assertEqual(0, len(vm_settings.floating_ip_settings))
509 class CreateStackNestedResourceTests(OSIntegrationTestCase):
511 Tests to ensure that nested heat templates work
516 super(self.__class__, self).__start__()
518 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
520 self.heat_creds = self.admin_os_creds
521 self.heat_creds.project_name = self.admin_os_creds.project_name
523 self.heat_cli = heat_utils.heat_client(self.heat_creds)
524 self.stack_creator = None
526 self.image_creator = OpenStackImage(
527 self.heat_creds, openstack_tests.cirros_image_settings(
528 name=self.guid + '-image',
529 image_metadata=self.image_metadata))
530 self.image_creator.create()
532 self.flavor_creator = OpenStackFlavor(
535 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
536 self.flavor_creator.create()
539 'public_network': self.ext_net_name,
540 'agent_image': self.image_creator.image_settings.name,
541 'agent_flavor': self.flavor_creator.flavor_settings.name,
544 heat_tmplt_path = pkg_resources.resource_filename(
545 'snaps.openstack.tests.heat', 'agent-group.yaml')
546 heat_resource_path = pkg_resources.resource_filename(
547 'snaps.openstack.tests.heat', 'agent.yaml')
549 stack_settings = StackConfig(
550 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
551 template_path=heat_tmplt_path,
552 resource_files=[heat_resource_path],
553 env_values=env_values)
555 self.stack_creator = OpenStackHeatStack(
556 self.heat_creds, stack_settings,
557 [self.image_creator.image_settings])
559 self.vm_inst_creators = list()
563 Cleans the stack and downloaded stack file
565 if self.stack_creator:
567 self.stack_creator.clean()
571 if self.image_creator:
573 self.image_creator.clean()
577 if self.flavor_creator:
579 self.flavor_creator.clean()
583 for vm_inst_creator in self.vm_inst_creators:
585 keypair_settings = vm_inst_creator.keypair_settings
586 if keypair_settings and keypair_settings.private_filepath:
587 expanded_path = os.path.expanduser(
588 keypair_settings.private_filepath)
589 os.chmod(expanded_path, 0o755)
590 os.remove(expanded_path)
594 super(self.__class__, self).__clean__()
596 def test_nested(self):
598 Tests the creation of an OpenStack stack from Heat template file and
599 the retrieval of two VM instance creators and attempt to connect via
600 SSH to the first one with a floating IP.
602 created_stack = self.stack_creator.create()
603 self.assertIsNotNone(created_stack)
605 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
606 heat_keypair_option='private_key')
607 self.assertIsNotNone(self.vm_inst_creators)
608 self.assertEqual(1, len(self.vm_inst_creators))
610 for vm_inst_creator in self.vm_inst_creators:
612 create_instance_tests.validate_ssh_client(vm_inst_creator))
615 class CreateStackRouterTests(OSIntegrationTestCase):
617 Tests for the CreateStack class defined in create_stack.py where the
618 target is a Network, Subnet, and Router
623 Instantiates the CreateStack object that is responsible for downloading
624 and creating an OS stack file within OpenStack
626 super(self.__class__, self).__start__()
628 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
630 self.heat_creds = self.admin_os_creds
631 self.heat_creds.project_name = self.admin_os_creds.project_name
633 self.heat_cli = heat_utils.heat_client(self.heat_creds)
634 self.neutron = neutron_utils.neutron_client(self.os_creds)
635 self.stack_creator = None
637 self.net_name = self.guid + '-net'
638 self.subnet_name = self.guid + '-subnet'
639 self.router_name = self.guid + '-router'
642 'net_name': self.net_name,
643 'subnet_name': self.subnet_name,
644 'router_name': self.router_name,
645 'external_net_name': self.ext_net_name}
647 self.heat_tmplt_path = pkg_resources.resource_filename(
648 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
650 stack_settings = StackConfig(
651 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
652 template_path=self.heat_tmplt_path,
653 env_values=self.env_values)
654 self.stack_creator = OpenStackHeatStack(
655 self.heat_creds, stack_settings)
656 self.created_stack = self.stack_creator.create()
657 self.assertIsNotNone(self.created_stack)
661 Cleans the stack and downloaded stack file
663 if self.stack_creator:
665 self.stack_creator.clean()
669 super(self.__class__, self).__clean__()
671 def test_retrieve_router_creator(self):
673 Tests the creation of an OpenStack stack from Heat template file and
674 the retrieval of an OpenStackRouter creator/state machine instance
676 router_creators = self.stack_creator.get_router_creators()
677 self.assertEqual(1, len(router_creators))
679 creator = router_creators[0]
680 self.assertEqual(self.router_name, creator.router_settings.name)
682 router = creator.get_router()
684 ext_net = neutron_utils.get_network(
685 self.neutron, network_name=self.ext_net_name)
686 self.assertEqual(ext_net.id, router.external_network_id)
689 class CreateStackVolumeTests(OSIntegrationTestCase):
691 Tests to ensure that floating IPs can be accessed via an
692 OpenStackVolume object obtained from the OpenStackHeatStack instance
697 super(self.__class__, self).__start__()
699 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
701 self.heat_creds = self.admin_os_creds
702 self.heat_creds.project_name = self.admin_os_creds.project_name
704 self.heat_cli = heat_utils.heat_client(self.heat_creds)
705 self.stack_creator = None
707 self.volume_name = self.guid + '-volume'
708 self.volume_type_name = self.guid + '-volume-type'
711 'volume_name': self.volume_name,
712 'volume_type_name': self.volume_type_name}
714 self.heat_tmplt_path = pkg_resources.resource_filename(
715 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
717 stack_settings = StackConfig(
718 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
719 template_path=self.heat_tmplt_path,
720 env_values=self.env_values)
721 self.stack_creator = OpenStackHeatStack(
722 self.heat_creds, stack_settings)
723 self.created_stack = self.stack_creator.create()
724 self.assertIsNotNone(self.created_stack)
728 Cleans the stack and downloaded stack file
730 if self.stack_creator:
732 self.stack_creator.clean()
736 super(self.__class__, self).__clean__()
738 def test_retrieve_volume_creator(self):
740 Tests the creation of an OpenStack stack from Heat template file and
741 the retrieval of an OpenStackVolume creator/state machine instance
743 volume_creators = self.stack_creator.get_volume_creators()
744 self.assertEqual(1, len(volume_creators))
746 creator = volume_creators[0]
747 self.assertEqual(self.volume_name, creator.volume_settings.name)
748 self.assertEqual(self.volume_name, creator.get_volume().name)
749 self.assertEqual(self.volume_type_name,
750 creator.volume_settings.type_name)
751 self.assertEqual(self.volume_type_name, creator.get_volume().type)
752 self.assertEqual(1, creator.volume_settings.size)
753 self.assertEqual(1, creator.get_volume().size)
755 def test_retrieve_volume_type_creator(self):
757 Tests the creation of an OpenStack stack from Heat template file and
758 the retrieval of an OpenStackVolume creator/state machine instance
760 volume_type_creators = self.stack_creator.get_volume_type_creators()
761 self.assertEqual(1, len(volume_type_creators))
763 creator = volume_type_creators[0]
764 self.assertIsNotNone(creator)
766 volume_type = creator.get_volume_type()
767 self.assertIsNotNone(volume_type)
769 self.assertEqual(self.volume_type_name, volume_type.name)
770 self.assertTrue(volume_type.public)
771 self.assertIsNone(volume_type.qos_spec)
773 # TODO - Add encryption back and find out why it broke in Pike
774 # encryption = volume_type.encryption
775 # self.assertIsNotNone(encryption)
776 # self.assertIsNone(encryption.cipher)
777 # self.assertEqual('front-end', encryption.control_location)
778 # self.assertIsNone(encryption.key_size)
779 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
780 # encryption.provider)
781 # self.assertEqual(volume_type.id, encryption.volume_type_id)
784 class CreateStackFlavorTests(OSIntegrationTestCase):
786 Tests to ensure that floating IPs can be accessed via an
787 OpenStackFlavor object obtained from the OpenStackHeatStack instance
792 super(self.__class__, self).__start__()
794 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
796 self.heat_creds = self.admin_os_creds
797 self.heat_creds.project_name = self.admin_os_creds.project_name
799 self.heat_cli = heat_utils.heat_client(self.heat_creds)
800 self.stack_creator = None
802 self.heat_tmplt_path = pkg_resources.resource_filename(
803 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
805 stack_settings = StackConfig(
806 name=self.guid + '-stack',
807 template_path=self.heat_tmplt_path)
808 self.stack_creator = OpenStackHeatStack(
809 self.heat_creds, stack_settings)
810 self.created_stack = self.stack_creator.create()
811 self.assertIsNotNone(self.created_stack)
815 Cleans the stack and downloaded stack file
817 if self.stack_creator:
819 self.stack_creator.clean()
823 super(self.__class__, self).__clean__()
825 def test_retrieve_flavor_creator(self):
827 Tests the creation of an OpenStack stack from Heat template file and
828 the retrieval of an OpenStackVolume creator/state machine instance
830 flavor_creators = self.stack_creator.get_flavor_creators()
831 self.assertEqual(1, len(flavor_creators))
833 creator = flavor_creators[0]
834 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
835 self.assertEqual(1024, creator.get_flavor().ram)
836 self.assertEqual(200, creator.get_flavor().disk)
837 self.assertEqual(8, creator.get_flavor().vcpus)
838 self.assertEqual(0, creator.get_flavor().ephemeral)
839 self.assertIsNone(creator.get_flavor().swap)
840 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
841 self.assertTrue(creator.get_flavor().is_public)
844 class CreateStackKeypairTests(OSIntegrationTestCase):
846 Tests to ensure that floating IPs can be accessed via an
847 OpenStackKeypair object obtained from the OpenStackHeatStack instance
852 super(self.__class__, self).__start__()
854 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
856 self.heat_creds = self.admin_os_creds
857 self.heat_creds.project_name = self.admin_os_creds.project_name
859 self.heat_cli = heat_utils.heat_client(self.heat_creds)
860 self.nova = nova_utils.nova_client(self.heat_creds)
861 self.stack_creator = None
863 self.keypair_name = self.guid + '-kp'
866 'keypair_name': self.keypair_name}
868 self.heat_tmplt_path = pkg_resources.resource_filename(
869 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
871 stack_settings = StackConfig(
872 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
873 template_path=self.heat_tmplt_path,
874 env_values=self.env_values)
875 self.stack_creator = OpenStackHeatStack(
876 self.heat_creds, stack_settings)
877 self.created_stack = self.stack_creator.create()
878 self.assertIsNotNone(self.created_stack)
880 self.keypair_creators = list()
884 Cleans the stack and downloaded stack file
886 if self.stack_creator:
888 self.stack_creator.clean()
891 for keypair_creator in self.keypair_creators:
893 keypair_creator.clean()
897 super(self.__class__, self).__clean__()
899 def test_retrieve_keypair_creator(self):
901 Tests the creation of an OpenStack stack from Heat template file and
902 the retrieval of an OpenStackKeypair creator/state machine instance
904 self.kp_creators = self.stack_creator.get_keypair_creators(
906 self.assertEqual(1, len(self.kp_creators))
908 self.keypair_creator = self.kp_creators[0]
910 self.assertEqual(self.keypair_name,
911 self.keypair_creator.get_keypair().name)
912 self.assertIsNotNone(
913 self.keypair_creator.keypair_settings.private_filepath)
915 private_file_contents = file_utils.read_file(
916 self.keypair_creator.keypair_settings.private_filepath)
917 self.assertTrue(private_file_contents.startswith(
918 '-----BEGIN RSA PRIVATE KEY-----'))
920 keypair = nova_utils.get_keypair_by_id(
921 self.nova, self.keypair_creator.get_keypair().id)
922 self.assertIsNotNone(keypair)
923 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
926 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
928 Tests for the OpenStackHeatStack class to ensure it returns an
929 OpenStackSecurityGroup object
934 Instantiates the CreateStack object that is responsible for downloading
935 and creating an OS stack file within OpenStack
937 super(self.__class__, self).__start__()
939 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
941 self.heat_creds = self.admin_os_creds
942 self.heat_creds.project_name = self.admin_os_creds.project_name
944 self.heat_cli = heat_utils.heat_client(self.heat_creds)
945 self.nova = nova_utils.nova_client(self.heat_creds)
946 self.stack_creator = None
948 self.security_group_name = self.guid + '-sec-grp'
951 'security_group_name': self.security_group_name}
953 self.heat_tmplt_path = pkg_resources.resource_filename(
954 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
956 stack_settings = StackConfig(
957 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
958 template_path=self.heat_tmplt_path,
959 env_values=self.env_values)
960 self.stack_creator = OpenStackHeatStack(
961 self.heat_creds, stack_settings)
962 self.created_stack = self.stack_creator.create()
963 self.assertIsNotNone(self.created_stack)
967 Cleans the stack and downloaded stack file
969 if self.stack_creator:
971 self.stack_creator.clean()
975 super(self.__class__, self).__clean__()
977 def test_retrieve_security_group_creator(self):
979 Tests the creation of an OpenStack stack from Heat template file and
980 the retrieval of an OpenStackSecurityGroup creator/state machine
983 sec_grp_creators = self.stack_creator.get_security_group_creators()
984 self.assertEqual(1, len(sec_grp_creators))
986 creator = sec_grp_creators[0]
987 sec_grp = creator.get_security_group()
989 self.assertEqual(self.security_group_name, sec_grp.name)
990 self.assertEqual('Test description', sec_grp.description)
991 self.assertEqual(2, len(sec_grp.rules))
994 has_icmp_rule = False
996 for rule in sec_grp.rules:
997 if (rule.security_group_id == sec_grp.id
998 and rule.direction == 'egress'
999 and rule.ethertype == 'IPv4'
1000 and rule.port_range_min == 22
1001 and rule.port_range_max == 22
1002 and rule.protocol == 'tcp'
1003 and rule.remote_group_id is None
1004 and rule.remote_ip_prefix == '0.0.0.0/0'):
1006 if (rule.security_group_id == sec_grp.id
1007 and rule.direction == 'ingress'
1008 and rule.ethertype == 'IPv4'
1009 and rule.port_range_min is None
1010 and rule.port_range_max is None
1011 and rule.protocol == 'icmp'
1012 and rule.remote_group_id is None
1013 and rule.remote_ip_prefix == '0.0.0.0/0'):
1014 has_icmp_rule = True
1016 self.assertTrue(has_ssh_rule)
1017 self.assertTrue(has_icmp_rule)
1020 class CreateStackNegativeTests(OSIntegrationTestCase):
1022 Negative test cases for the OpenStackHeatStack class with poor
1028 super(self.__class__, self).__start__()
1030 self.heat_creds = self.admin_os_creds
1031 self.heat_creds.project_name = self.admin_os_creds.project_name
1033 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1034 self.stack_creator = None
1035 self.heat_tmplt_path = pkg_resources.resource_filename(
1036 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1039 if self.stack_creator:
1040 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.heat_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.heat_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
1075 super(self.__class__, self).__start__()
1077 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1079 self.heat_creds = self.admin_os_creds
1080 self.heat_creds.project_name = self.admin_os_creds.project_name
1082 self.heat_cli = heat_utils.heat_client(self.heat_creds)
1083 self.stack_creator = None
1085 self.tmp_file = file_utils.save_string_to_file(
1086 ' ', str(uuid.uuid4()) + '-bad-image')
1087 self.image_creator = OpenStackImage(
1088 self.heat_creds, ImageConfig(
1089 name=self.guid + 'image', image_file=self.tmp_file.name,
1090 image_user='foo', img_format='qcow2'))
1091 self.image_creator.create()
1094 self.flavor_creator = OpenStackFlavor(
1095 self.admin_os_creds,
1097 name=self.guid + '-flavor-name', ram=256, disk=10,
1099 self.flavor_creator.create()
1101 self.network_name = self.guid + '-net'
1102 self.subnet_name = self.guid + '-subnet'
1103 self.vm_inst_name = self.guid + '-inst'
1106 'image_name': self.image_creator.image_settings.name,
1107 'flavor_name': self.flavor_creator.flavor_settings.name,
1108 'net_name': self.network_name,
1109 'subnet_name': self.subnet_name,
1110 'inst_name': self.vm_inst_name}
1112 self.heat_tmplt_path = pkg_resources.resource_filename(
1113 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1117 Cleans the stack and downloaded stack file
1119 if self.stack_creator:
1121 self.stack_creator.clean()
1125 if self.image_creator:
1127 self.image_creator.clean()
1131 if self.flavor_creator:
1133 self.flavor_creator.clean()
1139 os.remove(self.tmp_file.name)
1143 super(self.__class__, self).__clean__()
1145 def test_stack_failure(self):
1147 Tests the creation of an OpenStack stack from Heat template file that
1148 should always fail due to too many CPU cores
1151 # Set the default stack settings, then set any custom parameters sent
1153 stack_settings = StackConfig(
1154 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1155 template_path=self.heat_tmplt_path,
1156 env_values=self.env_values)
1157 self.stack_creator = OpenStackHeatStack(
1158 self.heat_creds, stack_settings)
1160 with self.assertRaises(StackError):
1162 self.stack_creator.create()
1164 resources = heat_utils.get_resources(
1165 self.heat_cli, self.stack_creator.get_stack().id)
1168 for resource in resources:
1169 if (resource.status ==
1170 snaps.config.stack.STATUS_CREATE_COMPLETE):
1172 self.assertTrue(found)