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.config.flavor import FlavorConfig
22 from snaps.config.image import ImageConfig
23 from snaps.openstack.create_flavor import OpenStackFlavor
24 from snaps.openstack.create_image import OpenStackImage
27 from urllib.request import URLError
29 from urllib2 import URLError
35 from snaps.openstack import create_stack
36 from snaps.openstack.create_stack import (
37 StackSettings, StackSettingsError, StackCreationError, StackError)
38 from snaps.openstack.tests import openstack_tests, create_instance_tests
39 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
40 from snaps.openstack.utils import heat_utils, neutron_utils, nova_utils
42 __author__ = 'spisarski'
44 logger = logging.getLogger('create_stack_tests')
47 class StackSettingsUnitTests(unittest.TestCase):
49 Tests the construction of the StackSettings class
52 def test_no_params(self):
53 with self.assertRaises(StackSettingsError):
56 def test_empty_config(self):
57 with self.assertRaises(StackSettingsError):
58 StackSettings(**dict())
60 def test_name_only(self):
61 with self.assertRaises(StackSettingsError):
62 StackSettings(name='foo')
64 def test_config_with_name_only(self):
65 with self.assertRaises(StackSettingsError):
66 StackSettings(**{'name': 'foo'})
68 def test_config_minimum_template(self):
69 settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
70 self.assertEqual('stack', settings.name)
71 self.assertEqual('foo', settings.template)
72 self.assertIsNone(settings.template_path)
73 self.assertIsNone(settings.env_values)
74 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
75 settings.stack_create_timeout)
77 def test_config_minimum_template_path(self):
78 settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
79 self.assertEqual('stack', settings.name)
80 self.assertIsNone(settings.template)
81 self.assertEqual('foo', settings.template_path)
82 self.assertIsNone(settings.env_values)
83 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
84 settings.stack_create_timeout)
86 def test_minimum_template(self):
87 settings = StackSettings(name='stack', template='foo')
88 self.assertEqual('stack', settings.name)
89 self.assertEqual('foo', settings.template)
90 self.assertIsNone(settings.template_path)
91 self.assertIsNone(settings.env_values)
92 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
93 settings.stack_create_timeout)
95 def test_minimum_template_path(self):
96 settings = StackSettings(name='stack', template_path='foo')
97 self.assertEqual('stack', settings.name)
98 self.assertEqual('foo', settings.template_path)
99 self.assertIsNone(settings.template)
100 self.assertIsNone(settings.env_values)
101 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
102 settings.stack_create_timeout)
105 env_values = {'foo': 'bar'}
106 settings = StackSettings(name='stack', template='bar',
107 template_path='foo', env_values=env_values,
108 stack_create_timeout=999)
109 self.assertEqual('stack', settings.name)
110 self.assertEqual('bar', settings.template)
111 self.assertEqual('foo', settings.template_path)
112 self.assertEqual(env_values, settings.env_values)
113 self.assertEqual(999, settings.stack_create_timeout)
115 def test_config_all(self):
116 env_values = {'foo': 'bar'}
117 settings = StackSettings(
118 **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
119 'env_values': env_values, 'stack_create_timeout': 999})
120 self.assertEqual('stack', settings.name)
121 self.assertEqual('bar', settings.template)
122 self.assertEqual('foo', settings.template_path)
123 self.assertEqual(env_values, settings.env_values)
124 self.assertEqual(999, settings.stack_create_timeout)
127 class CreateStackSuccessTests(OSIntegrationTestCase):
129 Tests for the OpenStackHeatStack class defined in create_stack.py
134 super(self.__class__, self).__start__()
136 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
138 self.heat_creds = self.admin_os_creds
139 self.heat_creds.project_name = self.admin_os_creds.project_name
141 self.heat_cli = heat_utils.heat_client(self.heat_creds)
142 self.stack_creator = None
144 self.image_creator = OpenStackImage(
145 self.heat_creds, openstack_tests.cirros_image_settings(
146 name=self.guid + '-image',
147 image_metadata=self.image_metadata))
148 self.image_creator.create()
151 self.flavor_creator = OpenStackFlavor(
154 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
155 self.flavor_creator.create()
157 self.network_name = self.guid + '-net'
158 self.subnet_name = self.guid + '-subnet'
159 self.vm_inst_name = self.guid + '-inst'
162 'image_name': self.image_creator.image_settings.name,
163 'flavor_name': self.flavor_creator.flavor_settings.name,
164 'net_name': self.network_name,
165 'subnet_name': self.subnet_name,
166 'inst_name': self.vm_inst_name}
168 self.heat_tmplt_path = pkg_resources.resource_filename(
169 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
173 Cleans the stack and downloaded stack file
175 if self.stack_creator:
177 self.stack_creator.clean()
181 if self.image_creator:
183 self.image_creator.clean()
187 if self.flavor_creator:
189 self.flavor_creator.clean()
193 super(self.__class__, self).__clean__()
195 def test_create_stack_template_file(self):
197 Tests the creation of an OpenStack stack from Heat template file.
200 # Set the default stack settings, then set any custom parameters sent
202 stack_settings = StackSettings(
203 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
204 template_path=self.heat_tmplt_path,
205 env_values=self.env_values)
206 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
208 created_stack = self.stack_creator.create()
209 self.assertIsNotNone(created_stack)
211 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
213 self.assertIsNotNone(retrieved_stack)
214 self.assertEqual(created_stack.name, retrieved_stack.name)
215 self.assertEqual(created_stack.id, retrieved_stack.id)
216 self.assertEqual(0, len(self.stack_creator.get_outputs()))
218 def test_create_stack_short_timeout(self):
220 Tests the creation of an OpenStack stack from Heat template file.
223 # Set the default stack settings, then set any custom parameters sent
225 stack_settings = StackSettings(
226 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
227 template_path=self.heat_tmplt_path,
228 env_values=self.env_values, stack_create_timeout=0)
230 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
232 with self.assertRaises(StackCreationError):
233 self.stack_creator.create()
235 def test_create_stack_template_dict(self):
237 Tests the creation of an OpenStack stack from a heat dict() object.
240 # Set the default stack settings, then set any custom parameters sent
242 template_dict = heat_utils.parse_heat_template_str(
243 file_utils.read_file(self.heat_tmplt_path))
244 stack_settings = StackSettings(
245 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
246 template=template_dict,
247 env_values=self.env_values)
248 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
250 created_stack = self.stack_creator.create()
251 self.assertIsNotNone(created_stack)
253 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
255 self.assertIsNotNone(retrieved_stack)
256 self.assertEqual(created_stack.name, retrieved_stack.name)
257 self.assertEqual(created_stack.id, retrieved_stack.id)
258 self.assertEqual(0, len(self.stack_creator.get_outputs()))
260 def test_create_delete_stack(self):
262 Tests the creation then deletion of an OpenStack stack to ensure
263 clean() does not raise an Exception.
266 template_dict = heat_utils.parse_heat_template_str(
267 file_utils.read_file(self.heat_tmplt_path))
268 stack_settings = StackSettings(
269 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
270 template=template_dict,
271 env_values=self.env_values)
272 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
274 created_stack = self.stack_creator.create()
275 self.assertIsNotNone(created_stack)
277 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
279 self.assertIsNotNone(retrieved_stack)
280 self.assertEqual(created_stack.name, retrieved_stack.name)
281 self.assertEqual(created_stack.id, retrieved_stack.id)
282 self.assertEqual(0, len(self.stack_creator.get_outputs()))
283 self.assertEqual(create_stack.STATUS_CREATE_COMPLETE,
284 self.stack_creator.get_status())
286 # Delete Stack manually
287 heat_utils.delete_stack(self.heat_cli, created_stack)
289 end_time = time.time() + 90
291 while time.time() < end_time:
292 status = heat_utils.get_stack_status(self.heat_cli,
294 if status == create_stack.STATUS_DELETE_COMPLETE:
298 self.assertTrue(deleted)
300 # Must not throw an exception when attempting to cleanup non-existent
302 self.stack_creator.clean()
303 self.assertIsNone(self.stack_creator.get_stack())
305 def test_create_same_stack(self):
307 Tests the creation of an OpenStack stack when the stack already exists.
310 template_dict = heat_utils.parse_heat_template_str(
311 file_utils.read_file(self.heat_tmplt_path))
312 stack_settings = StackSettings(
313 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
314 template=template_dict,
315 env_values=self.env_values)
316 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
318 created_stack1 = self.stack_creator.create()
320 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
322 self.assertIsNotNone(retrieved_stack)
323 self.assertEqual(created_stack1.name, retrieved_stack.name)
324 self.assertEqual(created_stack1.id, retrieved_stack.id)
325 self.assertEqual(0, len(self.stack_creator.get_outputs()))
327 # Should be retrieving the instance data
328 stack_creator2 = create_stack.OpenStackHeatStack(self.heat_creds,
330 stack2 = stack_creator2.create()
331 self.assertEqual(created_stack1.id, stack2.id)
333 def test_retrieve_network_creators(self):
335 Tests the creation of an OpenStack stack from Heat template file and
336 the retrieval of the network creator.
338 stack_settings = StackSettings(
339 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
340 template_path=self.heat_tmplt_path,
341 env_values=self.env_values)
342 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
344 created_stack = self.stack_creator.create()
345 self.assertIsNotNone(created_stack)
347 net_creators = self.stack_creator.get_network_creators()
348 self.assertIsNotNone(net_creators)
349 self.assertEqual(1, len(net_creators))
350 self.assertEqual(self.network_name, net_creators[0].get_network().name)
352 neutron = neutron_utils.neutron_client(self.os_creds)
353 net_by_name = neutron_utils.get_network(
354 neutron, network_name=net_creators[0].get_network().name)
355 self.assertEqual(net_creators[0].get_network(), net_by_name)
356 self.assertIsNotNone(neutron_utils.get_network_by_id(
357 neutron, net_creators[0].get_network().id))
359 self.assertEqual(1, len(net_creators[0].get_network().subnets))
360 subnet = net_creators[0].get_network().subnets[0]
361 subnet_by_name = neutron_utils.get_subnet(
362 neutron, subnet_name=subnet.name)
363 self.assertEqual(subnet, subnet_by_name)
365 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
366 self.assertIsNotNone(subnet_by_id)
367 self.assertEqual(subnet_by_name, subnet_by_id)
369 def test_retrieve_vm_inst_creators(self):
371 Tests the creation of an OpenStack stack from Heat template file and
372 the retrieval of the network creator.
374 stack_settings = StackSettings(
375 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
376 template_path=self.heat_tmplt_path,
377 env_values=self.env_values)
378 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
380 created_stack = self.stack_creator.create()
381 self.assertIsNotNone(created_stack)
383 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
384 self.assertIsNotNone(vm_inst_creators)
385 self.assertEqual(1, len(vm_inst_creators))
386 self.assertEqual(self.vm_inst_name,
387 vm_inst_creators[0].get_vm_inst().name)
389 nova = nova_utils.nova_client(self.admin_os_creds)
390 vm_inst_by_name = nova_utils.get_server(
391 nova, server_name=vm_inst_creators[0].get_vm_inst().name)
392 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
393 self.assertIsNotNone(nova_utils.get_server_object_by_id(
394 nova, vm_inst_creators[0].get_vm_inst().id))
397 class CreateStackFloatingIpTests(OSIntegrationTestCase):
399 Tests to ensure that floating IPs can be accessed via an
400 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
405 super(self.__class__, self).__start__()
407 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
409 self.heat_creds = self.admin_os_creds
410 self.heat_creds.project_name = self.admin_os_creds.project_name
412 self.heat_cli = heat_utils.heat_client(self.heat_creds)
413 self.stack_creator = None
415 self.image_creator = OpenStackImage(
416 self.heat_creds, openstack_tests.cirros_image_settings(
417 name=self.guid + '-image',
418 image_metadata=self.image_metadata))
419 self.image_creator.create()
421 self.network_name = self.guid + '-net'
422 self.subnet_name = self.guid + '-subnet'
423 self.flavor1_name = self.guid + '-flavor1'
424 self.flavor2_name = self.guid + '-flavor2'
425 self.sec_grp_name = self.guid + '-sec_grp'
426 self.vm_inst1_name = self.guid + '-inst1'
427 self.vm_inst2_name = self.guid + '-inst2'
428 self.keypair_name = self.guid + '-kp'
431 'image1_name': self.image_creator.image_settings.name,
432 'image2_name': self.image_creator.image_settings.name,
433 'flavor1_name': self.flavor1_name,
434 'flavor2_name': self.flavor2_name,
435 'net_name': self.network_name,
436 'subnet_name': self.subnet_name,
437 'inst1_name': self.vm_inst1_name,
438 'inst2_name': self.vm_inst2_name,
439 'keypair_name': self.keypair_name,
440 'external_net_name': self.ext_net_name,
441 'security_group_name': self.sec_grp_name}
443 self.heat_tmplt_path = pkg_resources.resource_filename(
444 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
446 self.vm_inst_creators = list()
450 Cleans the stack and downloaded stack file
452 if self.stack_creator:
454 self.stack_creator.clean()
458 if self.image_creator:
460 self.image_creator.clean()
464 for vm_inst_creator in self.vm_inst_creators:
466 keypair_settings = vm_inst_creator.keypair_settings
467 if keypair_settings and keypair_settings.private_filepath:
468 expanded_path = os.path.expanduser(
469 keypair_settings.private_filepath)
470 os.chmod(expanded_path, 0o755)
471 os.remove(expanded_path)
475 super(self.__class__, self).__clean__()
477 def test_connect_via_ssh_heat_vm(self):
479 Tests the creation of an OpenStack stack from Heat template file and
480 the retrieval of two VM instance creators and attempt to connect via
481 SSH to the first one with a floating IP.
483 stack_settings = StackSettings(
484 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
485 template_path=self.heat_tmplt_path,
486 env_values=self.env_values)
487 self.stack_creator = create_stack.OpenStackHeatStack(
488 self.heat_creds, stack_settings,
489 [self.image_creator.image_settings])
490 created_stack = self.stack_creator.create()
491 self.assertIsNotNone(created_stack)
493 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
494 heat_keypair_option='private_key')
495 self.assertIsNotNone(self.vm_inst_creators)
496 self.assertEqual(2, len(self.vm_inst_creators))
498 for vm_inst_creator in self.vm_inst_creators:
499 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
501 create_instance_tests.validate_ssh_client(vm_inst_creator))
503 vm_settings = vm_inst_creator.instance_settings
504 self.assertEqual(0, len(vm_settings.floating_ip_settings))
507 class CreateStackRouterTests(OSIntegrationTestCase):
509 Tests for the CreateStack class defined in create_stack.py where the
510 target is a Network, Subnet, and Router
515 Instantiates the CreateStack object that is responsible for downloading
516 and creating an OS stack file within OpenStack
518 super(self.__class__, self).__start__()
520 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
522 self.heat_creds = self.admin_os_creds
523 self.heat_creds.project_name = self.admin_os_creds.project_name
525 self.heat_cli = heat_utils.heat_client(self.heat_creds)
526 self.neutron = neutron_utils.neutron_client(self.os_creds)
527 self.stack_creator = None
529 self.net_name = self.guid + '-net'
530 self.subnet_name = self.guid + '-subnet'
531 self.router_name = self.guid + '-router'
534 'net_name': self.net_name,
535 'subnet_name': self.subnet_name,
536 'router_name': self.router_name,
537 'external_net_name': self.ext_net_name}
539 self.heat_tmplt_path = pkg_resources.resource_filename(
540 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
542 stack_settings = StackSettings(
543 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
544 template_path=self.heat_tmplt_path,
545 env_values=self.env_values)
546 self.stack_creator = create_stack.OpenStackHeatStack(
547 self.heat_creds, stack_settings)
548 self.created_stack = self.stack_creator.create()
549 self.assertIsNotNone(self.created_stack)
553 Cleans the stack and downloaded stack file
555 if self.stack_creator:
557 self.stack_creator.clean()
561 super(self.__class__, self).__clean__()
563 def test_retrieve_router_creator(self):
565 Tests the creation of an OpenStack stack from Heat template file and
566 the retrieval of an OpenStackRouter creator/state machine instance
568 router_creators = self.stack_creator.get_router_creators()
569 self.assertEqual(1, len(router_creators))
571 creator = router_creators[0]
572 self.assertEqual(self.router_name, creator.router_settings.name)
574 router = creator.get_router()
576 ext_net = neutron_utils.get_network(
577 self.neutron, network_name=self.ext_net_name)
578 self.assertEqual(ext_net.id, router.external_network_id)
581 class CreateStackVolumeTests(OSIntegrationTestCase):
583 Tests to ensure that floating IPs can be accessed via an
584 OpenStackVolume object obtained from the OpenStackHeatStack instance
589 super(self.__class__, self).__start__()
591 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
593 self.heat_creds = self.admin_os_creds
594 self.heat_creds.project_name = self.admin_os_creds.project_name
596 self.heat_cli = heat_utils.heat_client(self.heat_creds)
597 self.stack_creator = None
599 self.volume_name = self.guid + '-volume'
600 self.volume_type_name = self.guid + '-volume-type'
603 'volume_name': self.volume_name,
604 'volume_type_name': self.volume_type_name}
606 self.heat_tmplt_path = pkg_resources.resource_filename(
607 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
609 stack_settings = StackSettings(
610 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
611 template_path=self.heat_tmplt_path,
612 env_values=self.env_values)
613 self.stack_creator = create_stack.OpenStackHeatStack(
614 self.heat_creds, stack_settings)
615 self.created_stack = self.stack_creator.create()
616 self.assertIsNotNone(self.created_stack)
620 Cleans the stack and downloaded stack file
622 if self.stack_creator:
624 self.stack_creator.clean()
628 super(self.__class__, self).__clean__()
630 def test_retrieve_volume_creator(self):
632 Tests the creation of an OpenStack stack from Heat template file and
633 the retrieval of an OpenStackVolume creator/state machine instance
635 volume_creators = self.stack_creator.get_volume_creators()
636 self.assertEqual(1, len(volume_creators))
638 creator = volume_creators[0]
639 self.assertEqual(self.volume_name, creator.volume_settings.name)
640 self.assertEqual(self.volume_name, creator.get_volume().name)
641 self.assertEqual(self.volume_type_name,
642 creator.volume_settings.type_name)
643 self.assertEqual(self.volume_type_name, creator.get_volume().type)
644 self.assertEqual(1, creator.volume_settings.size)
645 self.assertEqual(1, creator.get_volume().size)
647 def test_retrieve_volume_type_creator(self):
649 Tests the creation of an OpenStack stack from Heat template file and
650 the retrieval of an OpenStackVolume creator/state machine instance
652 volume_type_creators = self.stack_creator.get_volume_type_creators()
653 self.assertEqual(1, len(volume_type_creators))
655 creator = volume_type_creators[0]
656 self.assertIsNotNone(creator)
658 volume_type = creator.get_volume_type()
659 self.assertIsNotNone(volume_type)
661 self.assertEqual(self.volume_type_name, volume_type.name)
662 self.assertTrue(volume_type.public)
663 self.assertIsNone(volume_type.qos_spec)
665 encryption = volume_type.encryption
666 self.assertIsNotNone(encryption)
667 self.assertIsNone(encryption.cipher)
668 self.assertEqual('front-end', encryption.control_location)
669 self.assertIsNone(encryption.key_size)
670 self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
672 self.assertEqual(volume_type.id, encryption.volume_type_id)
675 class CreateStackFlavorTests(OSIntegrationTestCase):
677 Tests to ensure that floating IPs can be accessed via an
678 OpenStackFlavor object obtained from the OpenStackHeatStack instance
683 super(self.__class__, self).__start__()
685 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
687 self.heat_creds = self.admin_os_creds
688 self.heat_creds.project_name = self.admin_os_creds.project_name
690 self.heat_cli = heat_utils.heat_client(self.heat_creds)
691 self.stack_creator = None
693 self.heat_tmplt_path = pkg_resources.resource_filename(
694 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
696 stack_settings = StackSettings(
697 name=self.guid + '-stack',
698 template_path=self.heat_tmplt_path)
699 self.stack_creator = create_stack.OpenStackHeatStack(
700 self.heat_creds, stack_settings)
701 self.created_stack = self.stack_creator.create()
702 self.assertIsNotNone(self.created_stack)
706 Cleans the stack and downloaded stack file
708 if self.stack_creator:
710 self.stack_creator.clean()
714 super(self.__class__, self).__clean__()
716 def test_retrieve_flavor_creator(self):
718 Tests the creation of an OpenStack stack from Heat template file and
719 the retrieval of an OpenStackVolume creator/state machine instance
721 flavor_creators = self.stack_creator.get_flavor_creators()
722 self.assertEqual(1, len(flavor_creators))
724 creator = flavor_creators[0]
725 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
726 self.assertEqual(1024, creator.get_flavor().ram)
727 self.assertEqual(200, creator.get_flavor().disk)
728 self.assertEqual(8, creator.get_flavor().vcpus)
729 self.assertEqual(0, creator.get_flavor().ephemeral)
730 self.assertIsNone(creator.get_flavor().swap)
731 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
732 self.assertTrue(creator.get_flavor().is_public)
735 class CreateStackKeypairTests(OSIntegrationTestCase):
737 Tests to ensure that floating IPs can be accessed via an
738 OpenStackKeypair object obtained from the OpenStackHeatStack instance
743 super(self.__class__, self).__start__()
745 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
747 self.heat_creds = self.admin_os_creds
748 self.heat_creds.project_name = self.admin_os_creds.project_name
750 self.heat_cli = heat_utils.heat_client(self.heat_creds)
751 self.nova = nova_utils.nova_client(self.heat_creds)
752 self.stack_creator = None
754 self.keypair_name = self.guid + '-kp'
757 'keypair_name': self.keypair_name}
759 self.heat_tmplt_path = pkg_resources.resource_filename(
760 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
762 stack_settings = StackSettings(
763 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
764 template_path=self.heat_tmplt_path,
765 env_values=self.env_values)
766 self.stack_creator = create_stack.OpenStackHeatStack(
767 self.heat_creds, stack_settings)
768 self.created_stack = self.stack_creator.create()
769 self.assertIsNotNone(self.created_stack)
771 self.keypair_creators = list()
775 Cleans the stack and downloaded stack file
777 if self.stack_creator:
779 self.stack_creator.clean()
782 for keypair_creator in self.keypair_creators:
784 keypair_creator.clean()
788 super(self.__class__, self).__clean__()
790 def test_retrieve_keypair_creator(self):
792 Tests the creation of an OpenStack stack from Heat template file and
793 the retrieval of an OpenStackKeypair creator/state machine instance
795 self.kp_creators = self.stack_creator.get_keypair_creators(
797 self.assertEqual(1, len(self.kp_creators))
799 self.keypair_creator = self.kp_creators[0]
801 self.assertEqual(self.keypair_name,
802 self.keypair_creator.get_keypair().name)
803 self.assertIsNotNone(
804 self.keypair_creator.keypair_settings.private_filepath)
806 private_file_contents = file_utils.read_file(
807 self.keypair_creator.keypair_settings.private_filepath)
808 self.assertTrue(private_file_contents.startswith(
809 '-----BEGIN RSA PRIVATE KEY-----'))
811 keypair = nova_utils.get_keypair_by_id(
812 self.nova, self.keypair_creator.get_keypair().id)
813 self.assertIsNotNone(keypair)
814 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
817 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
819 Tests for the OpenStackHeatStack class to ensure it returns an
820 OpenStackSecurityGroup object
825 Instantiates the CreateStack object that is responsible for downloading
826 and creating an OS stack file within OpenStack
828 super(self.__class__, self).__start__()
830 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
832 self.heat_creds = self.admin_os_creds
833 self.heat_creds.project_name = self.admin_os_creds.project_name
835 self.heat_cli = heat_utils.heat_client(self.heat_creds)
836 self.nova = nova_utils.nova_client(self.heat_creds)
837 self.stack_creator = None
839 self.security_group_name = self.guid + '-sec-grp'
842 'security_group_name': self.security_group_name}
844 self.heat_tmplt_path = pkg_resources.resource_filename(
845 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
847 stack_settings = StackSettings(
848 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
849 template_path=self.heat_tmplt_path,
850 env_values=self.env_values)
851 self.stack_creator = create_stack.OpenStackHeatStack(
852 self.heat_creds, stack_settings)
853 self.created_stack = self.stack_creator.create()
854 self.assertIsNotNone(self.created_stack)
858 Cleans the stack and downloaded stack file
860 if self.stack_creator:
862 self.stack_creator.clean()
866 super(self.__class__, self).__clean__()
868 def test_retrieve_security_group_creator(self):
870 Tests the creation of an OpenStack stack from Heat template file and
871 the retrieval of an OpenStackSecurityGroup creator/state machine
874 sec_grp_creators = self.stack_creator.get_security_group_creators()
875 self.assertEqual(1, len(sec_grp_creators))
877 creator = sec_grp_creators[0]
878 sec_grp = creator.get_security_group()
880 self.assertEqual(self.security_group_name, sec_grp.name)
881 self.assertEqual('Test description', sec_grp.description)
882 self.assertEqual(2, len(sec_grp.rules))
885 has_icmp_rule = False
887 for rule in sec_grp.rules:
888 if (rule.security_group_id == sec_grp.id
889 and rule.direction == 'egress'
890 and rule.ethertype == 'IPv4'
891 and rule.port_range_min == 22
892 and rule.port_range_max == 22
893 and rule.protocol == 'tcp'
894 and rule.remote_group_id is None
895 and rule.remote_ip_prefix == '0.0.0.0/0'):
897 if (rule.security_group_id == sec_grp.id
898 and rule.direction == 'ingress'
899 and rule.ethertype == 'IPv4'
900 and rule.port_range_min is None
901 and rule.port_range_max is None
902 and rule.protocol == 'icmp'
903 and rule.remote_group_id is None
904 and rule.remote_ip_prefix == '0.0.0.0/0'):
907 self.assertTrue(has_ssh_rule)
908 self.assertTrue(has_icmp_rule)
911 class CreateStackNegativeTests(OSIntegrationTestCase):
913 Negative test cases for the OpenStackHeatStack class with poor
919 super(self.__class__, self).__start__()
921 self.heat_creds = self.admin_os_creds
922 self.heat_creds.project_name = self.admin_os_creds.project_name
924 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
925 self.stack_creator = None
926 self.heat_tmplt_path = pkg_resources.resource_filename(
927 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
930 if self.stack_creator:
931 self.stack_creator.clean()
932 super(self.__class__, self).__clean__()
934 def test_missing_dependencies(self):
936 Expect an StackCreationError when the stack file does not exist
938 stack_settings = StackSettings(name=self.stack_name,
939 template_path=self.heat_tmplt_path)
940 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
942 with self.assertRaises(HTTPBadRequest):
943 self.stack_creator.create()
945 def test_bad_stack_file(self):
947 Expect an StackCreationError when the stack file does not exist
949 stack_settings = StackSettings(name=self.stack_name,
951 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
953 with self.assertRaises(IOError):
954 self.stack_creator.create()
957 class CreateStackFailureTests(OSIntegrationTestCase):
959 Tests for the OpenStackHeatStack class defined in create_stack.py for
960 when failures occur. Failures are being triggered by allocating 1 million
966 super(self.__class__, self).__start__()
968 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
970 self.heat_creds = self.admin_os_creds
971 self.heat_creds.project_name = self.admin_os_creds.project_name
973 self.heat_cli = heat_utils.heat_client(self.heat_creds)
974 self.stack_creator = None
976 self.tmp_file = file_utils.save_string_to_file(
977 ' ', str(uuid.uuid4()) + '-bad-image')
978 self.image_creator = OpenStackImage(
979 self.heat_creds, ImageConfig(
980 name=self.guid + 'image', image_file=self.tmp_file.name,
981 image_user='foo', img_format='qcow2'))
982 self.image_creator.create()
985 self.flavor_creator = OpenStackFlavor(
988 name=self.guid + '-flavor-name', ram=256, disk=10,
990 self.flavor_creator.create()
992 self.network_name = self.guid + '-net'
993 self.subnet_name = self.guid + '-subnet'
994 self.vm_inst_name = self.guid + '-inst'
997 'image_name': self.image_creator.image_settings.name,
998 'flavor_name': self.flavor_creator.flavor_settings.name,
999 'net_name': self.network_name,
1000 'subnet_name': self.subnet_name,
1001 'inst_name': self.vm_inst_name}
1003 self.heat_tmplt_path = pkg_resources.resource_filename(
1004 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1008 Cleans the stack and downloaded stack file
1010 if self.stack_creator:
1012 self.stack_creator.clean()
1016 if self.image_creator:
1018 self.image_creator.clean()
1022 if self.flavor_creator:
1024 self.flavor_creator.clean()
1030 os.remove(self.tmp_file.name)
1034 super(self.__class__, self).__clean__()
1036 def test_stack_failure(self):
1038 Tests the creation of an OpenStack stack from Heat template file that
1039 should always fail due to too many CPU cores
1042 # Set the default stack settings, then set any custom parameters sent
1044 stack_settings = StackSettings(
1045 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1046 template_path=self.heat_tmplt_path,
1047 env_values=self.env_values)
1048 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
1051 with self.assertRaises(StackError):
1053 self.stack_creator.create()
1055 resources = heat_utils.get_resources(
1056 self.heat_cli, self.stack_creator.get_stack())
1059 for resource in resources:
1060 if resource.status == create_stack.STATUS_CREATE_COMPLETE:
1062 self.assertTrue(found)