1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
19 from heatclient.exc import HTTPBadRequest
22 from snaps import file_utils
23 from snaps.config.flavor import FlavorConfig
24 from snaps.config.image import ImageConfig
25 from snaps.config.stack import StackConfigError, StackConfig
26 from snaps.openstack.create_flavor import OpenStackFlavor
27 from snaps.openstack.create_image import OpenStackImage
30 from urllib.request import URLError
32 from urllib2 import URLError
38 from snaps.openstack.create_stack import (
39 StackSettings, StackCreationError, StackError, OpenStackHeatStack)
40 from snaps.openstack.tests import openstack_tests, create_instance_tests
41 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
42 from snaps.openstack.utils import heat_utils, neutron_utils, nova_utils
44 __author__ = 'spisarski'
46 logger = logging.getLogger('create_stack_tests')
49 class StackSettingsUnitTests(unittest.TestCase):
51 Tests the construction of the StackSettings class
54 def test_no_params(self):
55 with self.assertRaises(StackConfigError):
58 def test_empty_config(self):
59 with self.assertRaises(StackConfigError):
60 StackSettings(**dict())
62 def test_name_only(self):
63 with self.assertRaises(StackConfigError):
64 StackSettings(name='foo')
66 def test_config_with_name_only(self):
67 with self.assertRaises(StackConfigError):
68 StackSettings(**{'name': 'foo'})
70 def test_config_minimum_template(self):
71 settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
72 self.assertEqual('stack', settings.name)
73 self.assertEqual('foo', settings.template)
74 self.assertIsNone(settings.template_path)
75 self.assertIsNone(settings.env_values)
76 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
77 settings.stack_create_timeout)
79 def test_config_minimum_template_path(self):
80 settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
81 self.assertEqual('stack', settings.name)
82 self.assertIsNone(settings.template)
83 self.assertEqual('foo', settings.template_path)
84 self.assertIsNone(settings.env_values)
85 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
86 settings.stack_create_timeout)
88 def test_minimum_template(self):
89 settings = StackSettings(name='stack', template='foo')
90 self.assertEqual('stack', settings.name)
91 self.assertEqual('foo', settings.template)
92 self.assertIsNone(settings.template_path)
93 self.assertIsNone(settings.env_values)
94 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
95 settings.stack_create_timeout)
97 def test_minimum_template_path(self):
98 settings = StackSettings(name='stack', template_path='foo')
99 self.assertEqual('stack', settings.name)
100 self.assertEqual('foo', settings.template_path)
101 self.assertIsNone(settings.template)
102 self.assertIsNone(settings.env_values)
103 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
104 settings.stack_create_timeout)
107 env_values = {'foo': 'bar'}
108 settings = StackSettings(name='stack', template='bar',
109 template_path='foo', env_values=env_values,
110 stack_create_timeout=999)
111 self.assertEqual('stack', settings.name)
112 self.assertEqual('bar', settings.template)
113 self.assertEqual('foo', settings.template_path)
114 self.assertEqual(env_values, settings.env_values)
115 self.assertEqual(999, settings.stack_create_timeout)
117 def test_config_all(self):
118 env_values = {'foo': 'bar'}
119 settings = StackSettings(
120 **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
121 'env_values': env_values, 'stack_create_timeout': 999})
122 self.assertEqual('stack', settings.name)
123 self.assertEqual('bar', settings.template)
124 self.assertEqual('foo', settings.template_path)
125 self.assertEqual(env_values, settings.env_values)
126 self.assertEqual(999, settings.stack_create_timeout)
129 class CreateStackSuccessTests(OSIntegrationTestCase):
131 Tests for the OpenStackHeatStack class defined in create_stack.py
136 super(self.__class__, self).__start__()
138 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
140 self.heat_creds = self.admin_os_creds
141 self.heat_creds.project_name = self.admin_os_creds.project_name
143 self.heat_cli = heat_utils.heat_client(self.heat_creds)
144 self.stack_creator = None
146 self.image_creator = OpenStackImage(
147 self.heat_creds, openstack_tests.cirros_image_settings(
148 name=self.guid + '-image',
149 image_metadata=self.image_metadata))
150 self.image_creator.create()
153 self.flavor_creator = OpenStackFlavor(
156 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
157 self.flavor_creator.create()
159 self.network_name = self.guid + '-net'
160 self.subnet_name = self.guid + '-subnet'
161 self.vm_inst_name = self.guid + '-inst'
164 'image_name': self.image_creator.image_settings.name,
165 'flavor_name': self.flavor_creator.flavor_settings.name,
166 'net_name': self.network_name,
167 'subnet_name': self.subnet_name,
168 'inst_name': self.vm_inst_name}
170 self.heat_tmplt_path = pkg_resources.resource_filename(
171 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
175 Cleans the stack and downloaded stack file
177 if self.stack_creator:
179 self.stack_creator.clean()
183 if self.image_creator:
185 self.image_creator.clean()
189 if self.flavor_creator:
191 self.flavor_creator.clean()
195 super(self.__class__, self).__clean__()
197 def test_create_stack_template_file(self):
199 Tests the creation of an OpenStack stack from Heat template file.
202 # Set the default stack settings, then set any custom parameters sent
204 stack_settings = StackConfig(
205 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
206 template_path=self.heat_tmplt_path,
207 env_values=self.env_values)
208 self.stack_creator = OpenStackHeatStack(
209 self.heat_creds, stack_settings)
210 created_stack = self.stack_creator.create()
211 self.assertIsNotNone(created_stack)
213 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
215 self.assertIsNotNone(retrieved_stack)
216 self.assertEqual(created_stack.name, retrieved_stack.name)
217 self.assertEqual(created_stack.id, retrieved_stack.id)
218 self.assertEqual(0, len(self.stack_creator.get_outputs()))
220 def test_create_stack_short_timeout(self):
222 Tests the creation of an OpenStack stack from Heat template file.
225 # Set the default stack settings, then set any custom parameters sent
227 stack_settings = StackConfig(
228 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
229 template_path=self.heat_tmplt_path,
230 env_values=self.env_values, stack_create_timeout=0)
232 self.stack_creator = OpenStackHeatStack(
233 self.heat_creds, stack_settings)
234 with self.assertRaises(StackCreationError):
235 self.stack_creator.create()
237 def test_create_stack_template_dict(self):
239 Tests the creation of an OpenStack stack from a heat dict() object.
242 # Set the default stack settings, then set any custom parameters sent
244 template_dict = heat_utils.parse_heat_template_str(
245 file_utils.read_file(self.heat_tmplt_path))
246 stack_settings = StackConfig(
247 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
248 template=template_dict,
249 env_values=self.env_values)
250 self.stack_creator = OpenStackHeatStack(
251 self.heat_creds, stack_settings)
252 created_stack = self.stack_creator.create()
253 self.assertIsNotNone(created_stack)
255 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
257 self.assertIsNotNone(retrieved_stack)
258 self.assertEqual(created_stack.name, retrieved_stack.name)
259 self.assertEqual(created_stack.id, retrieved_stack.id)
260 self.assertEqual(0, len(self.stack_creator.get_outputs()))
262 def test_create_delete_stack(self):
264 Tests the creation then deletion of an OpenStack stack to ensure
265 clean() does not raise an Exception.
268 template_dict = heat_utils.parse_heat_template_str(
269 file_utils.read_file(self.heat_tmplt_path))
270 stack_settings = StackConfig(
271 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
272 template=template_dict,
273 env_values=self.env_values)
274 self.stack_creator = OpenStackHeatStack(
275 self.heat_creds, stack_settings)
276 created_stack = self.stack_creator.create()
277 self.assertIsNotNone(created_stack)
279 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
281 self.assertIsNotNone(retrieved_stack)
282 self.assertEqual(created_stack.name, retrieved_stack.name)
283 self.assertEqual(created_stack.id, retrieved_stack.id)
284 self.assertEqual(0, len(self.stack_creator.get_outputs()))
285 self.assertEqual(snaps.config.stack.STATUS_CREATE_COMPLETE,
286 self.stack_creator.get_status())
288 # Delete Stack manually
289 heat_utils.delete_stack(self.heat_cli, created_stack)
291 end_time = time.time() + 90
293 while time.time() < end_time:
294 status = heat_utils.get_stack_status(self.heat_cli,
296 if status == snaps.config.stack.STATUS_DELETE_COMPLETE:
300 self.assertTrue(deleted)
302 # Must not throw an exception when attempting to cleanup non-existent
304 self.stack_creator.clean()
305 self.assertIsNone(self.stack_creator.get_stack())
307 def test_create_same_stack(self):
309 Tests the creation of an OpenStack stack when the stack already exists.
312 template_dict = heat_utils.parse_heat_template_str(
313 file_utils.read_file(self.heat_tmplt_path))
314 stack_settings = StackConfig(
315 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
316 template=template_dict,
317 env_values=self.env_values)
318 self.stack_creator = OpenStackHeatStack(
319 self.heat_creds, stack_settings)
320 created_stack1 = self.stack_creator.create()
322 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
324 self.assertIsNotNone(retrieved_stack)
325 self.assertEqual(created_stack1.name, retrieved_stack.name)
326 self.assertEqual(created_stack1.id, retrieved_stack.id)
327 self.assertEqual(0, len(self.stack_creator.get_outputs()))
329 # Should be retrieving the instance data
330 stack_creator2 = OpenStackHeatStack(self.heat_creds, stack_settings)
331 stack2 = stack_creator2.create()
332 self.assertEqual(created_stack1.id, stack2.id)
334 def test_retrieve_network_creators(self):
336 Tests the creation of an OpenStack stack from Heat template file and
337 the retrieval of the network creator.
339 stack_settings = StackConfig(
340 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
341 template_path=self.heat_tmplt_path,
342 env_values=self.env_values)
343 self.stack_creator = OpenStackHeatStack(
344 self.heat_creds, stack_settings)
345 created_stack = self.stack_creator.create()
346 self.assertIsNotNone(created_stack)
348 net_creators = self.stack_creator.get_network_creators()
349 self.assertIsNotNone(net_creators)
350 self.assertEqual(1, len(net_creators))
351 self.assertEqual(self.network_name, net_creators[0].get_network().name)
353 neutron = neutron_utils.neutron_client(self.os_creds)
354 net_by_name = neutron_utils.get_network(
355 neutron, network_name=net_creators[0].get_network().name)
356 self.assertEqual(net_creators[0].get_network(), net_by_name)
357 self.assertIsNotNone(neutron_utils.get_network_by_id(
358 neutron, net_creators[0].get_network().id))
360 self.assertEqual(1, len(net_creators[0].get_network().subnets))
361 subnet = net_creators[0].get_network().subnets[0]
362 subnet_by_name = neutron_utils.get_subnet(
363 neutron, subnet_name=subnet.name)
364 self.assertEqual(subnet, subnet_by_name)
366 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
367 self.assertIsNotNone(subnet_by_id)
368 self.assertEqual(subnet_by_name, subnet_by_id)
370 def test_retrieve_vm_inst_creators(self):
372 Tests the creation of an OpenStack stack from Heat template file and
373 the retrieval of the network creator.
375 stack_settings = StackConfig(
376 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
377 template_path=self.heat_tmplt_path,
378 env_values=self.env_values)
379 self.stack_creator = OpenStackHeatStack(
380 self.heat_creds, stack_settings)
381 created_stack = self.stack_creator.create()
382 self.assertIsNotNone(created_stack)
384 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
385 self.assertIsNotNone(vm_inst_creators)
386 self.assertEqual(1, len(vm_inst_creators))
387 self.assertEqual(self.vm_inst_name,
388 vm_inst_creators[0].get_vm_inst().name)
390 nova = nova_utils.nova_client(self.admin_os_creds)
391 vm_inst_by_name = nova_utils.get_server(
392 nova, server_name=vm_inst_creators[0].get_vm_inst().name)
393 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
394 self.assertIsNotNone(nova_utils.get_server_object_by_id(
395 nova, vm_inst_creators[0].get_vm_inst().id))
398 class CreateStackFloatingIpTests(OSIntegrationTestCase):
400 Tests to ensure that floating IPs can be accessed via an
401 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
406 super(self.__class__, self).__start__()
408 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
410 self.heat_creds = self.admin_os_creds
411 self.heat_creds.project_name = self.admin_os_creds.project_name
413 self.heat_cli = heat_utils.heat_client(self.heat_creds)
414 self.stack_creator = None
416 self.image_creator = OpenStackImage(
417 self.heat_creds, openstack_tests.cirros_image_settings(
418 name=self.guid + '-image',
419 image_metadata=self.image_metadata))
420 self.image_creator.create()
422 self.network_name = self.guid + '-net'
423 self.subnet_name = self.guid + '-subnet'
424 self.flavor1_name = self.guid + '-flavor1'
425 self.flavor2_name = self.guid + '-flavor2'
426 self.sec_grp_name = self.guid + '-sec_grp'
427 self.vm_inst1_name = self.guid + '-inst1'
428 self.vm_inst2_name = self.guid + '-inst2'
429 self.keypair_name = self.guid + '-kp'
432 'image1_name': self.image_creator.image_settings.name,
433 'image2_name': self.image_creator.image_settings.name,
434 'flavor1_name': self.flavor1_name,
435 'flavor2_name': self.flavor2_name,
436 'net_name': self.network_name,
437 'subnet_name': self.subnet_name,
438 'inst1_name': self.vm_inst1_name,
439 'inst2_name': self.vm_inst2_name,
440 'keypair_name': self.keypair_name,
441 'external_net_name': self.ext_net_name,
442 'security_group_name': self.sec_grp_name}
444 self.heat_tmplt_path = pkg_resources.resource_filename(
445 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
447 self.vm_inst_creators = list()
451 Cleans the stack and downloaded stack file
453 if self.stack_creator:
455 self.stack_creator.clean()
459 if self.image_creator:
461 self.image_creator.clean()
465 for vm_inst_creator in self.vm_inst_creators:
467 keypair_settings = vm_inst_creator.keypair_settings
468 if keypair_settings and keypair_settings.private_filepath:
469 expanded_path = os.path.expanduser(
470 keypair_settings.private_filepath)
471 os.chmod(expanded_path, 0o755)
472 os.remove(expanded_path)
476 super(self.__class__, self).__clean__()
478 def test_connect_via_ssh_heat_vm(self):
480 Tests the creation of an OpenStack stack from Heat template file and
481 the retrieval of two VM instance creators and attempt to connect via
482 SSH to the first one with a floating IP.
484 stack_settings = StackConfig(
485 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
486 template_path=self.heat_tmplt_path,
487 env_values=self.env_values)
488 self.stack_creator = OpenStackHeatStack(
489 self.heat_creds, stack_settings,
490 [self.image_creator.image_settings])
491 created_stack = self.stack_creator.create()
492 self.assertIsNotNone(created_stack)
494 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
495 heat_keypair_option='private_key')
496 self.assertIsNotNone(self.vm_inst_creators)
497 self.assertEqual(2, len(self.vm_inst_creators))
499 for vm_inst_creator in self.vm_inst_creators:
500 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
502 create_instance_tests.validate_ssh_client(vm_inst_creator))
504 vm_settings = vm_inst_creator.instance_settings
505 self.assertEqual(0, len(vm_settings.floating_ip_settings))
508 class CreateStackRouterTests(OSIntegrationTestCase):
510 Tests for the CreateStack class defined in create_stack.py where the
511 target is a Network, Subnet, and Router
516 Instantiates the CreateStack object that is responsible for downloading
517 and creating an OS stack file within OpenStack
519 super(self.__class__, self).__start__()
521 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
523 self.heat_creds = self.admin_os_creds
524 self.heat_creds.project_name = self.admin_os_creds.project_name
526 self.heat_cli = heat_utils.heat_client(self.heat_creds)
527 self.neutron = neutron_utils.neutron_client(self.os_creds)
528 self.stack_creator = None
530 self.net_name = self.guid + '-net'
531 self.subnet_name = self.guid + '-subnet'
532 self.router_name = self.guid + '-router'
535 'net_name': self.net_name,
536 'subnet_name': self.subnet_name,
537 'router_name': self.router_name,
538 'external_net_name': self.ext_net_name}
540 self.heat_tmplt_path = pkg_resources.resource_filename(
541 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
543 stack_settings = StackConfig(
544 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
545 template_path=self.heat_tmplt_path,
546 env_values=self.env_values)
547 self.stack_creator = OpenStackHeatStack(
548 self.heat_creds, stack_settings)
549 self.created_stack = self.stack_creator.create()
550 self.assertIsNotNone(self.created_stack)
554 Cleans the stack and downloaded stack file
556 if self.stack_creator:
558 self.stack_creator.clean()
562 super(self.__class__, self).__clean__()
564 def test_retrieve_router_creator(self):
566 Tests the creation of an OpenStack stack from Heat template file and
567 the retrieval of an OpenStackRouter creator/state machine instance
569 router_creators = self.stack_creator.get_router_creators()
570 self.assertEqual(1, len(router_creators))
572 creator = router_creators[0]
573 self.assertEqual(self.router_name, creator.router_settings.name)
575 router = creator.get_router()
577 ext_net = neutron_utils.get_network(
578 self.neutron, network_name=self.ext_net_name)
579 self.assertEqual(ext_net.id, router.external_network_id)
582 class CreateStackVolumeTests(OSIntegrationTestCase):
584 Tests to ensure that floating IPs can be accessed via an
585 OpenStackVolume object obtained from the OpenStackHeatStack instance
590 super(self.__class__, self).__start__()
592 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
594 self.heat_creds = self.admin_os_creds
595 self.heat_creds.project_name = self.admin_os_creds.project_name
597 self.heat_cli = heat_utils.heat_client(self.heat_creds)
598 self.stack_creator = None
600 self.volume_name = self.guid + '-volume'
601 self.volume_type_name = self.guid + '-volume-type'
604 'volume_name': self.volume_name,
605 'volume_type_name': self.volume_type_name}
607 self.heat_tmplt_path = pkg_resources.resource_filename(
608 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
610 stack_settings = StackConfig(
611 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
612 template_path=self.heat_tmplt_path,
613 env_values=self.env_values)
614 self.stack_creator = OpenStackHeatStack(
615 self.heat_creds, stack_settings)
616 self.created_stack = self.stack_creator.create()
617 self.assertIsNotNone(self.created_stack)
621 Cleans the stack and downloaded stack file
623 if self.stack_creator:
625 self.stack_creator.clean()
629 super(self.__class__, self).__clean__()
631 def test_retrieve_volume_creator(self):
633 Tests the creation of an OpenStack stack from Heat template file and
634 the retrieval of an OpenStackVolume creator/state machine instance
636 volume_creators = self.stack_creator.get_volume_creators()
637 self.assertEqual(1, len(volume_creators))
639 creator = volume_creators[0]
640 self.assertEqual(self.volume_name, creator.volume_settings.name)
641 self.assertEqual(self.volume_name, creator.get_volume().name)
642 self.assertEqual(self.volume_type_name,
643 creator.volume_settings.type_name)
644 self.assertEqual(self.volume_type_name, creator.get_volume().type)
645 self.assertEqual(1, creator.volume_settings.size)
646 self.assertEqual(1, creator.get_volume().size)
648 def test_retrieve_volume_type_creator(self):
650 Tests the creation of an OpenStack stack from Heat template file and
651 the retrieval of an OpenStackVolume creator/state machine instance
653 volume_type_creators = self.stack_creator.get_volume_type_creators()
654 self.assertEqual(1, len(volume_type_creators))
656 creator = volume_type_creators[0]
657 self.assertIsNotNone(creator)
659 volume_type = creator.get_volume_type()
660 self.assertIsNotNone(volume_type)
662 self.assertEqual(self.volume_type_name, volume_type.name)
663 self.assertTrue(volume_type.public)
664 self.assertIsNone(volume_type.qos_spec)
666 # TODO - Add encryption back and find out why it broke in Pike
667 # encryption = volume_type.encryption
668 # self.assertIsNotNone(encryption)
669 # self.assertIsNone(encryption.cipher)
670 # self.assertEqual('front-end', encryption.control_location)
671 # self.assertIsNone(encryption.key_size)
672 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
673 # encryption.provider)
674 # self.assertEqual(volume_type.id, encryption.volume_type_id)
677 class CreateStackFlavorTests(OSIntegrationTestCase):
679 Tests to ensure that floating IPs can be accessed via an
680 OpenStackFlavor object obtained from the OpenStackHeatStack instance
685 super(self.__class__, self).__start__()
687 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
689 self.heat_creds = self.admin_os_creds
690 self.heat_creds.project_name = self.admin_os_creds.project_name
692 self.heat_cli = heat_utils.heat_client(self.heat_creds)
693 self.stack_creator = None
695 self.heat_tmplt_path = pkg_resources.resource_filename(
696 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
698 stack_settings = StackConfig(
699 name=self.guid + '-stack',
700 template_path=self.heat_tmplt_path)
701 self.stack_creator = OpenStackHeatStack(
702 self.heat_creds, stack_settings)
703 self.created_stack = self.stack_creator.create()
704 self.assertIsNotNone(self.created_stack)
708 Cleans the stack and downloaded stack file
710 if self.stack_creator:
712 self.stack_creator.clean()
716 super(self.__class__, self).__clean__()
718 def test_retrieve_flavor_creator(self):
720 Tests the creation of an OpenStack stack from Heat template file and
721 the retrieval of an OpenStackVolume creator/state machine instance
723 flavor_creators = self.stack_creator.get_flavor_creators()
724 self.assertEqual(1, len(flavor_creators))
726 creator = flavor_creators[0]
727 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
728 self.assertEqual(1024, creator.get_flavor().ram)
729 self.assertEqual(200, creator.get_flavor().disk)
730 self.assertEqual(8, creator.get_flavor().vcpus)
731 self.assertEqual(0, creator.get_flavor().ephemeral)
732 self.assertIsNone(creator.get_flavor().swap)
733 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
734 self.assertTrue(creator.get_flavor().is_public)
737 class CreateStackKeypairTests(OSIntegrationTestCase):
739 Tests to ensure that floating IPs can be accessed via an
740 OpenStackKeypair object obtained from the OpenStackHeatStack instance
745 super(self.__class__, self).__start__()
747 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
749 self.heat_creds = self.admin_os_creds
750 self.heat_creds.project_name = self.admin_os_creds.project_name
752 self.heat_cli = heat_utils.heat_client(self.heat_creds)
753 self.nova = nova_utils.nova_client(self.heat_creds)
754 self.stack_creator = None
756 self.keypair_name = self.guid + '-kp'
759 'keypair_name': self.keypair_name}
761 self.heat_tmplt_path = pkg_resources.resource_filename(
762 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
764 stack_settings = StackConfig(
765 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
766 template_path=self.heat_tmplt_path,
767 env_values=self.env_values)
768 self.stack_creator = OpenStackHeatStack(
769 self.heat_creds, stack_settings)
770 self.created_stack = self.stack_creator.create()
771 self.assertIsNotNone(self.created_stack)
773 self.keypair_creators = list()
777 Cleans the stack and downloaded stack file
779 if self.stack_creator:
781 self.stack_creator.clean()
784 for keypair_creator in self.keypair_creators:
786 keypair_creator.clean()
790 super(self.__class__, self).__clean__()
792 def test_retrieve_keypair_creator(self):
794 Tests the creation of an OpenStack stack from Heat template file and
795 the retrieval of an OpenStackKeypair creator/state machine instance
797 self.kp_creators = self.stack_creator.get_keypair_creators(
799 self.assertEqual(1, len(self.kp_creators))
801 self.keypair_creator = self.kp_creators[0]
803 self.assertEqual(self.keypair_name,
804 self.keypair_creator.get_keypair().name)
805 self.assertIsNotNone(
806 self.keypair_creator.keypair_settings.private_filepath)
808 private_file_contents = file_utils.read_file(
809 self.keypair_creator.keypair_settings.private_filepath)
810 self.assertTrue(private_file_contents.startswith(
811 '-----BEGIN RSA PRIVATE KEY-----'))
813 keypair = nova_utils.get_keypair_by_id(
814 self.nova, self.keypair_creator.get_keypair().id)
815 self.assertIsNotNone(keypair)
816 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
819 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
821 Tests for the OpenStackHeatStack class to ensure it returns an
822 OpenStackSecurityGroup object
827 Instantiates the CreateStack object that is responsible for downloading
828 and creating an OS stack file within OpenStack
830 super(self.__class__, self).__start__()
832 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
834 self.heat_creds = self.admin_os_creds
835 self.heat_creds.project_name = self.admin_os_creds.project_name
837 self.heat_cli = heat_utils.heat_client(self.heat_creds)
838 self.nova = nova_utils.nova_client(self.heat_creds)
839 self.stack_creator = None
841 self.security_group_name = self.guid + '-sec-grp'
844 'security_group_name': self.security_group_name}
846 self.heat_tmplt_path = pkg_resources.resource_filename(
847 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
849 stack_settings = StackConfig(
850 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
851 template_path=self.heat_tmplt_path,
852 env_values=self.env_values)
853 self.stack_creator = OpenStackHeatStack(
854 self.heat_creds, stack_settings)
855 self.created_stack = self.stack_creator.create()
856 self.assertIsNotNone(self.created_stack)
860 Cleans the stack and downloaded stack file
862 if self.stack_creator:
864 self.stack_creator.clean()
868 super(self.__class__, self).__clean__()
870 def test_retrieve_security_group_creator(self):
872 Tests the creation of an OpenStack stack from Heat template file and
873 the retrieval of an OpenStackSecurityGroup creator/state machine
876 sec_grp_creators = self.stack_creator.get_security_group_creators()
877 self.assertEqual(1, len(sec_grp_creators))
879 creator = sec_grp_creators[0]
880 sec_grp = creator.get_security_group()
882 self.assertEqual(self.security_group_name, sec_grp.name)
883 self.assertEqual('Test description', sec_grp.description)
884 self.assertEqual(2, len(sec_grp.rules))
887 has_icmp_rule = False
889 for rule in sec_grp.rules:
890 if (rule.security_group_id == sec_grp.id
891 and rule.direction == 'egress'
892 and rule.ethertype == 'IPv4'
893 and rule.port_range_min == 22
894 and rule.port_range_max == 22
895 and rule.protocol == 'tcp'
896 and rule.remote_group_id is None
897 and rule.remote_ip_prefix == '0.0.0.0/0'):
899 if (rule.security_group_id == sec_grp.id
900 and rule.direction == 'ingress'
901 and rule.ethertype == 'IPv4'
902 and rule.port_range_min is None
903 and rule.port_range_max is None
904 and rule.protocol == 'icmp'
905 and rule.remote_group_id is None
906 and rule.remote_ip_prefix == '0.0.0.0/0'):
909 self.assertTrue(has_ssh_rule)
910 self.assertTrue(has_icmp_rule)
913 class CreateStackNegativeTests(OSIntegrationTestCase):
915 Negative test cases for the OpenStackHeatStack class with poor
921 super(self.__class__, self).__start__()
923 self.heat_creds = self.admin_os_creds
924 self.heat_creds.project_name = self.admin_os_creds.project_name
926 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
927 self.stack_creator = None
928 self.heat_tmplt_path = pkg_resources.resource_filename(
929 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
932 if self.stack_creator:
933 self.stack_creator.clean()
934 super(self.__class__, self).__clean__()
936 def test_missing_dependencies(self):
938 Expect an StackCreationError when the stack file does not exist
940 stack_settings = StackConfig(name=self.stack_name,
941 template_path=self.heat_tmplt_path)
942 self.stack_creator = OpenStackHeatStack(
943 self.heat_creds, stack_settings)
944 with self.assertRaises(HTTPBadRequest):
945 self.stack_creator.create()
947 def test_bad_stack_file(self):
949 Expect an StackCreationError when the stack file does not exist
951 stack_settings = StackConfig(
952 name=self.stack_name, template_path='foo')
953 self.stack_creator = OpenStackHeatStack(
954 self.heat_creds, stack_settings)
955 with self.assertRaises(IOError):
956 self.stack_creator.create()
959 class CreateStackFailureTests(OSIntegrationTestCase):
961 Tests for the OpenStackHeatStack class defined in create_stack.py for
962 when failures occur. Failures are being triggered by allocating 1 million
968 super(self.__class__, self).__start__()
970 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
972 self.heat_creds = self.admin_os_creds
973 self.heat_creds.project_name = self.admin_os_creds.project_name
975 self.heat_cli = heat_utils.heat_client(self.heat_creds)
976 self.stack_creator = None
978 self.tmp_file = file_utils.save_string_to_file(
979 ' ', str(uuid.uuid4()) + '-bad-image')
980 self.image_creator = OpenStackImage(
981 self.heat_creds, ImageConfig(
982 name=self.guid + 'image', image_file=self.tmp_file.name,
983 image_user='foo', img_format='qcow2'))
984 self.image_creator.create()
987 self.flavor_creator = OpenStackFlavor(
990 name=self.guid + '-flavor-name', ram=256, disk=10,
992 self.flavor_creator.create()
994 self.network_name = self.guid + '-net'
995 self.subnet_name = self.guid + '-subnet'
996 self.vm_inst_name = self.guid + '-inst'
999 'image_name': self.image_creator.image_settings.name,
1000 'flavor_name': self.flavor_creator.flavor_settings.name,
1001 'net_name': self.network_name,
1002 'subnet_name': self.subnet_name,
1003 'inst_name': self.vm_inst_name}
1005 self.heat_tmplt_path = pkg_resources.resource_filename(
1006 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1010 Cleans the stack and downloaded stack file
1012 if self.stack_creator:
1014 self.stack_creator.clean()
1018 if self.image_creator:
1020 self.image_creator.clean()
1024 if self.flavor_creator:
1026 self.flavor_creator.clean()
1032 os.remove(self.tmp_file.name)
1036 super(self.__class__, self).__clean__()
1038 def test_stack_failure(self):
1040 Tests the creation of an OpenStack stack from Heat template file that
1041 should always fail due to too many CPU cores
1044 # Set the default stack settings, then set any custom parameters sent
1046 stack_settings = StackConfig(
1047 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1048 template_path=self.heat_tmplt_path,
1049 env_values=self.env_values)
1050 self.stack_creator = OpenStackHeatStack(
1051 self.heat_creds, stack_settings)
1053 with self.assertRaises(StackError):
1055 self.stack_creator.create()
1057 resources = heat_utils.get_resources(
1058 self.heat_cli, self.stack_creator.get_stack())
1061 for resource in resources:
1062 if (resource.status ==
1063 snaps.config.stack.STATUS_CREATE_COMPLETE):
1065 self.assertTrue(found)