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
20 from snaps import file_utils
21 from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings
22 from snaps.openstack.create_image import OpenStackImage
23 from snaps.config.image import ImageConfig
26 from urllib.request import URLError
28 from urllib2 import URLError
34 from snaps.openstack import create_stack
35 from snaps.openstack.create_stack import (
36 StackSettings, StackSettingsError, StackCreationError, StackError)
37 from snaps.openstack.tests import openstack_tests, create_instance_tests
38 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
39 from snaps.openstack.utils import heat_utils, neutron_utils, nova_utils
41 __author__ = 'spisarski'
43 logger = logging.getLogger('create_stack_tests')
46 class StackSettingsUnitTests(unittest.TestCase):
48 Tests the construction of the StackSettings class
51 def test_no_params(self):
52 with self.assertRaises(StackSettingsError):
55 def test_empty_config(self):
56 with self.assertRaises(StackSettingsError):
57 StackSettings(**dict())
59 def test_name_only(self):
60 with self.assertRaises(StackSettingsError):
61 StackSettings(name='foo')
63 def test_config_with_name_only(self):
64 with self.assertRaises(StackSettingsError):
65 StackSettings(**{'name': 'foo'})
67 def test_config_minimum_template(self):
68 settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
69 self.assertEqual('stack', settings.name)
70 self.assertEqual('foo', settings.template)
71 self.assertIsNone(settings.template_path)
72 self.assertIsNone(settings.env_values)
73 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
74 settings.stack_create_timeout)
76 def test_config_minimum_template_path(self):
77 settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
78 self.assertEqual('stack', settings.name)
79 self.assertIsNone(settings.template)
80 self.assertEqual('foo', settings.template_path)
81 self.assertIsNone(settings.env_values)
82 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
83 settings.stack_create_timeout)
85 def test_minimum_template(self):
86 settings = StackSettings(name='stack', template='foo')
87 self.assertEqual('stack', settings.name)
88 self.assertEqual('foo', settings.template)
89 self.assertIsNone(settings.template_path)
90 self.assertIsNone(settings.env_values)
91 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
92 settings.stack_create_timeout)
94 def test_minimum_template_path(self):
95 settings = StackSettings(name='stack', template_path='foo')
96 self.assertEqual('stack', settings.name)
97 self.assertEqual('foo', settings.template_path)
98 self.assertIsNone(settings.template)
99 self.assertIsNone(settings.env_values)
100 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
101 settings.stack_create_timeout)
104 env_values = {'foo': 'bar'}
105 settings = StackSettings(name='stack', template='bar',
106 template_path='foo', env_values=env_values,
107 stack_create_timeout=999)
108 self.assertEqual('stack', settings.name)
109 self.assertEqual('bar', settings.template)
110 self.assertEqual('foo', settings.template_path)
111 self.assertEqual(env_values, settings.env_values)
112 self.assertEqual(999, settings.stack_create_timeout)
114 def test_config_all(self):
115 env_values = {'foo': 'bar'}
116 settings = StackSettings(
117 **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
118 'env_values': env_values, 'stack_create_timeout': 999})
119 self.assertEqual('stack', settings.name)
120 self.assertEqual('bar', settings.template)
121 self.assertEqual('foo', settings.template_path)
122 self.assertEqual(env_values, settings.env_values)
123 self.assertEqual(999, settings.stack_create_timeout)
126 class CreateStackSuccessTests(OSIntegrationTestCase):
128 Tests for the OpenStackHeatStack class defined in create_stack.py
133 super(self.__class__, self).__start__()
135 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
137 self.heat_creds = self.admin_os_creds
138 self.heat_creds.project_name = self.admin_os_creds.project_name
140 self.heat_cli = heat_utils.heat_client(self.heat_creds)
141 self.stack_creator = None
143 self.image_creator = OpenStackImage(
144 self.heat_creds, openstack_tests.cirros_image_settings(
145 name=self.guid + '-image',
146 image_metadata=self.image_metadata))
147 self.image_creator.create()
150 self.flavor_creator = OpenStackFlavor(
152 FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10,
154 self.flavor_creator.create()
156 self.network_name = self.guid + '-net'
157 self.subnet_name = self.guid + '-subnet'
158 self.vm_inst_name = self.guid + '-inst'
161 'image_name': self.image_creator.image_settings.name,
162 'flavor_name': self.flavor_creator.flavor_settings.name,
163 'net_name': self.network_name,
164 'subnet_name': self.subnet_name,
165 'inst_name': self.vm_inst_name}
167 self.heat_tmplt_path = pkg_resources.resource_filename(
168 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
172 Cleans the stack and downloaded stack file
174 if self.stack_creator:
176 self.stack_creator.clean()
180 if self.image_creator:
182 self.image_creator.clean()
186 if self.flavor_creator:
188 self.flavor_creator.clean()
192 super(self.__class__, self).__clean__()
194 def test_create_stack_template_file(self):
196 Tests the creation of an OpenStack stack from Heat template file.
199 # Set the default stack settings, then set any custom parameters sent
201 stack_settings = StackSettings(
202 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
203 template_path=self.heat_tmplt_path,
204 env_values=self.env_values)
205 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
207 created_stack = self.stack_creator.create()
208 self.assertIsNotNone(created_stack)
210 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
212 self.assertIsNotNone(retrieved_stack)
213 self.assertEqual(created_stack.name, retrieved_stack.name)
214 self.assertEqual(created_stack.id, retrieved_stack.id)
215 self.assertEqual(0, len(self.stack_creator.get_outputs()))
217 def test_create_stack_short_timeout(self):
219 Tests the creation of an OpenStack stack from Heat template file.
222 # Set the default stack settings, then set any custom parameters sent
224 stack_settings = StackSettings(
225 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
226 template_path=self.heat_tmplt_path,
227 env_values=self.env_values, stack_create_timeout=0)
229 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
231 with self.assertRaises(StackCreationError):
232 self.stack_creator.create()
234 def test_create_stack_template_dict(self):
236 Tests the creation of an OpenStack stack from a heat dict() object.
239 # Set the default stack settings, then set any custom parameters sent
241 template_dict = heat_utils.parse_heat_template_str(
242 file_utils.read_file(self.heat_tmplt_path))
243 stack_settings = StackSettings(
244 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
245 template=template_dict,
246 env_values=self.env_values)
247 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
249 created_stack = self.stack_creator.create()
250 self.assertIsNotNone(created_stack)
252 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
254 self.assertIsNotNone(retrieved_stack)
255 self.assertEqual(created_stack.name, retrieved_stack.name)
256 self.assertEqual(created_stack.id, retrieved_stack.id)
257 self.assertEqual(0, len(self.stack_creator.get_outputs()))
259 def test_create_delete_stack(self):
261 Tests the creation then deletion of an OpenStack stack to ensure
262 clean() does not raise an Exception.
265 template_dict = heat_utils.parse_heat_template_str(
266 file_utils.read_file(self.heat_tmplt_path))
267 stack_settings = StackSettings(
268 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
269 template=template_dict,
270 env_values=self.env_values)
271 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
273 created_stack = self.stack_creator.create()
274 self.assertIsNotNone(created_stack)
276 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
278 self.assertIsNotNone(retrieved_stack)
279 self.assertEqual(created_stack.name, retrieved_stack.name)
280 self.assertEqual(created_stack.id, retrieved_stack.id)
281 self.assertEqual(0, len(self.stack_creator.get_outputs()))
282 self.assertEqual(create_stack.STATUS_CREATE_COMPLETE,
283 self.stack_creator.get_status())
285 # Delete Stack manually
286 heat_utils.delete_stack(self.heat_cli, created_stack)
288 end_time = time.time() + 90
290 while time.time() < end_time:
291 status = heat_utils.get_stack_status(self.heat_cli,
293 if status == create_stack.STATUS_DELETE_COMPLETE:
297 self.assertTrue(deleted)
299 # Must not throw an exception when attempting to cleanup non-existent
301 self.stack_creator.clean()
302 self.assertIsNone(self.stack_creator.get_stack())
304 def test_create_same_stack(self):
306 Tests the creation of an OpenStack stack when the stack already exists.
309 template_dict = heat_utils.parse_heat_template_str(
310 file_utils.read_file(self.heat_tmplt_path))
311 stack_settings = StackSettings(
312 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
313 template=template_dict,
314 env_values=self.env_values)
315 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
317 created_stack1 = self.stack_creator.create()
319 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
321 self.assertIsNotNone(retrieved_stack)
322 self.assertEqual(created_stack1.name, retrieved_stack.name)
323 self.assertEqual(created_stack1.id, retrieved_stack.id)
324 self.assertEqual(0, len(self.stack_creator.get_outputs()))
326 # Should be retrieving the instance data
327 stack_creator2 = create_stack.OpenStackHeatStack(self.heat_creds,
329 stack2 = stack_creator2.create()
330 self.assertEqual(created_stack1.id, stack2.id)
332 def test_retrieve_network_creators(self):
334 Tests the creation of an OpenStack stack from Heat template file and
335 the retrieval of the network creator.
337 stack_settings = StackSettings(
338 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
339 template_path=self.heat_tmplt_path,
340 env_values=self.env_values)
341 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
343 created_stack = self.stack_creator.create()
344 self.assertIsNotNone(created_stack)
346 net_creators = self.stack_creator.get_network_creators()
347 self.assertIsNotNone(net_creators)
348 self.assertEqual(1, len(net_creators))
349 self.assertEqual(self.network_name, net_creators[0].get_network().name)
351 neutron = neutron_utils.neutron_client(self.os_creds)
352 net_by_name = neutron_utils.get_network(
353 neutron, network_name=net_creators[0].get_network().name)
354 self.assertEqual(net_creators[0].get_network(), net_by_name)
355 self.assertIsNotNone(neutron_utils.get_network_by_id(
356 neutron, net_creators[0].get_network().id))
358 self.assertEqual(1, len(net_creators[0].get_network().subnets))
359 subnet = net_creators[0].get_network().subnets[0]
360 subnet_by_name = neutron_utils.get_subnet(
361 neutron, subnet_name=subnet.name)
362 self.assertEqual(subnet, subnet_by_name)
364 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
365 self.assertIsNotNone(subnet_by_id)
366 self.assertEqual(subnet_by_name, subnet_by_id)
368 def test_retrieve_vm_inst_creators(self):
370 Tests the creation of an OpenStack stack from Heat template file and
371 the retrieval of the network creator.
373 stack_settings = StackSettings(
374 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
375 template_path=self.heat_tmplt_path,
376 env_values=self.env_values)
377 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
379 created_stack = self.stack_creator.create()
380 self.assertIsNotNone(created_stack)
382 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
383 self.assertIsNotNone(vm_inst_creators)
384 self.assertEqual(1, len(vm_inst_creators))
385 self.assertEqual(self.vm_inst_name,
386 vm_inst_creators[0].get_vm_inst().name)
388 nova = nova_utils.nova_client(self.admin_os_creds)
389 vm_inst_by_name = nova_utils.get_server(
390 nova, server_name=vm_inst_creators[0].get_vm_inst().name)
391 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
392 self.assertIsNotNone(nova_utils.get_server_object_by_id(
393 nova, vm_inst_creators[0].get_vm_inst().id))
396 class CreateStackFloatingIpTests(OSIntegrationTestCase):
398 Tests to ensure that floating IPs can be accessed via an
399 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
404 super(self.__class__, self).__start__()
406 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
408 self.heat_creds = self.admin_os_creds
409 self.heat_creds.project_name = self.admin_os_creds.project_name
411 self.heat_cli = heat_utils.heat_client(self.heat_creds)
412 self.stack_creator = None
414 self.image_creator = OpenStackImage(
415 self.heat_creds, openstack_tests.cirros_image_settings(
416 name=self.guid + '-image',
417 image_metadata=self.image_metadata))
418 self.image_creator.create()
420 self.network_name = self.guid + '-net'
421 self.subnet_name = self.guid + '-subnet'
422 self.flavor1_name = self.guid + '-flavor1'
423 self.flavor2_name = self.guid + '-flavor2'
424 self.sec_grp_name = self.guid + '-sec_grp'
425 self.vm_inst1_name = self.guid + '-inst1'
426 self.vm_inst2_name = self.guid + '-inst2'
427 self.keypair_name = self.guid + '-kp'
430 'image1_name': self.image_creator.image_settings.name,
431 'image2_name': self.image_creator.image_settings.name,
432 'flavor1_name': self.flavor1_name,
433 'flavor2_name': self.flavor2_name,
434 'net_name': self.network_name,
435 'subnet_name': self.subnet_name,
436 'inst1_name': self.vm_inst1_name,
437 'inst2_name': self.vm_inst2_name,
438 'keypair_name': self.keypair_name,
439 'external_net_name': self.ext_net_name,
440 'security_group_name': self.sec_grp_name}
442 self.heat_tmplt_path = pkg_resources.resource_filename(
443 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
445 self.vm_inst_creators = list()
449 Cleans the stack and downloaded stack file
451 if self.stack_creator:
453 self.stack_creator.clean()
457 if self.image_creator:
459 self.image_creator.clean()
463 for vm_inst_creator in self.vm_inst_creators:
465 keypair_settings = vm_inst_creator.keypair_settings
466 if keypair_settings and keypair_settings.private_filepath:
467 expanded_path = os.path.expanduser(
468 keypair_settings.private_filepath)
469 os.chmod(expanded_path, 0o755)
470 os.remove(expanded_path)
474 super(self.__class__, self).__clean__()
476 def test_connect_via_ssh_heat_vm(self):
478 Tests the creation of an OpenStack stack from Heat template file and
479 the retrieval of two VM instance creators and attempt to connect via
480 SSH to the first one with a floating IP.
482 stack_settings = StackSettings(
483 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
484 template_path=self.heat_tmplt_path,
485 env_values=self.env_values)
486 self.stack_creator = create_stack.OpenStackHeatStack(
487 self.heat_creds, stack_settings,
488 [self.image_creator.image_settings])
489 created_stack = self.stack_creator.create()
490 self.assertIsNotNone(created_stack)
492 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
493 heat_keypair_option='private_key')
494 self.assertIsNotNone(self.vm_inst_creators)
495 self.assertEqual(2, len(self.vm_inst_creators))
497 for vm_inst_creator in self.vm_inst_creators:
498 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
500 create_instance_tests.validate_ssh_client(vm_inst_creator))
502 vm_settings = vm_inst_creator.instance_settings
503 self.assertEqual(0, len(vm_settings.floating_ip_settings))
506 class CreateStackRouterTests(OSIntegrationTestCase):
508 Tests for the CreateStack class defined in create_stack.py where the
509 target is a Network, Subnet, and Router
514 Instantiates the CreateStack object that is responsible for downloading
515 and creating an OS stack file within OpenStack
517 super(self.__class__, self).__start__()
519 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
521 self.heat_creds = self.admin_os_creds
522 self.heat_creds.project_name = self.admin_os_creds.project_name
524 self.heat_cli = heat_utils.heat_client(self.heat_creds)
525 self.neutron = neutron_utils.neutron_client(self.os_creds)
526 self.stack_creator = None
528 self.net_name = self.guid + '-net'
529 self.subnet_name = self.guid + '-subnet'
530 self.router_name = self.guid + '-router'
533 'net_name': self.net_name,
534 'subnet_name': self.subnet_name,
535 'router_name': self.router_name,
536 'external_net_name': self.ext_net_name}
538 self.heat_tmplt_path = pkg_resources.resource_filename(
539 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
541 stack_settings = StackSettings(
542 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
543 template_path=self.heat_tmplt_path,
544 env_values=self.env_values)
545 self.stack_creator = create_stack.OpenStackHeatStack(
546 self.heat_creds, stack_settings)
547 self.created_stack = self.stack_creator.create()
548 self.assertIsNotNone(self.created_stack)
552 Cleans the stack and downloaded stack file
554 if self.stack_creator:
556 self.stack_creator.clean()
560 super(self.__class__, self).__clean__()
562 def test_retrieve_router_creator(self):
564 Tests the creation of an OpenStack stack from Heat template file and
565 the retrieval of an OpenStackRouter creator/state machine instance
567 router_creators = self.stack_creator.get_router_creators()
568 self.assertEqual(1, len(router_creators))
570 creator = router_creators[0]
571 self.assertEqual(self.router_name, creator.router_settings.name)
573 router = creator.get_router()
575 ext_net = neutron_utils.get_network(
576 self.neutron, network_name=self.ext_net_name)
577 self.assertEqual(ext_net.id, router.external_network_id)
580 class CreateStackVolumeTests(OSIntegrationTestCase):
582 Tests to ensure that floating IPs can be accessed via an
583 OpenStackVolume object obtained from the OpenStackHeatStack instance
588 super(self.__class__, self).__start__()
590 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
592 self.heat_creds = self.admin_os_creds
593 self.heat_creds.project_name = self.admin_os_creds.project_name
595 self.heat_cli = heat_utils.heat_client(self.heat_creds)
596 self.stack_creator = None
598 self.volume_name = self.guid + '-volume'
599 self.volume_type_name = self.guid + '-volume-type'
602 'volume_name': self.volume_name,
603 'volume_type_name': self.volume_type_name}
605 self.heat_tmplt_path = pkg_resources.resource_filename(
606 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
608 stack_settings = StackSettings(
609 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
610 template_path=self.heat_tmplt_path,
611 env_values=self.env_values)
612 self.stack_creator = create_stack.OpenStackHeatStack(
613 self.heat_creds, stack_settings)
614 self.created_stack = self.stack_creator.create()
615 self.assertIsNotNone(self.created_stack)
619 Cleans the stack and downloaded stack file
621 if self.stack_creator:
623 self.stack_creator.clean()
627 super(self.__class__, self).__clean__()
629 def test_retrieve_volume_creator(self):
631 Tests the creation of an OpenStack stack from Heat template file and
632 the retrieval of an OpenStackVolume creator/state machine instance
634 volume_creators = self.stack_creator.get_volume_creators()
635 self.assertEqual(1, len(volume_creators))
637 creator = volume_creators[0]
638 self.assertEqual(self.volume_name, creator.volume_settings.name)
639 self.assertEqual(self.volume_name, creator.get_volume().name)
640 self.assertEqual(self.volume_type_name,
641 creator.volume_settings.type_name)
642 self.assertEqual(self.volume_type_name, creator.get_volume().type)
643 self.assertEqual(1, creator.volume_settings.size)
644 self.assertEqual(1, creator.get_volume().size)
646 def test_retrieve_volume_type_creator(self):
648 Tests the creation of an OpenStack stack from Heat template file and
649 the retrieval of an OpenStackVolume creator/state machine instance
651 volume_type_creators = self.stack_creator.get_volume_type_creators()
652 self.assertEqual(1, len(volume_type_creators))
654 creator = volume_type_creators[0]
655 self.assertIsNotNone(creator)
657 volume_type = creator.get_volume_type()
658 self.assertIsNotNone(volume_type)
660 self.assertEqual(self.volume_type_name, volume_type.name)
661 self.assertTrue(volume_type.public)
662 self.assertIsNone(volume_type.qos_spec)
664 encryption = volume_type.encryption
665 self.assertIsNotNone(encryption)
666 self.assertIsNone(encryption.cipher)
667 self.assertEqual('front-end', encryption.control_location)
668 self.assertIsNone(encryption.key_size)
669 self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
671 self.assertEqual(volume_type.id, encryption.volume_type_id)
674 class CreateStackFlavorTests(OSIntegrationTestCase):
676 Tests to ensure that floating IPs can be accessed via an
677 OpenStackFlavor object obtained from the OpenStackHeatStack instance
682 super(self.__class__, self).__start__()
684 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
686 self.heat_creds = self.admin_os_creds
687 self.heat_creds.project_name = self.admin_os_creds.project_name
689 self.heat_cli = heat_utils.heat_client(self.heat_creds)
690 self.stack_creator = None
692 self.heat_tmplt_path = pkg_resources.resource_filename(
693 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
695 stack_settings = StackSettings(
696 name=self.guid + '-stack',
697 template_path=self.heat_tmplt_path)
698 self.stack_creator = create_stack.OpenStackHeatStack(
699 self.heat_creds, stack_settings)
700 self.created_stack = self.stack_creator.create()
701 self.assertIsNotNone(self.created_stack)
705 Cleans the stack and downloaded stack file
707 if self.stack_creator:
709 self.stack_creator.clean()
713 super(self.__class__, self).__clean__()
715 def test_retrieve_flavor_creator(self):
717 Tests the creation of an OpenStack stack from Heat template file and
718 the retrieval of an OpenStackVolume creator/state machine instance
720 flavor_creators = self.stack_creator.get_flavor_creators()
721 self.assertEqual(1, len(flavor_creators))
723 creator = flavor_creators[0]
724 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
725 self.assertEqual(1024, creator.get_flavor().ram)
726 self.assertEqual(200, creator.get_flavor().disk)
727 self.assertEqual(8, creator.get_flavor().vcpus)
728 self.assertEqual(0, creator.get_flavor().ephemeral)
729 self.assertIsNone(creator.get_flavor().swap)
730 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
731 self.assertTrue(creator.get_flavor().is_public)
734 class CreateStackKeypairTests(OSIntegrationTestCase):
736 Tests to ensure that floating IPs can be accessed via an
737 OpenStackKeypair object obtained from the OpenStackHeatStack instance
742 super(self.__class__, self).__start__()
744 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
746 self.heat_creds = self.admin_os_creds
747 self.heat_creds.project_name = self.admin_os_creds.project_name
749 self.heat_cli = heat_utils.heat_client(self.heat_creds)
750 self.nova = nova_utils.nova_client(self.heat_creds)
751 self.stack_creator = None
753 self.keypair_name = self.guid + '-kp'
756 'keypair_name': self.keypair_name}
758 self.heat_tmplt_path = pkg_resources.resource_filename(
759 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
761 stack_settings = StackSettings(
762 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
763 template_path=self.heat_tmplt_path,
764 env_values=self.env_values)
765 self.stack_creator = create_stack.OpenStackHeatStack(
766 self.heat_creds, stack_settings)
767 self.created_stack = self.stack_creator.create()
768 self.assertIsNotNone(self.created_stack)
770 self.keypair_creators = list()
774 Cleans the stack and downloaded stack file
776 if self.stack_creator:
778 self.stack_creator.clean()
781 for keypair_creator in self.keypair_creators:
783 keypair_creator.clean()
787 super(self.__class__, self).__clean__()
789 def test_retrieve_keypair_creator(self):
791 Tests the creation of an OpenStack stack from Heat template file and
792 the retrieval of an OpenStackKeypair creator/state machine instance
794 self.kp_creators = self.stack_creator.get_keypair_creators(
796 self.assertEqual(1, len(self.kp_creators))
798 self.keypair_creator = self.kp_creators[0]
800 self.assertEqual(self.keypair_name,
801 self.keypair_creator.get_keypair().name)
802 self.assertIsNotNone(
803 self.keypair_creator.keypair_settings.private_filepath)
805 private_file_contents = file_utils.read_file(
806 self.keypair_creator.keypair_settings.private_filepath)
807 self.assertTrue(private_file_contents.startswith(
808 '-----BEGIN RSA PRIVATE KEY-----'))
810 keypair = nova_utils.get_keypair_by_id(
811 self.nova, self.keypair_creator.get_keypair().id)
812 self.assertIsNotNone(keypair)
813 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
816 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
818 Tests for the OpenStackHeatStack class to ensure it returns an
819 OpenStackSecurityGroup object
824 Instantiates the CreateStack object that is responsible for downloading
825 and creating an OS stack file within OpenStack
827 super(self.__class__, self).__start__()
829 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
831 self.heat_creds = self.admin_os_creds
832 self.heat_creds.project_name = self.admin_os_creds.project_name
834 self.heat_cli = heat_utils.heat_client(self.heat_creds)
835 self.nova = nova_utils.nova_client(self.heat_creds)
836 self.stack_creator = None
838 self.security_group_name = self.guid + '-sec-grp'
841 'security_group_name': self.security_group_name}
843 self.heat_tmplt_path = pkg_resources.resource_filename(
844 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
846 stack_settings = StackSettings(
847 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
848 template_path=self.heat_tmplt_path,
849 env_values=self.env_values)
850 self.stack_creator = create_stack.OpenStackHeatStack(
851 self.heat_creds, stack_settings)
852 self.created_stack = self.stack_creator.create()
853 self.assertIsNotNone(self.created_stack)
857 Cleans the stack and downloaded stack file
859 if self.stack_creator:
861 self.stack_creator.clean()
865 super(self.__class__, self).__clean__()
867 def test_retrieve_security_group_creator(self):
869 Tests the creation of an OpenStack stack from Heat template file and
870 the retrieval of an OpenStackSecurityGroup creator/state machine
873 sec_grp_creators = self.stack_creator.get_security_group_creators()
874 self.assertEqual(1, len(sec_grp_creators))
876 creator = sec_grp_creators[0]
877 sec_grp = creator.get_security_group()
879 self.assertEqual(self.security_group_name, sec_grp.name)
880 self.assertEqual('Test description', sec_grp.description)
881 self.assertEqual(2, len(sec_grp.rules))
884 has_icmp_rule = False
886 for rule in sec_grp.rules:
887 if (rule.security_group_id == sec_grp.id
888 and rule.direction == 'egress'
889 and rule.ethertype == 'IPv4'
890 and rule.port_range_min == 22
891 and rule.port_range_max == 22
892 and rule.protocol == 'tcp'
893 and rule.remote_group_id is None
894 and rule.remote_ip_prefix == '0.0.0.0/0'):
896 if (rule.security_group_id == sec_grp.id
897 and rule.direction == 'ingress'
898 and rule.ethertype == 'IPv4'
899 and rule.port_range_min is None
900 and rule.port_range_max is None
901 and rule.protocol == 'icmp'
902 and rule.remote_group_id is None
903 and rule.remote_ip_prefix == '0.0.0.0/0'):
906 self.assertTrue(has_ssh_rule)
907 self.assertTrue(has_icmp_rule)
910 class CreateStackNegativeTests(OSIntegrationTestCase):
912 Negative test cases for the OpenStackHeatStack class with poor
918 super(self.__class__, self).__start__()
920 self.heat_creds = self.admin_os_creds
921 self.heat_creds.project_name = self.admin_os_creds.project_name
923 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
924 self.stack_creator = None
925 self.heat_tmplt_path = pkg_resources.resource_filename(
926 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
929 if self.stack_creator:
930 self.stack_creator.clean()
931 super(self.__class__, self).__clean__()
933 def test_missing_dependencies(self):
935 Expect an StackCreationError when the stack file does not exist
937 stack_settings = StackSettings(name=self.stack_name,
938 template_path=self.heat_tmplt_path)
939 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
941 with self.assertRaises(HTTPBadRequest):
942 self.stack_creator.create()
944 def test_bad_stack_file(self):
946 Expect an StackCreationError when the stack file does not exist
948 stack_settings = StackSettings(name=self.stack_name,
950 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
952 with self.assertRaises(IOError):
953 self.stack_creator.create()
956 class CreateStackFailureTests(OSIntegrationTestCase):
958 Tests for the OpenStackHeatStack class defined in create_stack.py for
959 when failures occur. Failures are being triggered by allocating 1 million
965 super(self.__class__, self).__start__()
967 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
969 self.heat_creds = self.admin_os_creds
970 self.heat_creds.project_name = self.admin_os_creds.project_name
972 self.heat_cli = heat_utils.heat_client(self.heat_creds)
973 self.stack_creator = None
975 self.tmp_file = file_utils.save_string_to_file(
976 ' ', str(uuid.uuid4()) + '-bad-image')
977 self.image_creator = OpenStackImage(
978 self.heat_creds, ImageConfig(
979 name=self.guid + 'image', image_file=self.tmp_file.name,
980 image_user='foo', img_format='qcow2'))
981 self.image_creator.create()
984 self.flavor_creator = OpenStackFlavor(
986 FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10,
988 self.flavor_creator.create()
990 self.network_name = self.guid + '-net'
991 self.subnet_name = self.guid + '-subnet'
992 self.vm_inst_name = self.guid + '-inst'
995 'image_name': self.image_creator.image_settings.name,
996 'flavor_name': self.flavor_creator.flavor_settings.name,
997 'net_name': self.network_name,
998 'subnet_name': self.subnet_name,
999 'inst_name': self.vm_inst_name}
1001 self.heat_tmplt_path = pkg_resources.resource_filename(
1002 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1006 Cleans the stack and downloaded stack file
1008 if self.stack_creator:
1010 self.stack_creator.clean()
1014 if self.image_creator:
1016 self.image_creator.clean()
1020 if self.flavor_creator:
1022 self.flavor_creator.clean()
1028 os.remove(self.tmp_file.name)
1032 super(self.__class__, self).__clean__()
1034 def test_stack_failure(self):
1036 Tests the creation of an OpenStack stack from Heat template file that
1037 should always fail due to too many CPU cores
1040 # Set the default stack settings, then set any custom parameters sent
1042 stack_settings = StackSettings(
1043 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1044 template_path=self.heat_tmplt_path,
1045 env_values=self.env_values)
1046 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
1049 with self.assertRaises(StackError):
1051 self.stack_creator.create()
1053 resources = heat_utils.get_resources(
1054 self.heat_cli, self.stack_creator.get_stack())
1057 for resource in resources:
1058 if resource.status == create_stack.STATUS_CREATE_COMPLETE:
1060 self.assertTrue(found)