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 neutron = neutron_utils.neutron_client(self.admin_os_creds)
392 vm_inst_by_name = nova_utils.get_server(
393 nova, neutron, server_name=vm_inst_creators[0].get_vm_inst().name)
394 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
395 self.assertIsNotNone(nova_utils.get_server_object_by_id(
396 nova, neutron, vm_inst_creators[0].get_vm_inst().id))
399 class CreateStackFloatingIpTests(OSIntegrationTestCase):
401 Tests to ensure that floating IPs can be accessed via an
402 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
407 super(self.__class__, self).__start__()
409 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
411 self.heat_creds = self.admin_os_creds
412 self.heat_creds.project_name = self.admin_os_creds.project_name
414 self.heat_cli = heat_utils.heat_client(self.heat_creds)
415 self.stack_creator = None
417 self.image_creator = OpenStackImage(
418 self.heat_creds, openstack_tests.cirros_image_settings(
419 name=self.guid + '-image',
420 image_metadata=self.image_metadata))
421 self.image_creator.create()
423 self.network_name = self.guid + '-net'
424 self.subnet_name = self.guid + '-subnet'
425 self.flavor1_name = self.guid + '-flavor1'
426 self.flavor2_name = self.guid + '-flavor2'
427 self.sec_grp_name = self.guid + '-sec_grp'
428 self.vm_inst1_name = self.guid + '-inst1'
429 self.vm_inst2_name = self.guid + '-inst2'
430 self.keypair_name = self.guid + '-kp'
433 'image1_name': self.image_creator.image_settings.name,
434 'image2_name': self.image_creator.image_settings.name,
435 'flavor1_name': self.flavor1_name,
436 'flavor2_name': self.flavor2_name,
437 'net_name': self.network_name,
438 'subnet_name': self.subnet_name,
439 'inst1_name': self.vm_inst1_name,
440 'inst2_name': self.vm_inst2_name,
441 'keypair_name': self.keypair_name,
442 'external_net_name': self.ext_net_name,
443 'security_group_name': self.sec_grp_name}
445 self.heat_tmplt_path = pkg_resources.resource_filename(
446 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
448 self.vm_inst_creators = list()
452 Cleans the stack and downloaded stack file
454 if self.stack_creator:
456 self.stack_creator.clean()
460 if self.image_creator:
462 self.image_creator.clean()
466 for vm_inst_creator in self.vm_inst_creators:
468 keypair_settings = vm_inst_creator.keypair_settings
469 if keypair_settings and keypair_settings.private_filepath:
470 expanded_path = os.path.expanduser(
471 keypair_settings.private_filepath)
472 os.chmod(expanded_path, 0o755)
473 os.remove(expanded_path)
477 super(self.__class__, self).__clean__()
479 def test_connect_via_ssh_heat_vm(self):
481 Tests the creation of an OpenStack stack from Heat template file and
482 the retrieval of two VM instance creators and attempt to connect via
483 SSH to the first one with a floating IP.
485 stack_settings = StackConfig(
486 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
487 template_path=self.heat_tmplt_path,
488 env_values=self.env_values)
489 self.stack_creator = OpenStackHeatStack(
490 self.heat_creds, stack_settings,
491 [self.image_creator.image_settings])
492 created_stack = self.stack_creator.create()
493 self.assertIsNotNone(created_stack)
495 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
496 heat_keypair_option='private_key')
497 self.assertIsNotNone(self.vm_inst_creators)
498 self.assertEqual(2, len(self.vm_inst_creators))
500 for vm_inst_creator in self.vm_inst_creators:
501 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
503 create_instance_tests.validate_ssh_client(vm_inst_creator))
505 vm_settings = vm_inst_creator.instance_settings
506 self.assertEqual(0, len(vm_settings.floating_ip_settings))
509 class CreateStackRouterTests(OSIntegrationTestCase):
511 Tests for the CreateStack class defined in create_stack.py where the
512 target is a Network, Subnet, and Router
517 Instantiates the CreateStack object that is responsible for downloading
518 and creating an OS stack file within OpenStack
520 super(self.__class__, self).__start__()
522 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
524 self.heat_creds = self.admin_os_creds
525 self.heat_creds.project_name = self.admin_os_creds.project_name
527 self.heat_cli = heat_utils.heat_client(self.heat_creds)
528 self.neutron = neutron_utils.neutron_client(self.os_creds)
529 self.stack_creator = None
531 self.net_name = self.guid + '-net'
532 self.subnet_name = self.guid + '-subnet'
533 self.router_name = self.guid + '-router'
536 'net_name': self.net_name,
537 'subnet_name': self.subnet_name,
538 'router_name': self.router_name,
539 'external_net_name': self.ext_net_name}
541 self.heat_tmplt_path = pkg_resources.resource_filename(
542 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
544 stack_settings = StackConfig(
545 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
546 template_path=self.heat_tmplt_path,
547 env_values=self.env_values)
548 self.stack_creator = OpenStackHeatStack(
549 self.heat_creds, stack_settings)
550 self.created_stack = self.stack_creator.create()
551 self.assertIsNotNone(self.created_stack)
555 Cleans the stack and downloaded stack file
557 if self.stack_creator:
559 self.stack_creator.clean()
563 super(self.__class__, self).__clean__()
565 def test_retrieve_router_creator(self):
567 Tests the creation of an OpenStack stack from Heat template file and
568 the retrieval of an OpenStackRouter creator/state machine instance
570 router_creators = self.stack_creator.get_router_creators()
571 self.assertEqual(1, len(router_creators))
573 creator = router_creators[0]
574 self.assertEqual(self.router_name, creator.router_settings.name)
576 router = creator.get_router()
578 ext_net = neutron_utils.get_network(
579 self.neutron, network_name=self.ext_net_name)
580 self.assertEqual(ext_net.id, router.external_network_id)
583 class CreateStackVolumeTests(OSIntegrationTestCase):
585 Tests to ensure that floating IPs can be accessed via an
586 OpenStackVolume object obtained from the OpenStackHeatStack instance
591 super(self.__class__, self).__start__()
593 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
595 self.heat_creds = self.admin_os_creds
596 self.heat_creds.project_name = self.admin_os_creds.project_name
598 self.heat_cli = heat_utils.heat_client(self.heat_creds)
599 self.stack_creator = None
601 self.volume_name = self.guid + '-volume'
602 self.volume_type_name = self.guid + '-volume-type'
605 'volume_name': self.volume_name,
606 'volume_type_name': self.volume_type_name}
608 self.heat_tmplt_path = pkg_resources.resource_filename(
609 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
611 stack_settings = StackConfig(
612 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
613 template_path=self.heat_tmplt_path,
614 env_values=self.env_values)
615 self.stack_creator = OpenStackHeatStack(
616 self.heat_creds, stack_settings)
617 self.created_stack = self.stack_creator.create()
618 self.assertIsNotNone(self.created_stack)
622 Cleans the stack and downloaded stack file
624 if self.stack_creator:
626 self.stack_creator.clean()
630 super(self.__class__, self).__clean__()
632 def test_retrieve_volume_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_creators = self.stack_creator.get_volume_creators()
638 self.assertEqual(1, len(volume_creators))
640 creator = volume_creators[0]
641 self.assertEqual(self.volume_name, creator.volume_settings.name)
642 self.assertEqual(self.volume_name, creator.get_volume().name)
643 self.assertEqual(self.volume_type_name,
644 creator.volume_settings.type_name)
645 self.assertEqual(self.volume_type_name, creator.get_volume().type)
646 self.assertEqual(1, creator.volume_settings.size)
647 self.assertEqual(1, creator.get_volume().size)
649 def test_retrieve_volume_type_creator(self):
651 Tests the creation of an OpenStack stack from Heat template file and
652 the retrieval of an OpenStackVolume creator/state machine instance
654 volume_type_creators = self.stack_creator.get_volume_type_creators()
655 self.assertEqual(1, len(volume_type_creators))
657 creator = volume_type_creators[0]
658 self.assertIsNotNone(creator)
660 volume_type = creator.get_volume_type()
661 self.assertIsNotNone(volume_type)
663 self.assertEqual(self.volume_type_name, volume_type.name)
664 self.assertTrue(volume_type.public)
665 self.assertIsNone(volume_type.qos_spec)
667 # TODO - Add encryption back and find out why it broke in Pike
668 # encryption = volume_type.encryption
669 # self.assertIsNotNone(encryption)
670 # self.assertIsNone(encryption.cipher)
671 # self.assertEqual('front-end', encryption.control_location)
672 # self.assertIsNone(encryption.key_size)
673 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
674 # encryption.provider)
675 # self.assertEqual(volume_type.id, encryption.volume_type_id)
678 class CreateStackFlavorTests(OSIntegrationTestCase):
680 Tests to ensure that floating IPs can be accessed via an
681 OpenStackFlavor object obtained from the OpenStackHeatStack instance
686 super(self.__class__, self).__start__()
688 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
690 self.heat_creds = self.admin_os_creds
691 self.heat_creds.project_name = self.admin_os_creds.project_name
693 self.heat_cli = heat_utils.heat_client(self.heat_creds)
694 self.stack_creator = None
696 self.heat_tmplt_path = pkg_resources.resource_filename(
697 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
699 stack_settings = StackConfig(
700 name=self.guid + '-stack',
701 template_path=self.heat_tmplt_path)
702 self.stack_creator = OpenStackHeatStack(
703 self.heat_creds, stack_settings)
704 self.created_stack = self.stack_creator.create()
705 self.assertIsNotNone(self.created_stack)
709 Cleans the stack and downloaded stack file
711 if self.stack_creator:
713 self.stack_creator.clean()
717 super(self.__class__, self).__clean__()
719 def test_retrieve_flavor_creator(self):
721 Tests the creation of an OpenStack stack from Heat template file and
722 the retrieval of an OpenStackVolume creator/state machine instance
724 flavor_creators = self.stack_creator.get_flavor_creators()
725 self.assertEqual(1, len(flavor_creators))
727 creator = flavor_creators[0]
728 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
729 self.assertEqual(1024, creator.get_flavor().ram)
730 self.assertEqual(200, creator.get_flavor().disk)
731 self.assertEqual(8, creator.get_flavor().vcpus)
732 self.assertEqual(0, creator.get_flavor().ephemeral)
733 self.assertIsNone(creator.get_flavor().swap)
734 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
735 self.assertTrue(creator.get_flavor().is_public)
738 class CreateStackKeypairTests(OSIntegrationTestCase):
740 Tests to ensure that floating IPs can be accessed via an
741 OpenStackKeypair object obtained from the OpenStackHeatStack instance
746 super(self.__class__, self).__start__()
748 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
750 self.heat_creds = self.admin_os_creds
751 self.heat_creds.project_name = self.admin_os_creds.project_name
753 self.heat_cli = heat_utils.heat_client(self.heat_creds)
754 self.nova = nova_utils.nova_client(self.heat_creds)
755 self.stack_creator = None
757 self.keypair_name = self.guid + '-kp'
760 'keypair_name': self.keypair_name}
762 self.heat_tmplt_path = pkg_resources.resource_filename(
763 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
765 stack_settings = StackConfig(
766 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
767 template_path=self.heat_tmplt_path,
768 env_values=self.env_values)
769 self.stack_creator = OpenStackHeatStack(
770 self.heat_creds, stack_settings)
771 self.created_stack = self.stack_creator.create()
772 self.assertIsNotNone(self.created_stack)
774 self.keypair_creators = list()
778 Cleans the stack and downloaded stack file
780 if self.stack_creator:
782 self.stack_creator.clean()
785 for keypair_creator in self.keypair_creators:
787 keypair_creator.clean()
791 super(self.__class__, self).__clean__()
793 def test_retrieve_keypair_creator(self):
795 Tests the creation of an OpenStack stack from Heat template file and
796 the retrieval of an OpenStackKeypair creator/state machine instance
798 self.kp_creators = self.stack_creator.get_keypair_creators(
800 self.assertEqual(1, len(self.kp_creators))
802 self.keypair_creator = self.kp_creators[0]
804 self.assertEqual(self.keypair_name,
805 self.keypair_creator.get_keypair().name)
806 self.assertIsNotNone(
807 self.keypair_creator.keypair_settings.private_filepath)
809 private_file_contents = file_utils.read_file(
810 self.keypair_creator.keypair_settings.private_filepath)
811 self.assertTrue(private_file_contents.startswith(
812 '-----BEGIN RSA PRIVATE KEY-----'))
814 keypair = nova_utils.get_keypair_by_id(
815 self.nova, self.keypair_creator.get_keypair().id)
816 self.assertIsNotNone(keypair)
817 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
820 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
822 Tests for the OpenStackHeatStack class to ensure it returns an
823 OpenStackSecurityGroup object
828 Instantiates the CreateStack object that is responsible for downloading
829 and creating an OS stack file within OpenStack
831 super(self.__class__, self).__start__()
833 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
835 self.heat_creds = self.admin_os_creds
836 self.heat_creds.project_name = self.admin_os_creds.project_name
838 self.heat_cli = heat_utils.heat_client(self.heat_creds)
839 self.nova = nova_utils.nova_client(self.heat_creds)
840 self.stack_creator = None
842 self.security_group_name = self.guid + '-sec-grp'
845 'security_group_name': self.security_group_name}
847 self.heat_tmplt_path = pkg_resources.resource_filename(
848 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
850 stack_settings = StackConfig(
851 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
852 template_path=self.heat_tmplt_path,
853 env_values=self.env_values)
854 self.stack_creator = OpenStackHeatStack(
855 self.heat_creds, stack_settings)
856 self.created_stack = self.stack_creator.create()
857 self.assertIsNotNone(self.created_stack)
861 Cleans the stack and downloaded stack file
863 if self.stack_creator:
865 self.stack_creator.clean()
869 super(self.__class__, self).__clean__()
871 def test_retrieve_security_group_creator(self):
873 Tests the creation of an OpenStack stack from Heat template file and
874 the retrieval of an OpenStackSecurityGroup creator/state machine
877 sec_grp_creators = self.stack_creator.get_security_group_creators()
878 self.assertEqual(1, len(sec_grp_creators))
880 creator = sec_grp_creators[0]
881 sec_grp = creator.get_security_group()
883 self.assertEqual(self.security_group_name, sec_grp.name)
884 self.assertEqual('Test description', sec_grp.description)
885 self.assertEqual(2, len(sec_grp.rules))
888 has_icmp_rule = False
890 for rule in sec_grp.rules:
891 if (rule.security_group_id == sec_grp.id
892 and rule.direction == 'egress'
893 and rule.ethertype == 'IPv4'
894 and rule.port_range_min == 22
895 and rule.port_range_max == 22
896 and rule.protocol == 'tcp'
897 and rule.remote_group_id is None
898 and rule.remote_ip_prefix == '0.0.0.0/0'):
900 if (rule.security_group_id == sec_grp.id
901 and rule.direction == 'ingress'
902 and rule.ethertype == 'IPv4'
903 and rule.port_range_min is None
904 and rule.port_range_max is None
905 and rule.protocol == 'icmp'
906 and rule.remote_group_id is None
907 and rule.remote_ip_prefix == '0.0.0.0/0'):
910 self.assertTrue(has_ssh_rule)
911 self.assertTrue(has_icmp_rule)
914 class CreateStackNegativeTests(OSIntegrationTestCase):
916 Negative test cases for the OpenStackHeatStack class with poor
922 super(self.__class__, self).__start__()
924 self.heat_creds = self.admin_os_creds
925 self.heat_creds.project_name = self.admin_os_creds.project_name
927 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
928 self.stack_creator = None
929 self.heat_tmplt_path = pkg_resources.resource_filename(
930 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
933 if self.stack_creator:
934 self.stack_creator.clean()
935 super(self.__class__, self).__clean__()
937 def test_missing_dependencies(self):
939 Expect an StackCreationError when the stack file does not exist
941 stack_settings = StackConfig(name=self.stack_name,
942 template_path=self.heat_tmplt_path)
943 self.stack_creator = OpenStackHeatStack(
944 self.heat_creds, stack_settings)
945 with self.assertRaises(HTTPBadRequest):
946 self.stack_creator.create()
948 def test_bad_stack_file(self):
950 Expect an StackCreationError when the stack file does not exist
952 stack_settings = StackConfig(
953 name=self.stack_name, template_path='foo')
954 self.stack_creator = OpenStackHeatStack(
955 self.heat_creds, stack_settings)
956 with self.assertRaises(IOError):
957 self.stack_creator.create()
960 class CreateStackFailureTests(OSIntegrationTestCase):
962 Tests for the OpenStackHeatStack class defined in create_stack.py for
963 when failures occur. Failures are being triggered by allocating 1 million
969 super(self.__class__, self).__start__()
971 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
973 self.heat_creds = self.admin_os_creds
974 self.heat_creds.project_name = self.admin_os_creds.project_name
976 self.heat_cli = heat_utils.heat_client(self.heat_creds)
977 self.stack_creator = None
979 self.tmp_file = file_utils.save_string_to_file(
980 ' ', str(uuid.uuid4()) + '-bad-image')
981 self.image_creator = OpenStackImage(
982 self.heat_creds, ImageConfig(
983 name=self.guid + 'image', image_file=self.tmp_file.name,
984 image_user='foo', img_format='qcow2'))
985 self.image_creator.create()
988 self.flavor_creator = OpenStackFlavor(
991 name=self.guid + '-flavor-name', ram=256, disk=10,
993 self.flavor_creator.create()
995 self.network_name = self.guid + '-net'
996 self.subnet_name = self.guid + '-subnet'
997 self.vm_inst_name = self.guid + '-inst'
1000 'image_name': self.image_creator.image_settings.name,
1001 'flavor_name': self.flavor_creator.flavor_settings.name,
1002 'net_name': self.network_name,
1003 'subnet_name': self.subnet_name,
1004 'inst_name': self.vm_inst_name}
1006 self.heat_tmplt_path = pkg_resources.resource_filename(
1007 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1011 Cleans the stack and downloaded stack file
1013 if self.stack_creator:
1015 self.stack_creator.clean()
1019 if self.image_creator:
1021 self.image_creator.clean()
1025 if self.flavor_creator:
1027 self.flavor_creator.clean()
1033 os.remove(self.tmp_file.name)
1037 super(self.__class__, self).__clean__()
1039 def test_stack_failure(self):
1041 Tests the creation of an OpenStack stack from Heat template file that
1042 should always fail due to too many CPU cores
1045 # Set the default stack settings, then set any custom parameters sent
1047 stack_settings = StackConfig(
1048 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1049 template_path=self.heat_tmplt_path,
1050 env_values=self.env_values)
1051 self.stack_creator = OpenStackHeatStack(
1052 self.heat_creds, stack_settings)
1054 with self.assertRaises(StackError):
1056 self.stack_creator.create()
1058 resources = heat_utils.get_resources(
1059 self.heat_cli, self.stack_creator.get_stack())
1062 for resource in resources:
1063 if (resource.status ==
1064 snaps.config.stack.STATUS_CREATE_COMPLETE):
1066 self.assertTrue(found)