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')
446 Cleans the stack and downloaded stack file
448 if self.stack_creator:
450 self.stack_creator.clean()
454 if self.image_creator:
456 self.image_creator.clean()
460 super(self.__class__, self).__clean__()
462 def test_connect_via_ssh_heat_vm(self):
464 Tests the creation of an OpenStack stack from Heat template file and
465 the retrieval of two VM instance creators and attempt to connect via
466 SSH to the first one with a floating IP.
468 stack_settings = StackSettings(
469 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
470 template_path=self.heat_tmplt_path,
471 env_values=self.env_values)
472 self.stack_creator = create_stack.OpenStackHeatStack(
473 self.heat_creds, stack_settings,
474 [self.image_creator.image_settings])
475 created_stack = self.stack_creator.create()
476 self.assertIsNotNone(created_stack)
478 vm_inst_creators = self.stack_creator.get_vm_inst_creators(
479 heat_keypair_option='private_key')
480 self.assertIsNotNone(vm_inst_creators)
481 self.assertEqual(2, len(vm_inst_creators))
483 for vm_inst_creator in vm_inst_creators:
484 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
486 create_instance_tests.validate_ssh_client(vm_inst_creator))
488 vm_settings = vm_inst_creator.instance_settings
489 self.assertEqual(0, len(vm_settings.floating_ip_settings))
492 class CreateStackRouterTests(OSIntegrationTestCase):
494 Tests for the CreateStack class defined in create_stack.py where the
495 target is a Network, Subnet, and Router
500 Instantiates the CreateStack object that is responsible for downloading
501 and creating an OS stack file within OpenStack
503 super(self.__class__, self).__start__()
505 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
507 self.heat_creds = self.admin_os_creds
508 self.heat_creds.project_name = self.admin_os_creds.project_name
510 self.heat_cli = heat_utils.heat_client(self.heat_creds)
511 self.neutron = neutron_utils.neutron_client(self.os_creds)
512 self.stack_creator = None
514 self.net_name = self.guid + '-net'
515 self.subnet_name = self.guid + '-subnet'
516 self.router_name = self.guid + '-router'
519 'net_name': self.net_name,
520 'subnet_name': self.subnet_name,
521 'router_name': self.router_name,
522 'external_net_name': self.ext_net_name}
524 self.heat_tmplt_path = pkg_resources.resource_filename(
525 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
527 stack_settings = StackSettings(
528 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
529 template_path=self.heat_tmplt_path,
530 env_values=self.env_values)
531 self.stack_creator = create_stack.OpenStackHeatStack(
532 self.heat_creds, stack_settings)
533 self.created_stack = self.stack_creator.create()
534 self.assertIsNotNone(self.created_stack)
538 Cleans the stack and downloaded stack file
540 if self.stack_creator:
542 self.stack_creator.clean()
546 super(self.__class__, self).__clean__()
548 def test_retrieve_router_creator(self):
550 Tests the creation of an OpenStack stack from Heat template file and
551 the retrieval of an OpenStackRouter creator/state machine instance
553 router_creators = self.stack_creator.get_router_creators()
554 self.assertEqual(1, len(router_creators))
556 creator = router_creators[0]
557 self.assertEqual(self.router_name, creator.router_settings.name)
559 router = creator.get_router()
561 ext_net = neutron_utils.get_network(
562 self.neutron, network_name=self.ext_net_name)
563 self.assertEqual(ext_net.id, router.external_network_id)
566 class CreateStackVolumeTests(OSIntegrationTestCase):
568 Tests to ensure that floating IPs can be accessed via an
569 OpenStackVolume object obtained from the OpenStackHeatStack instance
574 super(self.__class__, self).__start__()
576 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
578 self.heat_creds = self.admin_os_creds
579 self.heat_creds.project_name = self.admin_os_creds.project_name
581 self.heat_cli = heat_utils.heat_client(self.heat_creds)
582 self.stack_creator = None
584 self.volume_name = self.guid + '-volume'
585 self.volume_type_name = self.guid + '-volume-type'
588 'volume_name': self.volume_name,
589 'volume_type_name': self.volume_type_name}
591 self.heat_tmplt_path = pkg_resources.resource_filename(
592 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
594 stack_settings = StackSettings(
595 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
596 template_path=self.heat_tmplt_path,
597 env_values=self.env_values)
598 self.stack_creator = create_stack.OpenStackHeatStack(
599 self.heat_creds, stack_settings)
600 self.created_stack = self.stack_creator.create()
601 self.assertIsNotNone(self.created_stack)
605 Cleans the stack and downloaded stack file
607 if self.stack_creator:
609 self.stack_creator.clean()
613 super(self.__class__, self).__clean__()
615 def test_retrieve_volume_creator(self):
617 Tests the creation of an OpenStack stack from Heat template file and
618 the retrieval of an OpenStackVolume creator/state machine instance
620 volume_creators = self.stack_creator.get_volume_creators()
621 self.assertEqual(1, len(volume_creators))
623 creator = volume_creators[0]
624 self.assertEqual(self.volume_name, creator.volume_settings.name)
625 self.assertEqual(self.volume_name, creator.get_volume().name)
626 self.assertEqual(self.volume_type_name,
627 creator.volume_settings.type_name)
628 self.assertEqual(self.volume_type_name, creator.get_volume().type)
629 self.assertEqual(1, creator.volume_settings.size)
630 self.assertEqual(1, creator.get_volume().size)
632 def test_retrieve_volume_type_creator(self):
634 Tests the creation of an OpenStack stack from Heat template file and
635 the retrieval of an OpenStackVolume creator/state machine instance
637 volume_type_creators = self.stack_creator.get_volume_type_creators()
638 self.assertEqual(1, len(volume_type_creators))
640 creator = volume_type_creators[0]
641 self.assertIsNotNone(creator)
643 volume_type = creator.get_volume_type()
644 self.assertIsNotNone(volume_type)
646 self.assertEqual(self.volume_type_name, volume_type.name)
647 self.assertTrue(volume_type.public)
648 self.assertIsNone(volume_type.qos_spec)
650 encryption = volume_type.encryption
651 self.assertIsNotNone(encryption)
652 self.assertIsNone(encryption.cipher)
653 self.assertEqual('front-end', encryption.control_location)
654 self.assertIsNone(encryption.key_size)
655 self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
657 self.assertEqual(volume_type.id, encryption.volume_type_id)
660 class CreateStackFlavorTests(OSIntegrationTestCase):
662 Tests to ensure that floating IPs can be accessed via an
663 OpenStackFlavor object obtained from the OpenStackHeatStack instance
668 super(self.__class__, self).__start__()
670 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
672 self.heat_creds = self.admin_os_creds
673 self.heat_creds.project_name = self.admin_os_creds.project_name
675 self.heat_cli = heat_utils.heat_client(self.heat_creds)
676 self.stack_creator = None
678 self.heat_tmplt_path = pkg_resources.resource_filename(
679 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
681 stack_settings = StackSettings(
682 name=self.guid + '-stack',
683 template_path=self.heat_tmplt_path)
684 self.stack_creator = create_stack.OpenStackHeatStack(
685 self.heat_creds, stack_settings)
686 self.created_stack = self.stack_creator.create()
687 self.assertIsNotNone(self.created_stack)
691 Cleans the stack and downloaded stack file
693 if self.stack_creator:
695 self.stack_creator.clean()
699 super(self.__class__, self).__clean__()
701 def test_retrieve_flavor_creator(self):
703 Tests the creation of an OpenStack stack from Heat template file and
704 the retrieval of an OpenStackVolume creator/state machine instance
706 flavor_creators = self.stack_creator.get_flavor_creators()
707 self.assertEqual(1, len(flavor_creators))
709 creator = flavor_creators[0]
710 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
711 self.assertEqual(1024, creator.get_flavor().ram)
712 self.assertEqual(200, creator.get_flavor().disk)
713 self.assertEqual(8, creator.get_flavor().vcpus)
714 self.assertEqual(0, creator.get_flavor().ephemeral)
715 self.assertIsNone(creator.get_flavor().swap)
716 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
717 self.assertTrue(creator.get_flavor().is_public)
720 class CreateStackKeypairTests(OSIntegrationTestCase):
722 Tests to ensure that floating IPs can be accessed via an
723 OpenStackKeypair object obtained from the OpenStackHeatStack instance
728 super(self.__class__, self).__start__()
730 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
732 self.heat_creds = self.admin_os_creds
733 self.heat_creds.project_name = self.admin_os_creds.project_name
735 self.heat_cli = heat_utils.heat_client(self.heat_creds)
736 self.nova = nova_utils.nova_client(self.heat_creds)
737 self.stack_creator = None
739 self.keypair_name = self.guid + '-kp'
742 'keypair_name': self.keypair_name}
744 self.heat_tmplt_path = pkg_resources.resource_filename(
745 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
747 stack_settings = StackSettings(
748 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
749 template_path=self.heat_tmplt_path,
750 env_values=self.env_values)
751 self.stack_creator = create_stack.OpenStackHeatStack(
752 self.heat_creds, stack_settings)
753 self.created_stack = self.stack_creator.create()
754 self.assertIsNotNone(self.created_stack)
758 Cleans the stack and downloaded stack file
760 if self.stack_creator:
762 self.stack_creator.clean()
766 super(self.__class__, self).__clean__()
768 def test_retrieve_keypair_creator(self):
770 Tests the creation of an OpenStack stack from Heat template file and
771 the retrieval of an OpenStackKeypair creator/state machine instance
773 kp_creators = self.stack_creator.get_keypair_creators('private_key')
774 self.assertEqual(1, len(kp_creators))
776 creator = kp_creators[0]
778 self.assertEqual(self.keypair_name, creator.get_keypair().name)
779 self.assertIsNotNone(creator.keypair_settings.private_filepath)
781 private_file_contents = file_utils.read_file(
782 creator.keypair_settings.private_filepath)
783 self.assertTrue(private_file_contents.startswith(
784 '-----BEGIN RSA PRIVATE KEY-----'))
786 keypair = nova_utils.get_keypair_by_id(
787 self.nova, creator.get_keypair().id)
788 self.assertIsNotNone(keypair)
789 self.assertEqual(creator.get_keypair(), keypair)
792 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
794 Tests for the OpenStackHeatStack class to ensure it returns an
795 OpenStackSecurityGroup object
800 Instantiates the CreateStack object that is responsible for downloading
801 and creating an OS stack file within OpenStack
803 super(self.__class__, self).__start__()
805 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
807 self.heat_creds = self.admin_os_creds
808 self.heat_creds.project_name = self.admin_os_creds.project_name
810 self.heat_cli = heat_utils.heat_client(self.heat_creds)
811 self.nova = nova_utils.nova_client(self.heat_creds)
812 self.stack_creator = None
814 self.security_group_name = self.guid + '-sec-grp'
817 'security_group_name': self.security_group_name}
819 self.heat_tmplt_path = pkg_resources.resource_filename(
820 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
822 stack_settings = StackSettings(
823 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
824 template_path=self.heat_tmplt_path,
825 env_values=self.env_values)
826 self.stack_creator = create_stack.OpenStackHeatStack(
827 self.heat_creds, stack_settings)
828 self.created_stack = self.stack_creator.create()
829 self.assertIsNotNone(self.created_stack)
833 Cleans the stack and downloaded stack file
835 if self.stack_creator:
837 self.stack_creator.clean()
841 super(self.__class__, self).__clean__()
843 def test_retrieve_security_group_creator(self):
845 Tests the creation of an OpenStack stack from Heat template file and
846 the retrieval of an OpenStackSecurityGroup creator/state machine
849 sec_grp_creators = self.stack_creator.get_security_group_creators()
850 self.assertEqual(1, len(sec_grp_creators))
852 creator = sec_grp_creators[0]
853 sec_grp = creator.get_security_group()
855 self.assertEqual(self.security_group_name, sec_grp.name)
856 self.assertEqual('Test description', sec_grp.description)
857 self.assertEqual(2, len(sec_grp.rules))
860 has_icmp_rule = False
862 for rule in sec_grp.rules:
863 if (rule.security_group_id == sec_grp.id
864 and rule.direction == 'egress'
865 and rule.ethertype == 'IPv4'
866 and rule.port_range_min == 22
867 and rule.port_range_max == 22
868 and rule.protocol == 'tcp'
869 and rule.remote_group_id is None
870 and rule.remote_ip_prefix == '0.0.0.0/0'):
872 if (rule.security_group_id == sec_grp.id
873 and rule.direction == 'ingress'
874 and rule.ethertype == 'IPv4'
875 and rule.port_range_min is None
876 and rule.port_range_max is None
877 and rule.protocol == 'icmp'
878 and rule.remote_group_id is None
879 and rule.remote_ip_prefix == '0.0.0.0/0'):
882 self.assertTrue(has_ssh_rule)
883 self.assertTrue(has_icmp_rule)
886 class CreateStackNegativeTests(OSIntegrationTestCase):
888 Negative test cases for the OpenStackHeatStack class with poor
894 super(self.__class__, self).__start__()
896 self.heat_creds = self.admin_os_creds
897 self.heat_creds.project_name = self.admin_os_creds.project_name
899 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
900 self.stack_creator = None
901 self.heat_tmplt_path = pkg_resources.resource_filename(
902 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
905 if self.stack_creator:
906 self.stack_creator.clean()
907 super(self.__class__, self).__clean__()
909 def test_missing_dependencies(self):
911 Expect an StackCreationError when the stack file does not exist
913 stack_settings = StackSettings(name=self.stack_name,
914 template_path=self.heat_tmplt_path)
915 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
917 with self.assertRaises(HTTPBadRequest):
918 self.stack_creator.create()
920 def test_bad_stack_file(self):
922 Expect an StackCreationError when the stack file does not exist
924 stack_settings = StackSettings(name=self.stack_name,
926 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
928 with self.assertRaises(IOError):
929 self.stack_creator.create()
932 class CreateStackFailureTests(OSIntegrationTestCase):
934 Tests for the OpenStackHeatStack class defined in create_stack.py for
935 when failures occur. Failures are being triggered by allocating 1 million
941 super(self.__class__, self).__start__()
943 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
945 self.heat_creds = self.admin_os_creds
946 self.heat_creds.project_name = self.admin_os_creds.project_name
948 self.heat_cli = heat_utils.heat_client(self.heat_creds)
949 self.stack_creator = None
951 self.tmp_file = file_utils.save_string_to_file(
952 ' ', str(uuid.uuid4()) + '-bad-image')
953 self.image_creator = OpenStackImage(
954 self.heat_creds, ImageSettings(
955 name=self.guid + 'image', image_file=self.tmp_file.name,
956 image_user='foo', img_format='qcow2'))
957 self.image_creator.create()
960 self.flavor_creator = OpenStackFlavor(
962 FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10,
964 self.flavor_creator.create()
966 self.network_name = self.guid + '-net'
967 self.subnet_name = self.guid + '-subnet'
968 self.vm_inst_name = self.guid + '-inst'
971 'image_name': self.image_creator.image_settings.name,
972 'flavor_name': self.flavor_creator.flavor_settings.name,
973 'net_name': self.network_name,
974 'subnet_name': self.subnet_name,
975 'inst_name': self.vm_inst_name}
977 self.heat_tmplt_path = pkg_resources.resource_filename(
978 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
982 Cleans the stack and downloaded stack file
984 if self.stack_creator:
986 self.stack_creator.clean()
990 if self.image_creator:
992 self.image_creator.clean()
996 if self.flavor_creator:
998 self.flavor_creator.clean()
1004 os.remove(self.tmp_file.name)
1008 super(self.__class__, self).__clean__()
1010 def test_stack_failure(self):
1012 Tests the creation of an OpenStack stack from Heat template file that
1013 should always fail due to too many CPU cores
1016 # Set the default stack settings, then set any custom parameters sent
1018 stack_settings = StackSettings(
1019 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1020 template_path=self.heat_tmplt_path,
1021 env_values=self.env_values)
1022 self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds,
1025 with self.assertRaises(StackError):
1027 self.stack_creator.create()
1029 resources = heat_utils.get_resources(
1030 self.heat_cli, self.stack_creator.get_stack())
1033 for resource in resources:
1034 if resource.status == create_stack.STATUS_CREATE_COMPLETE:
1036 self.assertTrue(found)