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, ImageSettings
25 from urllib.request import URLError
27 from urllib2 import URLError
33 from snaps.openstack import create_stack
34 from snaps.openstack.create_stack import (
35 StackSettings, StackSettingsError, StackCreationError, StackError)
36 from snaps.openstack.tests import openstack_tests, create_instance_tests
37 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
38 from snaps.openstack.utils import heat_utils, neutron_utils, nova_utils
40 __author__ = 'spisarski'
42 logger = logging.getLogger('create_stack_tests')
45 class StackSettingsUnitTests(unittest.TestCase):
47 Tests the construction of the StackSettings class
50 def test_no_params(self):
51 with self.assertRaises(StackSettingsError):
54 def test_empty_config(self):
55 with self.assertRaises(StackSettingsError):
56 StackSettings(**dict())
58 def test_name_only(self):
59 with self.assertRaises(StackSettingsError):
60 StackSettings(name='foo')
62 def test_config_with_name_only(self):
63 with self.assertRaises(StackSettingsError):
64 StackSettings(**{'name': 'foo'})
66 def test_config_minimum_template(self):
67 settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
68 self.assertEqual('stack', settings.name)
69 self.assertEqual('foo', settings.template)
70 self.assertIsNone(settings.template_path)
71 self.assertIsNone(settings.env_values)
72 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
73 settings.stack_create_timeout)
75 def test_config_minimum_template_path(self):
76 settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
77 self.assertEqual('stack', settings.name)
78 self.assertIsNone(settings.template)
79 self.assertEqual('foo', settings.template_path)
80 self.assertIsNone(settings.env_values)
81 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
82 settings.stack_create_timeout)
84 def test_minimum_template(self):
85 settings = StackSettings(name='stack', template='foo')
86 self.assertEqual('stack', settings.name)
87 self.assertEqual('foo', settings.template)
88 self.assertIsNone(settings.template_path)
89 self.assertIsNone(settings.env_values)
90 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
91 settings.stack_create_timeout)
93 def test_minimum_template_path(self):
94 settings = StackSettings(name='stack', template_path='foo')
95 self.assertEqual('stack', settings.name)
96 self.assertEqual('foo', settings.template_path)
97 self.assertIsNone(settings.template)
98 self.assertIsNone(settings.env_values)
99 self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT,
100 settings.stack_create_timeout)
103 env_values = {'foo': 'bar'}
104 settings = StackSettings(name='stack', template='bar',
105 template_path='foo', env_values=env_values,
106 stack_create_timeout=999)
107 self.assertEqual('stack', settings.name)
108 self.assertEqual('bar', settings.template)
109 self.assertEqual('foo', settings.template_path)
110 self.assertEqual(env_values, settings.env_values)
111 self.assertEqual(999, settings.stack_create_timeout)
113 def test_config_all(self):
114 env_values = {'foo': 'bar'}
115 settings = StackSettings(
116 **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
117 'env_values': env_values, 'stack_create_timeout': 999})
118 self.assertEqual('stack', settings.name)
119 self.assertEqual('bar', settings.template)
120 self.assertEqual('foo', settings.template_path)
121 self.assertEqual(env_values, settings.env_values)
122 self.assertEqual(999, settings.stack_create_timeout)
125 class CreateStackSuccessTests(OSIntegrationTestCase):
127 Tests for the OpenStackHeatStack class defined in create_stack.py
132 super(self.__class__, self).__start__()
134 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
136 self.heat_creds = self.admin_os_creds
137 self.heat_creds.project_name = self.admin_os_creds.project_name
139 self.heat_cli = heat_utils.heat_client(self.heat_creds)
140 self.stack_creator = None
142 self.image_creator = OpenStackImage(
143 self.heat_creds, openstack_tests.cirros_image_settings(
144 name=self.guid + '-image',
145 image_metadata=self.image_metadata))
146 self.image_creator.create()
149 self.flavor_creator = OpenStackFlavor(
151 FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10,
153 self.flavor_creator.create()
155 self.network_name = self.guid + '-net'
156 self.subnet_name = self.guid + '-subnet'
157 self.vm_inst_name = self.guid + '-inst'
160 'image_name': self.image_creator.image_settings.name,
161 'flavor_name': self.flavor_creator.flavor_settings.name,
162 'net_name': self.network_name,
163 'subnet_name': self.subnet_name,
164 'inst_name': self.vm_inst_name}
166 self.heat_tmplt_path = pkg_resources.resource_filename(
167 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
171 Cleans the stack and downloaded stack file
173 if self.stack_creator:
175 self.stack_creator.clean()
179 if self.image_creator:
181 self.image_creator.clean()
185 if self.flavor_creator:
187 self.flavor_creator.clean()
191 super(self.__class__, self).__clean__()
193 def test_create_stack_template_file(self):
195 Tests the creation of an OpenStack stack from Heat template file.
198 # Set the default stack settings, then set any custom parameters sent
200 stack_settings = StackSettings(
201 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
202 template_path=self.heat_tmplt_path,
203 env_values=self.env_values)
204 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
206 created_stack = self.stack_creator.create()
207 self.assertIsNotNone(created_stack)
209 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
211 self.assertIsNotNone(retrieved_stack)
212 self.assertEqual(created_stack.name, retrieved_stack.name)
213 self.assertEqual(created_stack.id, retrieved_stack.id)
214 self.assertEqual(0, len(self.stack_creator.get_outputs()))
216 def test_create_stack_short_timeout(self):
218 Tests the creation of an OpenStack stack from Heat template file.
221 # Set the default stack settings, then set any custom parameters sent
223 stack_settings = StackSettings(
224 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
225 template_path=self.heat_tmplt_path,
226 env_values=self.env_values, stack_create_timeout=0)
228 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
230 with self.assertRaises(StackCreationError):
231 self.stack_creator.create()
233 def test_create_stack_template_dict(self):
235 Tests the creation of an OpenStack stack from a heat dict() object.
238 # Set the default stack settings, then set any custom parameters sent
240 template_dict = heat_utils.parse_heat_template_str(
241 file_utils.read_file(self.heat_tmplt_path))
242 stack_settings = StackSettings(
243 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
244 template=template_dict,
245 env_values=self.env_values)
246 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
248 created_stack = self.stack_creator.create()
249 self.assertIsNotNone(created_stack)
251 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
253 self.assertIsNotNone(retrieved_stack)
254 self.assertEqual(created_stack.name, retrieved_stack.name)
255 self.assertEqual(created_stack.id, retrieved_stack.id)
256 self.assertEqual(0, len(self.stack_creator.get_outputs()))
258 def test_create_delete_stack(self):
260 Tests the creation then deletion of an OpenStack stack to ensure
261 clean() does not raise an Exception.
264 template_dict = heat_utils.parse_heat_template_str(
265 file_utils.read_file(self.heat_tmplt_path))
266 stack_settings = StackSettings(
267 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
268 template=template_dict,
269 env_values=self.env_values)
270 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
272 created_stack = self.stack_creator.create()
273 self.assertIsNotNone(created_stack)
275 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
277 self.assertIsNotNone(retrieved_stack)
278 self.assertEqual(created_stack.name, retrieved_stack.name)
279 self.assertEqual(created_stack.id, retrieved_stack.id)
280 self.assertEqual(0, len(self.stack_creator.get_outputs()))
281 self.assertEqual(create_stack.STATUS_CREATE_COMPLETE,
282 self.stack_creator.get_status())
284 # Delete Stack manually
285 heat_utils.delete_stack(self.heat_cli, created_stack)
287 end_time = time.time() + 90
289 while time.time() < end_time:
290 status = heat_utils.get_stack_status(self.heat_cli,
292 if status == create_stack.STATUS_DELETE_COMPLETE:
296 self.assertTrue(deleted)
298 # Must not throw an exception when attempting to cleanup non-existent
300 self.stack_creator.clean()
301 self.assertIsNone(self.stack_creator.get_stack())
303 def test_create_same_stack(self):
305 Tests the creation of an OpenStack stack when the stack already exists.
308 template_dict = heat_utils.parse_heat_template_str(
309 file_utils.read_file(self.heat_tmplt_path))
310 stack_settings = StackSettings(
311 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
312 template=template_dict,
313 env_values=self.env_values)
314 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
316 created_stack1 = self.stack_creator.create()
318 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
320 self.assertIsNotNone(retrieved_stack)
321 self.assertEqual(created_stack1.name, retrieved_stack.name)
322 self.assertEqual(created_stack1.id, retrieved_stack.id)
323 self.assertEqual(0, len(self.stack_creator.get_outputs()))
325 # Should be retrieving the instance data
326 stack_creator2 = create_stack.OpenStackHeatStack(self.heat_creds,
328 stack2 = stack_creator2.create()
329 self.assertEqual(created_stack1.id, stack2.id)
331 def test_retrieve_network_creators(self):
333 Tests the creation of an OpenStack stack from Heat template file and
334 the retrieval of the network creator.
336 stack_settings = StackSettings(
337 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
338 template_path=self.heat_tmplt_path,
339 env_values=self.env_values)
340 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
342 created_stack = self.stack_creator.create()
343 self.assertIsNotNone(created_stack)
345 net_creators = self.stack_creator.get_network_creators()
346 self.assertIsNotNone(net_creators)
347 self.assertEqual(1, len(net_creators))
348 self.assertEqual(self.network_name, net_creators[0].get_network().name)
350 neutron = neutron_utils.neutron_client(self.os_creds)
351 net_by_name = neutron_utils.get_network(
352 neutron, network_name=net_creators[0].get_network().name)
353 self.assertEqual(net_creators[0].get_network(), net_by_name)
354 self.assertIsNotNone(neutron_utils.get_network_by_id(
355 neutron, net_creators[0].get_network().id))
357 self.assertEqual(1, len(net_creators[0].get_network().subnets))
358 subnet = net_creators[0].get_network().subnets[0]
359 subnet_by_name = neutron_utils.get_subnet(
360 neutron, subnet_name=subnet.name)
361 self.assertEqual(subnet, subnet_by_name)
363 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
364 self.assertIsNotNone(subnet_by_id)
365 self.assertEqual(subnet_by_name, subnet_by_id)
367 def test_retrieve_vm_inst_creators(self):
369 Tests the creation of an OpenStack stack from Heat template file and
370 the retrieval of the network creator.
372 stack_settings = StackSettings(
373 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
374 template_path=self.heat_tmplt_path,
375 env_values=self.env_values)
376 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
378 created_stack = self.stack_creator.create()
379 self.assertIsNotNone(created_stack)
381 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
382 self.assertIsNotNone(vm_inst_creators)
383 self.assertEqual(1, len(vm_inst_creators))
384 self.assertEqual(self.vm_inst_name,
385 vm_inst_creators[0].get_vm_inst().name)
387 nova = nova_utils.nova_client(self.admin_os_creds)
388 vm_inst_by_name = nova_utils.get_server(
389 nova, server_name=vm_inst_creators[0].get_vm_inst().name)
390 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
391 self.assertIsNotNone(nova_utils.get_server_object_by_id(
392 nova, vm_inst_creators[0].get_vm_inst().id))
395 class CreateStackFloatingIpTests(OSIntegrationTestCase):
397 Tests to ensure that floating IPs can be accessed via an
398 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
403 super(self.__class__, self).__start__()
405 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
407 self.heat_creds = self.admin_os_creds
408 self.heat_creds.project_name = self.admin_os_creds.project_name
410 self.heat_cli = heat_utils.heat_client(self.heat_creds)
411 self.stack_creator = None
413 self.image_creator = OpenStackImage(
414 self.heat_creds, openstack_tests.cirros_image_settings(
415 name=self.guid + '-image',
416 image_metadata=self.image_metadata))
417 self.image_creator.create()
419 self.network_name = self.guid + '-net'
420 self.subnet_name = self.guid + '-subnet'
421 self.flavor1_name = self.guid + '-flavor1'
422 self.flavor2_name = self.guid + '-flavor2'
423 self.sec_grp_name = self.guid + '-sec_grp'
424 self.vm_inst1_name = self.guid + '-inst1'
425 self.vm_inst2_name = self.guid + '-inst2'
426 self.keypair_name = self.guid + '-kp'
429 'image1_name': self.image_creator.image_settings.name,
430 'image2_name': self.image_creator.image_settings.name,
431 'flavor1_name': self.flavor1_name,
432 'flavor2_name': self.flavor2_name,
433 'net_name': self.network_name,
434 'subnet_name': self.subnet_name,
435 'inst1_name': self.vm_inst1_name,
436 'inst2_name': self.vm_inst2_name,
437 'keypair_name': self.keypair_name,
438 'external_net_name': self.ext_net_name,
439 'security_group_name': self.sec_grp_name}
441 self.heat_tmplt_path = pkg_resources.resource_filename(
442 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
444 self.vm_inst_creators = list()
448 Cleans the stack and downloaded stack file
450 if self.stack_creator:
452 self.stack_creator.clean()
456 if self.image_creator:
458 self.image_creator.clean()
462 for vm_inst_creator in self.vm_inst_creators:
464 keypair_settings = vm_inst_creator.keypair_settings
465 if keypair_settings and keypair_settings.private_filepath:
466 expanded_path = os.path.expanduser(
467 keypair_settings.private_filepath)
468 os.chmod(expanded_path, 0o755)
469 os.remove(expanded_path)
473 super(self.__class__, self).__clean__()
475 def test_connect_via_ssh_heat_vm(self):
477 Tests the creation of an OpenStack stack from Heat template file and
478 the retrieval of two VM instance creators and attempt to connect via
479 SSH to the first one with a floating IP.
481 stack_settings = StackSettings(
482 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
483 template_path=self.heat_tmplt_path,
484 env_values=self.env_values)
485 self.stack_creator = create_stack.OpenStackHeatStack(
486 self.heat_creds, stack_settings,
487 [self.image_creator.image_settings])
488 created_stack = self.stack_creator.create()
489 self.assertIsNotNone(created_stack)
491 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
492 heat_keypair_option='private_key')
493 self.assertIsNotNone(self.vm_inst_creators)
494 self.assertEqual(2, len(self.vm_inst_creators))
496 for vm_inst_creator in self.vm_inst_creators:
497 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
499 create_instance_tests.validate_ssh_client(vm_inst_creator))
501 vm_settings = vm_inst_creator.instance_settings
502 self.assertEqual(0, len(vm_settings.floating_ip_settings))
505 class CreateStackRouterTests(OSIntegrationTestCase):
507 Tests for the CreateStack class defined in create_stack.py where the
508 target is a Network, Subnet, and Router
513 Instantiates the CreateStack object that is responsible for downloading
514 and creating an OS stack file within OpenStack
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.neutron = neutron_utils.neutron_client(self.os_creds)
525 self.stack_creator = None
527 self.net_name = self.guid + '-net'
528 self.subnet_name = self.guid + '-subnet'
529 self.router_name = self.guid + '-router'
532 'net_name': self.net_name,
533 'subnet_name': self.subnet_name,
534 'router_name': self.router_name,
535 'external_net_name': self.ext_net_name}
537 self.heat_tmplt_path = pkg_resources.resource_filename(
538 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
540 stack_settings = StackSettings(
541 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
542 template_path=self.heat_tmplt_path,
543 env_values=self.env_values)
544 self.stack_creator = create_stack.OpenStackHeatStack(
545 self.heat_creds, stack_settings)
546 self.created_stack = self.stack_creator.create()
547 self.assertIsNotNone(self.created_stack)
551 Cleans the stack and downloaded stack file
553 if self.stack_creator:
555 self.stack_creator.clean()
559 super(self.__class__, self).__clean__()
561 def test_retrieve_router_creator(self):
563 Tests the creation of an OpenStack stack from Heat template file and
564 the retrieval of an OpenStackRouter creator/state machine instance
566 router_creators = self.stack_creator.get_router_creators()
567 self.assertEqual(1, len(router_creators))
569 creator = router_creators[0]
570 self.assertEqual(self.router_name, creator.router_settings.name)
572 router = creator.get_router()
574 ext_net = neutron_utils.get_network(
575 self.neutron, network_name=self.ext_net_name)
576 self.assertEqual(ext_net.id, router.external_network_id)
579 class CreateStackVolumeTests(OSIntegrationTestCase):
581 Tests to ensure that floating IPs can be accessed via an
582 OpenStackVolume object obtained from the OpenStackHeatStack instance
587 super(self.__class__, self).__start__()
589 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
591 self.heat_creds = self.admin_os_creds
592 self.heat_creds.project_name = self.admin_os_creds.project_name
594 self.heat_cli = heat_utils.heat_client(self.heat_creds)
595 self.stack_creator = None
597 self.volume_name = self.guid + '-volume'
598 self.volume_type_name = self.guid + '-volume-type'
601 'volume_name': self.volume_name,
602 'volume_type_name': self.volume_type_name}
604 self.heat_tmplt_path = pkg_resources.resource_filename(
605 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
607 stack_settings = StackSettings(
608 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
609 template_path=self.heat_tmplt_path,
610 env_values=self.env_values)
611 self.stack_creator = create_stack.OpenStackHeatStack(
612 self.heat_creds, stack_settings)
613 self.created_stack = self.stack_creator.create()
614 self.assertIsNotNone(self.created_stack)
618 Cleans the stack and downloaded stack file
620 if self.stack_creator:
622 self.stack_creator.clean()
626 super(self.__class__, self).__clean__()
628 def test_retrieve_volume_creator(self):
630 Tests the creation of an OpenStack stack from Heat template file and
631 the retrieval of an OpenStackVolume creator/state machine instance
633 volume_creators = self.stack_creator.get_volume_creators()
634 self.assertEqual(1, len(volume_creators))
636 creator = volume_creators[0]
637 self.assertEqual(self.volume_name, creator.volume_settings.name)
638 self.assertEqual(self.volume_name, creator.get_volume().name)
639 self.assertEqual(self.volume_type_name,
640 creator.volume_settings.type_name)
641 self.assertEqual(self.volume_type_name, creator.get_volume().type)
642 self.assertEqual(1, creator.volume_settings.size)
643 self.assertEqual(1, creator.get_volume().size)
645 def test_retrieve_volume_type_creator(self):
647 Tests the creation of an OpenStack stack from Heat template file and
648 the retrieval of an OpenStackVolume creator/state machine instance
650 volume_type_creators = self.stack_creator.get_volume_type_creators()
651 self.assertEqual(1, len(volume_type_creators))
653 creator = volume_type_creators[0]
654 self.assertIsNotNone(creator)
656 volume_type = creator.get_volume_type()
657 self.assertIsNotNone(volume_type)
659 self.assertEqual(self.volume_type_name, volume_type.name)
660 self.assertTrue(volume_type.public)
661 self.assertIsNone(volume_type.qos_spec)
663 encryption = volume_type.encryption
664 self.assertIsNotNone(encryption)
665 self.assertIsNone(encryption.cipher)
666 self.assertEqual('front-end', encryption.control_location)
667 self.assertIsNone(encryption.key_size)
668 self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
670 self.assertEqual(volume_type.id, encryption.volume_type_id)
673 class CreateStackFlavorTests(OSIntegrationTestCase):
675 Tests to ensure that floating IPs can be accessed via an
676 OpenStackFlavor object obtained from the OpenStackHeatStack instance
681 super(self.__class__, self).__start__()
683 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
685 self.heat_creds = self.admin_os_creds
686 self.heat_creds.project_name = self.admin_os_creds.project_name
688 self.heat_cli = heat_utils.heat_client(self.heat_creds)
689 self.stack_creator = None
691 self.heat_tmplt_path = pkg_resources.resource_filename(
692 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
694 stack_settings = StackSettings(
695 name=self.guid + '-stack',
696 template_path=self.heat_tmplt_path)
697 self.stack_creator = create_stack.OpenStackHeatStack(
698 self.heat_creds, stack_settings)
699 self.created_stack = self.stack_creator.create()
700 self.assertIsNotNone(self.created_stack)
704 Cleans the stack and downloaded stack file
706 if self.stack_creator:
708 self.stack_creator.clean()
712 super(self.__class__, self).__clean__()
714 def test_retrieve_flavor_creator(self):
716 Tests the creation of an OpenStack stack from Heat template file and
717 the retrieval of an OpenStackVolume creator/state machine instance
719 flavor_creators = self.stack_creator.get_flavor_creators()
720 self.assertEqual(1, len(flavor_creators))
722 creator = flavor_creators[0]
723 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
724 self.assertEqual(1024, creator.get_flavor().ram)
725 self.assertEqual(200, creator.get_flavor().disk)
726 self.assertEqual(8, creator.get_flavor().vcpus)
727 self.assertEqual(0, creator.get_flavor().ephemeral)
728 self.assertIsNone(creator.get_flavor().swap)
729 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
730 self.assertTrue(creator.get_flavor().is_public)
733 class CreateStackKeypairTests(OSIntegrationTestCase):
735 Tests to ensure that floating IPs can be accessed via an
736 OpenStackKeypair object obtained from the OpenStackHeatStack instance
741 super(self.__class__, self).__start__()
743 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
745 self.heat_creds = self.admin_os_creds
746 self.heat_creds.project_name = self.admin_os_creds.project_name
748 self.heat_cli = heat_utils.heat_client(self.heat_creds)
749 self.nova = nova_utils.nova_client(self.heat_creds)
750 self.stack_creator = None
752 self.keypair_name = self.guid + '-kp'
755 'keypair_name': self.keypair_name}
757 self.heat_tmplt_path = pkg_resources.resource_filename(
758 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
760 stack_settings = StackSettings(
761 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
762 template_path=self.heat_tmplt_path,
763 env_values=self.env_values)
764 self.stack_creator = create_stack.OpenStackHeatStack(
765 self.heat_creds, stack_settings)
766 self.created_stack = self.stack_creator.create()
767 self.assertIsNotNone(self.created_stack)
769 self.keypair_creators = list()
773 Cleans the stack and downloaded stack file
775 if self.stack_creator:
777 self.stack_creator.clean()
780 for keypair_creator in self.keypair_creators:
782 keypair_creator.clean()
786 super(self.__class__, self).__clean__()
788 def test_retrieve_keypair_creator(self):
790 Tests the creation of an OpenStack stack from Heat template file and
791 the retrieval of an OpenStackKeypair creator/state machine instance
793 self.kp_creators = self.stack_creator.get_keypair_creators(
795 self.assertEqual(1, len(self.kp_creators))
797 self.keypair_creator = self.kp_creators[0]
799 self.assertEqual(self.keypair_name,
800 self.keypair_creator.get_keypair().name)
801 self.assertIsNotNone(
802 self.keypair_creator.keypair_settings.private_filepath)
804 private_file_contents = file_utils.read_file(
805 self.keypair_creator.keypair_settings.private_filepath)
806 self.assertTrue(private_file_contents.startswith(
807 '-----BEGIN RSA PRIVATE KEY-----'))
809 keypair = nova_utils.get_keypair_by_id(
810 self.nova, self.keypair_creator.get_keypair().id)
811 self.assertIsNotNone(keypair)
812 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
815 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
817 Tests for the OpenStackHeatStack class to ensure it returns an
818 OpenStackSecurityGroup object
823 Instantiates the CreateStack object that is responsible for downloading
824 and creating an OS stack file within OpenStack
826 super(self.__class__, self).__start__()
828 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
830 self.heat_creds = self.admin_os_creds
831 self.heat_creds.project_name = self.admin_os_creds.project_name
833 self.heat_cli = heat_utils.heat_client(self.heat_creds)
834 self.nova = nova_utils.nova_client(self.heat_creds)
835 self.stack_creator = None
837 self.security_group_name = self.guid + '-sec-grp'
840 'security_group_name': self.security_group_name}
842 self.heat_tmplt_path = pkg_resources.resource_filename(
843 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
845 stack_settings = StackSettings(
846 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
847 template_path=self.heat_tmplt_path,
848 env_values=self.env_values)
849 self.stack_creator = create_stack.OpenStackHeatStack(
850 self.heat_creds, stack_settings)
851 self.created_stack = self.stack_creator.create()
852 self.assertIsNotNone(self.created_stack)
856 Cleans the stack and downloaded stack file
858 if self.stack_creator:
860 self.stack_creator.clean()
864 super(self.__class__, self).__clean__()
866 def test_retrieve_security_group_creator(self):
868 Tests the creation of an OpenStack stack from Heat template file and
869 the retrieval of an OpenStackSecurityGroup creator/state machine
872 sec_grp_creators = self.stack_creator.get_security_group_creators()
873 self.assertEqual(1, len(sec_grp_creators))
875 creator = sec_grp_creators[0]
876 sec_grp = creator.get_security_group()
878 self.assertEqual(self.security_group_name, sec_grp.name)
879 self.assertEqual('Test description', sec_grp.description)
880 self.assertEqual(2, len(sec_grp.rules))
883 has_icmp_rule = False
885 for rule in sec_grp.rules:
886 if (rule.security_group_id == sec_grp.id
887 and rule.direction == 'egress'
888 and rule.ethertype == 'IPv4'
889 and rule.port_range_min == 22
890 and rule.port_range_max == 22
891 and rule.protocol == 'tcp'
892 and rule.remote_group_id is None
893 and rule.remote_ip_prefix == '0.0.0.0/0'):
895 if (rule.security_group_id == sec_grp.id
896 and rule.direction == 'ingress'
897 and rule.ethertype == 'IPv4'
898 and rule.port_range_min is None
899 and rule.port_range_max is None
900 and rule.protocol == 'icmp'
901 and rule.remote_group_id is None
902 and rule.remote_ip_prefix == '0.0.0.0/0'):
905 self.assertTrue(has_ssh_rule)
906 self.assertTrue(has_icmp_rule)
909 class CreateStackNegativeTests(OSIntegrationTestCase):
911 Negative test cases for the OpenStackHeatStack class with poor
917 super(self.__class__, self).__start__()
919 self.heat_creds = self.admin_os_creds
920 self.heat_creds.project_name = self.admin_os_creds.project_name
922 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
923 self.stack_creator = None
924 self.heat_tmplt_path = pkg_resources.resource_filename(
925 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
928 if self.stack_creator:
929 self.stack_creator.clean()
930 super(self.__class__, self).__clean__()
932 def test_missing_dependencies(self):
934 Expect an StackCreationError when the stack file does not exist
936 stack_settings = StackSettings(name=self.stack_name,
937 template_path=self.heat_tmplt_path)
938 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
940 with self.assertRaises(HTTPBadRequest):
941 self.stack_creator.create()
943 def test_bad_stack_file(self):
945 Expect an StackCreationError when the stack file does not exist
947 stack_settings = StackSettings(name=self.stack_name,
949 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
951 with self.assertRaises(IOError):
952 self.stack_creator.create()
955 class CreateStackFailureTests(OSIntegrationTestCase):
957 Tests for the OpenStackHeatStack class defined in create_stack.py for
958 when failures occur. Failures are being triggered by allocating 1 million
964 super(self.__class__, self).__start__()
966 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
968 self.heat_creds = self.admin_os_creds
969 self.heat_creds.project_name = self.admin_os_creds.project_name
971 self.heat_cli = heat_utils.heat_client(self.heat_creds)
972 self.stack_creator = None
974 self.tmp_file = file_utils.save_string_to_file(
975 ' ', str(uuid.uuid4()) + '-bad-image')
976 self.image_creator = OpenStackImage(
977 self.heat_creds, ImageSettings(
978 name=self.guid + 'image', image_file=self.tmp_file.name,
979 image_user='foo', img_format='qcow2'))
980 self.image_creator.create()
983 self.flavor_creator = OpenStackFlavor(
985 FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10,
987 self.flavor_creator.create()
989 self.network_name = self.guid + '-net'
990 self.subnet_name = self.guid + '-subnet'
991 self.vm_inst_name = self.guid + '-inst'
994 'image_name': self.image_creator.image_settings.name,
995 'flavor_name': self.flavor_creator.flavor_settings.name,
996 'net_name': self.network_name,
997 'subnet_name': self.subnet_name,
998 'inst_name': self.vm_inst_name}
1000 self.heat_tmplt_path = pkg_resources.resource_filename(
1001 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1005 Cleans the stack and downloaded stack file
1007 if self.stack_creator:
1009 self.stack_creator.clean()
1013 if self.image_creator:
1015 self.image_creator.clean()
1019 if self.flavor_creator:
1021 self.flavor_creator.clean()
1027 os.remove(self.tmp_file.name)
1031 super(self.__class__, self).__clean__()
1033 def test_stack_failure(self):
1035 Tests the creation of an OpenStack stack from Heat template file that
1036 should always fail due to too many CPU cores
1039 # Set the default stack settings, then set any custom parameters sent
1041 stack_settings = StackSettings(
1042 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1043 template_path=self.heat_tmplt_path,
1044 env_values=self.env_values)
1045 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
1048 with self.assertRaises(StackError):
1050 self.stack_creator.create()
1052 resources = heat_utils.get_resources(
1053 self.heat_cli, self.stack_creator.get_stack())
1056 for resource in resources:
1057 if resource.status == create_stack.STATUS_CREATE_COMPLETE:
1059 self.assertTrue(found)