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 CreateStackNestedResourceTests(OSIntegrationTestCase):
511 Tests to ensure that nested heat templates work
516 super(self.__class__, self).__start__()
518 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
520 self.heat_creds = self.admin_os_creds
521 self.heat_creds.project_name = self.admin_os_creds.project_name
523 self.heat_cli = heat_utils.heat_client(self.heat_creds)
524 self.stack_creator = None
526 self.image_creator = OpenStackImage(
527 self.heat_creds, openstack_tests.cirros_image_settings(
528 name=self.guid + '-image',
529 image_metadata=self.image_metadata))
530 self.image_creator.create()
532 self.flavor_creator = OpenStackFlavor(
535 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
536 self.flavor_creator.create()
539 'network_name': self.guid + '-network',
540 'public_network': self.ext_net_name,
541 'agent_image': self.image_creator.image_settings.name,
542 'agent_flavor': self.flavor_creator.flavor_settings.name,
543 'key_name': self.guid + '-key',
546 heat_tmplt_path = pkg_resources.resource_filename(
547 'snaps.openstack.tests.heat', 'agent-group.yaml')
548 heat_resource_path = pkg_resources.resource_filename(
549 'snaps.openstack.tests.heat', 'agent.yaml')
551 stack_settings = StackConfig(
552 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
553 template_path=heat_tmplt_path,
554 resource_files=[heat_resource_path],
555 env_values=env_values)
557 self.stack_creator = OpenStackHeatStack(
558 self.heat_creds, stack_settings,
559 [self.image_creator.image_settings])
561 self.vm_inst_creators = list()
565 Cleans the stack and downloaded stack file
567 if self.stack_creator:
569 self.stack_creator.clean()
573 if self.image_creator:
575 self.image_creator.clean()
579 if self.flavor_creator:
581 self.flavor_creator.clean()
585 for vm_inst_creator in self.vm_inst_creators:
587 keypair_settings = vm_inst_creator.keypair_settings
588 if keypair_settings and keypair_settings.private_filepath:
589 expanded_path = os.path.expanduser(
590 keypair_settings.private_filepath)
591 os.chmod(expanded_path, 0o755)
592 os.remove(expanded_path)
596 super(self.__class__, self).__clean__()
598 def test_nested(self):
600 Tests the creation of an OpenStack stack from Heat template file and
601 the retrieval of two VM instance creators and attempt to connect via
602 SSH to the first one with a floating IP.
604 created_stack = self.stack_creator.create()
605 self.assertIsNotNone(created_stack)
607 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
608 heat_keypair_option='private_key')
609 self.assertIsNotNone(self.vm_inst_creators)
610 self.assertEqual(1, len(self.vm_inst_creators))
612 for vm_inst_creator in self.vm_inst_creators:
614 create_instance_tests.validate_ssh_client(vm_inst_creator))
617 class CreateStackRouterTests(OSIntegrationTestCase):
619 Tests for the CreateStack class defined in create_stack.py where the
620 target is a Network, Subnet, and Router
625 Instantiates the CreateStack object that is responsible for downloading
626 and creating an OS stack file within OpenStack
628 super(self.__class__, self).__start__()
630 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
632 self.heat_creds = self.admin_os_creds
633 self.heat_creds.project_name = self.admin_os_creds.project_name
635 self.heat_cli = heat_utils.heat_client(self.heat_creds)
636 self.neutron = neutron_utils.neutron_client(self.os_creds)
637 self.stack_creator = None
639 self.net_name = self.guid + '-net'
640 self.subnet_name = self.guid + '-subnet'
641 self.router_name = self.guid + '-router'
644 'net_name': self.net_name,
645 'subnet_name': self.subnet_name,
646 'router_name': self.router_name,
647 'external_net_name': self.ext_net_name}
649 self.heat_tmplt_path = pkg_resources.resource_filename(
650 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
652 stack_settings = StackConfig(
653 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
654 template_path=self.heat_tmplt_path,
655 env_values=self.env_values)
656 self.stack_creator = OpenStackHeatStack(
657 self.heat_creds, stack_settings)
658 self.created_stack = self.stack_creator.create()
659 self.assertIsNotNone(self.created_stack)
663 Cleans the stack and downloaded stack file
665 if self.stack_creator:
667 self.stack_creator.clean()
671 super(self.__class__, self).__clean__()
673 def test_retrieve_router_creator(self):
675 Tests the creation of an OpenStack stack from Heat template file and
676 the retrieval of an OpenStackRouter creator/state machine instance
678 router_creators = self.stack_creator.get_router_creators()
679 self.assertEqual(1, len(router_creators))
681 creator = router_creators[0]
682 self.assertEqual(self.router_name, creator.router_settings.name)
684 router = creator.get_router()
686 ext_net = neutron_utils.get_network(
687 self.neutron, network_name=self.ext_net_name)
688 self.assertEqual(ext_net.id, router.external_network_id)
691 class CreateStackVolumeTests(OSIntegrationTestCase):
693 Tests to ensure that floating IPs can be accessed via an
694 OpenStackVolume object obtained from the OpenStackHeatStack instance
699 super(self.__class__, self).__start__()
701 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
703 self.heat_creds = self.admin_os_creds
704 self.heat_creds.project_name = self.admin_os_creds.project_name
706 self.heat_cli = heat_utils.heat_client(self.heat_creds)
707 self.stack_creator = None
709 self.volume_name = self.guid + '-volume'
710 self.volume_type_name = self.guid + '-volume-type'
713 'volume_name': self.volume_name,
714 'volume_type_name': self.volume_type_name}
716 self.heat_tmplt_path = pkg_resources.resource_filename(
717 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
719 stack_settings = StackConfig(
720 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
721 template_path=self.heat_tmplt_path,
722 env_values=self.env_values)
723 self.stack_creator = OpenStackHeatStack(
724 self.heat_creds, stack_settings)
725 self.created_stack = self.stack_creator.create()
726 self.assertIsNotNone(self.created_stack)
730 Cleans the stack and downloaded stack file
732 if self.stack_creator:
734 self.stack_creator.clean()
738 super(self.__class__, self).__clean__()
740 def test_retrieve_volume_creator(self):
742 Tests the creation of an OpenStack stack from Heat template file and
743 the retrieval of an OpenStackVolume creator/state machine instance
745 volume_creators = self.stack_creator.get_volume_creators()
746 self.assertEqual(1, len(volume_creators))
748 creator = volume_creators[0]
749 self.assertEqual(self.volume_name, creator.volume_settings.name)
750 self.assertEqual(self.volume_name, creator.get_volume().name)
751 self.assertEqual(self.volume_type_name,
752 creator.volume_settings.type_name)
753 self.assertEqual(self.volume_type_name, creator.get_volume().type)
754 self.assertEqual(1, creator.volume_settings.size)
755 self.assertEqual(1, creator.get_volume().size)
757 def test_retrieve_volume_type_creator(self):
759 Tests the creation of an OpenStack stack from Heat template file and
760 the retrieval of an OpenStackVolume creator/state machine instance
762 volume_type_creators = self.stack_creator.get_volume_type_creators()
763 self.assertEqual(1, len(volume_type_creators))
765 creator = volume_type_creators[0]
766 self.assertIsNotNone(creator)
768 volume_type = creator.get_volume_type()
769 self.assertIsNotNone(volume_type)
771 self.assertEqual(self.volume_type_name, volume_type.name)
772 self.assertTrue(volume_type.public)
773 self.assertIsNone(volume_type.qos_spec)
775 # TODO - Add encryption back and find out why it broke in Pike
776 # encryption = volume_type.encryption
777 # self.assertIsNotNone(encryption)
778 # self.assertIsNone(encryption.cipher)
779 # self.assertEqual('front-end', encryption.control_location)
780 # self.assertIsNone(encryption.key_size)
781 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
782 # encryption.provider)
783 # self.assertEqual(volume_type.id, encryption.volume_type_id)
786 class CreateStackFlavorTests(OSIntegrationTestCase):
788 Tests to ensure that floating IPs can be accessed via an
789 OpenStackFlavor object obtained from the OpenStackHeatStack instance
794 super(self.__class__, self).__start__()
796 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
798 self.heat_creds = self.admin_os_creds
799 self.heat_creds.project_name = self.admin_os_creds.project_name
801 self.heat_cli = heat_utils.heat_client(self.heat_creds)
802 self.stack_creator = None
804 self.heat_tmplt_path = pkg_resources.resource_filename(
805 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
807 stack_settings = StackConfig(
808 name=self.guid + '-stack',
809 template_path=self.heat_tmplt_path)
810 self.stack_creator = OpenStackHeatStack(
811 self.heat_creds, stack_settings)
812 self.created_stack = self.stack_creator.create()
813 self.assertIsNotNone(self.created_stack)
817 Cleans the stack and downloaded stack file
819 if self.stack_creator:
821 self.stack_creator.clean()
825 super(self.__class__, self).__clean__()
827 def test_retrieve_flavor_creator(self):
829 Tests the creation of an OpenStack stack from Heat template file and
830 the retrieval of an OpenStackVolume creator/state machine instance
832 flavor_creators = self.stack_creator.get_flavor_creators()
833 self.assertEqual(1, len(flavor_creators))
835 creator = flavor_creators[0]
836 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
837 self.assertEqual(1024, creator.get_flavor().ram)
838 self.assertEqual(200, creator.get_flavor().disk)
839 self.assertEqual(8, creator.get_flavor().vcpus)
840 self.assertEqual(0, creator.get_flavor().ephemeral)
841 self.assertIsNone(creator.get_flavor().swap)
842 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
843 self.assertTrue(creator.get_flavor().is_public)
846 class CreateStackKeypairTests(OSIntegrationTestCase):
848 Tests to ensure that floating IPs can be accessed via an
849 OpenStackKeypair object obtained from the OpenStackHeatStack instance
854 super(self.__class__, self).__start__()
856 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
858 self.heat_creds = self.admin_os_creds
859 self.heat_creds.project_name = self.admin_os_creds.project_name
861 self.heat_cli = heat_utils.heat_client(self.heat_creds)
862 self.nova = nova_utils.nova_client(self.heat_creds)
863 self.stack_creator = None
865 self.keypair_name = self.guid + '-kp'
868 'keypair_name': self.keypair_name}
870 self.heat_tmplt_path = pkg_resources.resource_filename(
871 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
873 stack_settings = StackConfig(
874 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
875 template_path=self.heat_tmplt_path,
876 env_values=self.env_values)
877 self.stack_creator = OpenStackHeatStack(
878 self.heat_creds, stack_settings)
879 self.created_stack = self.stack_creator.create()
880 self.assertIsNotNone(self.created_stack)
882 self.keypair_creators = list()
886 Cleans the stack and downloaded stack file
888 if self.stack_creator:
890 self.stack_creator.clean()
893 for keypair_creator in self.keypair_creators:
895 keypair_creator.clean()
899 super(self.__class__, self).__clean__()
901 def test_retrieve_keypair_creator(self):
903 Tests the creation of an OpenStack stack from Heat template file and
904 the retrieval of an OpenStackKeypair creator/state machine instance
906 self.kp_creators = self.stack_creator.get_keypair_creators(
908 self.assertEqual(1, len(self.kp_creators))
910 self.keypair_creator = self.kp_creators[0]
912 self.assertEqual(self.keypair_name,
913 self.keypair_creator.get_keypair().name)
914 self.assertIsNotNone(
915 self.keypair_creator.keypair_settings.private_filepath)
917 private_file_contents = file_utils.read_file(
918 self.keypair_creator.keypair_settings.private_filepath)
919 self.assertTrue(private_file_contents.startswith(
920 '-----BEGIN RSA PRIVATE KEY-----'))
922 keypair = nova_utils.get_keypair_by_id(
923 self.nova, self.keypair_creator.get_keypair().id)
924 self.assertIsNotNone(keypair)
925 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
928 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
930 Tests for the OpenStackHeatStack class to ensure it returns an
931 OpenStackSecurityGroup object
936 Instantiates the CreateStack object that is responsible for downloading
937 and creating an OS stack file within OpenStack
939 super(self.__class__, self).__start__()
941 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
943 self.heat_creds = self.admin_os_creds
944 self.heat_creds.project_name = self.admin_os_creds.project_name
946 self.heat_cli = heat_utils.heat_client(self.heat_creds)
947 self.nova = nova_utils.nova_client(self.heat_creds)
948 self.stack_creator = None
950 self.security_group_name = self.guid + '-sec-grp'
953 'security_group_name': self.security_group_name}
955 self.heat_tmplt_path = pkg_resources.resource_filename(
956 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
958 stack_settings = StackConfig(
959 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
960 template_path=self.heat_tmplt_path,
961 env_values=self.env_values)
962 self.stack_creator = OpenStackHeatStack(
963 self.heat_creds, stack_settings)
964 self.created_stack = self.stack_creator.create()
965 self.assertIsNotNone(self.created_stack)
969 Cleans the stack and downloaded stack file
971 if self.stack_creator:
973 self.stack_creator.clean()
977 super(self.__class__, self).__clean__()
979 def test_retrieve_security_group_creator(self):
981 Tests the creation of an OpenStack stack from Heat template file and
982 the retrieval of an OpenStackSecurityGroup creator/state machine
985 sec_grp_creators = self.stack_creator.get_security_group_creators()
986 self.assertEqual(1, len(sec_grp_creators))
988 creator = sec_grp_creators[0]
989 sec_grp = creator.get_security_group()
991 self.assertEqual(self.security_group_name, sec_grp.name)
992 self.assertEqual('Test description', sec_grp.description)
993 self.assertEqual(2, len(sec_grp.rules))
996 has_icmp_rule = False
998 for rule in sec_grp.rules:
999 if (rule.security_group_id == sec_grp.id
1000 and rule.direction == 'egress'
1001 and rule.ethertype == 'IPv4'
1002 and rule.port_range_min == 22
1003 and rule.port_range_max == 22
1004 and rule.protocol == 'tcp'
1005 and rule.remote_group_id is None
1006 and rule.remote_ip_prefix == '0.0.0.0/0'):
1008 if (rule.security_group_id == sec_grp.id
1009 and rule.direction == 'ingress'
1010 and rule.ethertype == 'IPv4'
1011 and rule.port_range_min is None
1012 and rule.port_range_max is None
1013 and rule.protocol == 'icmp'
1014 and rule.remote_group_id is None
1015 and rule.remote_ip_prefix == '0.0.0.0/0'):
1016 has_icmp_rule = True
1018 self.assertTrue(has_ssh_rule)
1019 self.assertTrue(has_icmp_rule)
1022 class CreateStackNegativeTests(OSIntegrationTestCase):
1024 Negative test cases for the OpenStackHeatStack class with poor
1030 super(self.__class__, self).__start__()
1032 self.heat_creds = self.admin_os_creds
1033 self.heat_creds.project_name = self.admin_os_creds.project_name
1035 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1036 self.stack_creator = None
1037 self.heat_tmplt_path = pkg_resources.resource_filename(
1038 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1041 if self.stack_creator:
1042 self.stack_creator.clean()
1043 super(self.__class__, self).__clean__()
1045 def test_missing_dependencies(self):
1047 Expect an StackCreationError when the stack file does not exist
1049 stack_settings = StackConfig(name=self.stack_name,
1050 template_path=self.heat_tmplt_path)
1051 self.stack_creator = OpenStackHeatStack(
1052 self.heat_creds, stack_settings)
1053 with self.assertRaises(HTTPBadRequest):
1054 self.stack_creator.create()
1056 def test_bad_stack_file(self):
1058 Expect an StackCreationError when the stack file does not exist
1060 stack_settings = StackConfig(
1061 name=self.stack_name, template_path='foo')
1062 self.stack_creator = OpenStackHeatStack(
1063 self.heat_creds, stack_settings)
1064 with self.assertRaises(IOError):
1065 self.stack_creator.create()
1068 class CreateStackFailureTests(OSIntegrationTestCase):
1070 Tests for the OpenStackHeatStack class defined in create_stack.py for
1071 when failures occur. Failures are being triggered by allocating 1 million
1077 super(self.__class__, self).__start__()
1079 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1081 self.heat_creds = self.admin_os_creds
1082 self.heat_creds.project_name = self.admin_os_creds.project_name
1084 self.heat_cli = heat_utils.heat_client(self.heat_creds)
1085 self.stack_creator = None
1087 self.tmp_file = file_utils.save_string_to_file(
1088 ' ', str(uuid.uuid4()) + '-bad-image')
1089 self.image_creator = OpenStackImage(
1090 self.heat_creds, ImageConfig(
1091 name=self.guid + 'image', image_file=self.tmp_file.name,
1092 image_user='foo', img_format='qcow2'))
1093 self.image_creator.create()
1096 self.flavor_creator = OpenStackFlavor(
1097 self.admin_os_creds,
1099 name=self.guid + '-flavor-name', ram=256, disk=10,
1101 self.flavor_creator.create()
1103 self.network_name = self.guid + '-net'
1104 self.subnet_name = self.guid + '-subnet'
1105 self.vm_inst_name = self.guid + '-inst'
1108 'image_name': self.image_creator.image_settings.name,
1109 'flavor_name': self.flavor_creator.flavor_settings.name,
1110 'net_name': self.network_name,
1111 'subnet_name': self.subnet_name,
1112 'inst_name': self.vm_inst_name}
1114 self.heat_tmplt_path = pkg_resources.resource_filename(
1115 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1119 Cleans the stack and downloaded stack file
1121 if self.stack_creator:
1123 self.stack_creator.clean()
1127 if self.image_creator:
1129 self.image_creator.clean()
1133 if self.flavor_creator:
1135 self.flavor_creator.clean()
1141 os.remove(self.tmp_file.name)
1145 super(self.__class__, self).__clean__()
1147 def test_stack_failure(self):
1149 Tests the creation of an OpenStack stack from Heat template file that
1150 should always fail due to too many CPU cores
1153 # Set the default stack settings, then set any custom parameters sent
1155 stack_settings = StackConfig(
1156 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1157 template_path=self.heat_tmplt_path,
1158 env_values=self.env_values)
1159 self.stack_creator = OpenStackHeatStack(
1160 self.heat_creds, stack_settings)
1162 with self.assertRaises(StackError):
1164 self.stack_creator.create()
1166 resources = heat_utils.get_resources(
1167 self.heat_cli, self.stack_creator.get_stack().id)
1170 for resource in resources:
1171 if (resource.status ==
1172 snaps.config.stack.STATUS_CREATE_COMPLETE):
1174 self.assertTrue(found)