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 encryption = volume_type.encryption
667 self.assertIsNotNone(encryption)
668 self.assertIsNone(encryption.cipher)
669 self.assertEqual('front-end', encryption.control_location)
670 self.assertIsNone(encryption.key_size)
671 self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
673 self.assertEqual(volume_type.id, encryption.volume_type_id)
676 class CreateStackFlavorTests(OSIntegrationTestCase):
678 Tests to ensure that floating IPs can be accessed via an
679 OpenStackFlavor object obtained from the OpenStackHeatStack instance
684 super(self.__class__, self).__start__()
686 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
688 self.heat_creds = self.admin_os_creds
689 self.heat_creds.project_name = self.admin_os_creds.project_name
691 self.heat_cli = heat_utils.heat_client(self.heat_creds)
692 self.stack_creator = None
694 self.heat_tmplt_path = pkg_resources.resource_filename(
695 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
697 stack_settings = StackConfig(
698 name=self.guid + '-stack',
699 template_path=self.heat_tmplt_path)
700 self.stack_creator = OpenStackHeatStack(
701 self.heat_creds, stack_settings)
702 self.created_stack = self.stack_creator.create()
703 self.assertIsNotNone(self.created_stack)
707 Cleans the stack and downloaded stack file
709 if self.stack_creator:
711 self.stack_creator.clean()
715 super(self.__class__, self).__clean__()
717 def test_retrieve_flavor_creator(self):
719 Tests the creation of an OpenStack stack from Heat template file and
720 the retrieval of an OpenStackVolume creator/state machine instance
722 flavor_creators = self.stack_creator.get_flavor_creators()
723 self.assertEqual(1, len(flavor_creators))
725 creator = flavor_creators[0]
726 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
727 self.assertEqual(1024, creator.get_flavor().ram)
728 self.assertEqual(200, creator.get_flavor().disk)
729 self.assertEqual(8, creator.get_flavor().vcpus)
730 self.assertEqual(0, creator.get_flavor().ephemeral)
731 self.assertIsNone(creator.get_flavor().swap)
732 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
733 self.assertTrue(creator.get_flavor().is_public)
736 class CreateStackKeypairTests(OSIntegrationTestCase):
738 Tests to ensure that floating IPs can be accessed via an
739 OpenStackKeypair object obtained from the OpenStackHeatStack instance
744 super(self.__class__, self).__start__()
746 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
748 self.heat_creds = self.admin_os_creds
749 self.heat_creds.project_name = self.admin_os_creds.project_name
751 self.heat_cli = heat_utils.heat_client(self.heat_creds)
752 self.nova = nova_utils.nova_client(self.heat_creds)
753 self.stack_creator = None
755 self.keypair_name = self.guid + '-kp'
758 'keypair_name': self.keypair_name}
760 self.heat_tmplt_path = pkg_resources.resource_filename(
761 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
763 stack_settings = StackConfig(
764 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
765 template_path=self.heat_tmplt_path,
766 env_values=self.env_values)
767 self.stack_creator = OpenStackHeatStack(
768 self.heat_creds, stack_settings)
769 self.created_stack = self.stack_creator.create()
770 self.assertIsNotNone(self.created_stack)
772 self.keypair_creators = list()
776 Cleans the stack and downloaded stack file
778 if self.stack_creator:
780 self.stack_creator.clean()
783 for keypair_creator in self.keypair_creators:
785 keypair_creator.clean()
789 super(self.__class__, self).__clean__()
791 def test_retrieve_keypair_creator(self):
793 Tests the creation of an OpenStack stack from Heat template file and
794 the retrieval of an OpenStackKeypair creator/state machine instance
796 self.kp_creators = self.stack_creator.get_keypair_creators(
798 self.assertEqual(1, len(self.kp_creators))
800 self.keypair_creator = self.kp_creators[0]
802 self.assertEqual(self.keypair_name,
803 self.keypair_creator.get_keypair().name)
804 self.assertIsNotNone(
805 self.keypair_creator.keypair_settings.private_filepath)
807 private_file_contents = file_utils.read_file(
808 self.keypair_creator.keypair_settings.private_filepath)
809 self.assertTrue(private_file_contents.startswith(
810 '-----BEGIN RSA PRIVATE KEY-----'))
812 keypair = nova_utils.get_keypair_by_id(
813 self.nova, self.keypair_creator.get_keypair().id)
814 self.assertIsNotNone(keypair)
815 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
818 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
820 Tests for the OpenStackHeatStack class to ensure it returns an
821 OpenStackSecurityGroup object
826 Instantiates the CreateStack object that is responsible for downloading
827 and creating an OS stack file within OpenStack
829 super(self.__class__, self).__start__()
831 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
833 self.heat_creds = self.admin_os_creds
834 self.heat_creds.project_name = self.admin_os_creds.project_name
836 self.heat_cli = heat_utils.heat_client(self.heat_creds)
837 self.nova = nova_utils.nova_client(self.heat_creds)
838 self.stack_creator = None
840 self.security_group_name = self.guid + '-sec-grp'
843 'security_group_name': self.security_group_name}
845 self.heat_tmplt_path = pkg_resources.resource_filename(
846 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
848 stack_settings = StackConfig(
849 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
850 template_path=self.heat_tmplt_path,
851 env_values=self.env_values)
852 self.stack_creator = OpenStackHeatStack(
853 self.heat_creds, stack_settings)
854 self.created_stack = self.stack_creator.create()
855 self.assertIsNotNone(self.created_stack)
859 Cleans the stack and downloaded stack file
861 if self.stack_creator:
863 self.stack_creator.clean()
867 super(self.__class__, self).__clean__()
869 def test_retrieve_security_group_creator(self):
871 Tests the creation of an OpenStack stack from Heat template file and
872 the retrieval of an OpenStackSecurityGroup creator/state machine
875 sec_grp_creators = self.stack_creator.get_security_group_creators()
876 self.assertEqual(1, len(sec_grp_creators))
878 creator = sec_grp_creators[0]
879 sec_grp = creator.get_security_group()
881 self.assertEqual(self.security_group_name, sec_grp.name)
882 self.assertEqual('Test description', sec_grp.description)
883 self.assertEqual(2, len(sec_grp.rules))
886 has_icmp_rule = False
888 for rule in sec_grp.rules:
889 if (rule.security_group_id == sec_grp.id
890 and rule.direction == 'egress'
891 and rule.ethertype == 'IPv4'
892 and rule.port_range_min == 22
893 and rule.port_range_max == 22
894 and rule.protocol == 'tcp'
895 and rule.remote_group_id is None
896 and rule.remote_ip_prefix == '0.0.0.0/0'):
898 if (rule.security_group_id == sec_grp.id
899 and rule.direction == 'ingress'
900 and rule.ethertype == 'IPv4'
901 and rule.port_range_min is None
902 and rule.port_range_max is None
903 and rule.protocol == 'icmp'
904 and rule.remote_group_id is None
905 and rule.remote_ip_prefix == '0.0.0.0/0'):
908 self.assertTrue(has_ssh_rule)
909 self.assertTrue(has_icmp_rule)
912 class CreateStackNegativeTests(OSIntegrationTestCase):
914 Negative test cases for the OpenStackHeatStack class with poor
920 super(self.__class__, self).__start__()
922 self.heat_creds = self.admin_os_creds
923 self.heat_creds.project_name = self.admin_os_creds.project_name
925 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
926 self.stack_creator = None
927 self.heat_tmplt_path = pkg_resources.resource_filename(
928 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
931 if self.stack_creator:
932 self.stack_creator.clean()
933 super(self.__class__, self).__clean__()
935 def test_missing_dependencies(self):
937 Expect an StackCreationError when the stack file does not exist
939 stack_settings = StackConfig(name=self.stack_name,
940 template_path=self.heat_tmplt_path)
941 self.stack_creator = OpenStackHeatStack(
942 self.heat_creds, stack_settings)
943 with self.assertRaises(HTTPBadRequest):
944 self.stack_creator.create()
946 def test_bad_stack_file(self):
948 Expect an StackCreationError when the stack file does not exist
950 stack_settings = StackConfig(
951 name=self.stack_name, template_path='foo')
952 self.stack_creator = OpenStackHeatStack(
953 self.heat_creds, stack_settings)
954 with self.assertRaises(IOError):
955 self.stack_creator.create()
958 class CreateStackFailureTests(OSIntegrationTestCase):
960 Tests for the OpenStackHeatStack class defined in create_stack.py for
961 when failures occur. Failures are being triggered by allocating 1 million
967 super(self.__class__, self).__start__()
969 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
971 self.heat_creds = self.admin_os_creds
972 self.heat_creds.project_name = self.admin_os_creds.project_name
974 self.heat_cli = heat_utils.heat_client(self.heat_creds)
975 self.stack_creator = None
977 self.tmp_file = file_utils.save_string_to_file(
978 ' ', str(uuid.uuid4()) + '-bad-image')
979 self.image_creator = OpenStackImage(
980 self.heat_creds, ImageConfig(
981 name=self.guid + 'image', image_file=self.tmp_file.name,
982 image_user='foo', img_format='qcow2'))
983 self.image_creator.create()
986 self.flavor_creator = OpenStackFlavor(
989 name=self.guid + '-flavor-name', ram=256, disk=10,
991 self.flavor_creator.create()
993 self.network_name = self.guid + '-net'
994 self.subnet_name = self.guid + '-subnet'
995 self.vm_inst_name = self.guid + '-inst'
998 'image_name': self.image_creator.image_settings.name,
999 'flavor_name': self.flavor_creator.flavor_settings.name,
1000 'net_name': self.network_name,
1001 'subnet_name': self.subnet_name,
1002 'inst_name': self.vm_inst_name}
1004 self.heat_tmplt_path = pkg_resources.resource_filename(
1005 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1009 Cleans the stack and downloaded stack file
1011 if self.stack_creator:
1013 self.stack_creator.clean()
1017 if self.image_creator:
1019 self.image_creator.clean()
1023 if self.flavor_creator:
1025 self.flavor_creator.clean()
1031 os.remove(self.tmp_file.name)
1035 super(self.__class__, self).__clean__()
1037 def test_stack_failure(self):
1039 Tests the creation of an OpenStack stack from Heat template file that
1040 should always fail due to too many CPU cores
1043 # Set the default stack settings, then set any custom parameters sent
1045 stack_settings = StackConfig(
1046 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1047 template_path=self.heat_tmplt_path,
1048 env_values=self.env_values)
1049 self.stack_creator = OpenStackHeatStack(
1050 self.heat_creds, stack_settings)
1052 with self.assertRaises(StackError):
1054 self.stack_creator.create()
1056 resources = heat_utils.get_resources(
1057 self.heat_cli, self.stack_creator.get_stack())
1060 for resource in resources:
1061 if (resource.status ==
1062 snaps.config.stack.STATUS_CREATE_COMPLETE):
1064 self.assertTrue(found)