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 import create_stack
39 from snaps.openstack.create_stack import (
40 StackSettings, StackCreationError, StackError, OpenStackHeatStack)
41 from snaps.openstack.tests import openstack_tests, create_instance_tests
42 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
43 from snaps.openstack.utils import (
44 heat_utils, neutron_utils, nova_utils, keystone_utils)
46 __author__ = 'spisarski'
48 logger = logging.getLogger('create_stack_tests')
51 class StackSettingsUnitTests(unittest.TestCase):
53 Tests the construction of the StackSettings class
56 def test_no_params(self):
57 with self.assertRaises(StackConfigError):
60 def test_empty_config(self):
61 with self.assertRaises(StackConfigError):
62 StackSettings(**dict())
64 def test_name_only(self):
65 with self.assertRaises(StackConfigError):
66 StackSettings(name='foo')
68 def test_config_with_name_only(self):
69 with self.assertRaises(StackConfigError):
70 StackSettings(**{'name': 'foo'})
72 def test_config_minimum_template(self):
73 settings = StackSettings(**{'name': 'stack', 'template': 'foo'})
74 self.assertEqual('stack', settings.name)
75 self.assertEqual('foo', settings.template)
76 self.assertIsNone(settings.template_path)
77 self.assertIsNone(settings.env_values)
78 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
79 settings.stack_create_timeout)
81 def test_config_minimum_template_path(self):
82 settings = StackSettings(**{'name': 'stack', 'template_path': 'foo'})
83 self.assertEqual('stack', settings.name)
84 self.assertIsNone(settings.template)
85 self.assertEqual('foo', settings.template_path)
86 self.assertIsNone(settings.env_values)
87 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
88 settings.stack_create_timeout)
90 def test_minimum_template(self):
91 settings = StackSettings(name='stack', template='foo')
92 self.assertEqual('stack', settings.name)
93 self.assertEqual('foo', settings.template)
94 self.assertIsNone(settings.template_path)
95 self.assertIsNone(settings.env_values)
96 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
97 settings.stack_create_timeout)
99 def test_minimum_template_path(self):
100 settings = StackSettings(name='stack', template_path='foo')
101 self.assertEqual('stack', settings.name)
102 self.assertEqual('foo', settings.template_path)
103 self.assertIsNone(settings.template)
104 self.assertIsNone(settings.env_values)
105 self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT,
106 settings.stack_create_timeout)
109 env_values = {'foo': 'bar'}
110 settings = StackSettings(name='stack', template='bar',
111 template_path='foo', env_values=env_values,
112 stack_create_timeout=999)
113 self.assertEqual('stack', settings.name)
114 self.assertEqual('bar', settings.template)
115 self.assertEqual('foo', settings.template_path)
116 self.assertEqual(env_values, settings.env_values)
117 self.assertEqual(999, settings.stack_create_timeout)
119 def test_config_all(self):
120 env_values = {'foo': 'bar'}
121 settings = StackSettings(
122 **{'name': 'stack', 'template': 'bar', 'template_path': 'foo',
123 'env_values': env_values, 'stack_create_timeout': 999})
124 self.assertEqual('stack', settings.name)
125 self.assertEqual('bar', settings.template)
126 self.assertEqual('foo', settings.template_path)
127 self.assertEqual(env_values, settings.env_values)
128 self.assertEqual(999, settings.stack_create_timeout)
131 class CreateStackSuccessTests(OSIntegrationTestCase):
133 Tests for the OpenStackHeatStack class defined in create_stack.py
137 self.user_roles = ['heat_stack_owner']
139 super(self.__class__, self).__start__()
141 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
143 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
144 self.stack_creator = None
146 self.image_creator = OpenStackImage(
147 self.os_creds, openstack_tests.cirros_image_settings(
148 name=self.guid + '-image',
149 image_metadata=self.image_metadata))
150 self.image_creator.create()
153 flavor_config = openstack_tests.get_flavor_config(
154 name=self.guid + '-flavor-name', ram=256, disk=10,
155 vcpus=1, metadata=self.flavor_metadata)
156 self.flavor_creator = OpenStackFlavor(
157 self.admin_os_creds, flavor_config)
158 self.flavor_creator.create()
160 self.network_name = self.guid + '-net'
161 self.subnet_name = self.guid + '-subnet'
162 self.vm_inst_name = self.guid + '-inst'
165 'image_name': self.image_creator.image_settings.name,
166 'flavor_name': self.flavor_creator.flavor_settings.name,
167 'net_name': self.network_name,
168 'subnet_name': self.subnet_name,
169 'inst_name': self.vm_inst_name}
171 self.heat_tmplt_path = pkg_resources.resource_filename(
172 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
176 Cleans the stack and downloaded stack file
178 if self.stack_creator:
180 self.stack_creator.clean()
184 if self.image_creator:
186 self.image_creator.clean()
190 if self.flavor_creator:
192 self.flavor_creator.clean()
196 super(self.__class__, self).__clean__()
198 def test_create_stack_template_file(self):
200 Tests the creation of an OpenStack stack from Heat template file.
203 # Set the default stack settings, then set any custom parameters sent
205 stack_settings = StackConfig(
206 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
207 template_path=self.heat_tmplt_path,
208 env_values=self.env_values)
209 self.stack_creator = OpenStackHeatStack(
210 self.os_creds, stack_settings)
211 created_stack = self.stack_creator.create()
212 self.assertIsNotNone(created_stack)
214 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
216 self.assertIsNotNone(retrieved_stack)
217 self.assertEqual(created_stack.name, retrieved_stack.name)
218 self.assertEqual(created_stack.id, retrieved_stack.id)
219 self.assertEqual(0, len(self.stack_creator.get_outputs()))
221 derived_creator = create_stack.generate_creator(
222 self.os_creds, retrieved_stack,
223 [self.image_creator.image_settings])
224 derived_stack = derived_creator.get_stack()
225 self.assertEqual(retrieved_stack, derived_stack)
227 def test_create_stack_short_timeout(self):
229 Tests the creation of an OpenStack stack from Heat template file.
232 # Set the default stack settings, then set any custom parameters sent
234 stack_settings = StackConfig(
235 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
236 template_path=self.heat_tmplt_path,
237 env_values=self.env_values, stack_create_timeout=0)
239 self.stack_creator = OpenStackHeatStack(
240 self.os_creds, stack_settings)
241 with self.assertRaises(StackCreationError):
242 self.stack_creator.create()
244 def test_create_stack_template_dict(self):
246 Tests the creation of an OpenStack stack from a heat dict() object.
249 # Set the default stack settings, then set any custom parameters sent
251 template_dict = heat_utils.parse_heat_template_str(
252 file_utils.read_file(self.heat_tmplt_path))
253 stack_settings = StackConfig(
254 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
255 template=template_dict,
256 env_values=self.env_values)
257 self.stack_creator = OpenStackHeatStack(
258 self.os_creds, stack_settings)
259 created_stack = self.stack_creator.create()
260 self.assertIsNotNone(created_stack)
262 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
264 self.assertIsNotNone(retrieved_stack)
265 self.assertEqual(created_stack.name, retrieved_stack.name)
266 self.assertEqual(created_stack.id, retrieved_stack.id)
267 self.assertEqual(0, len(self.stack_creator.get_outputs()))
269 def test_create_delete_stack(self):
271 Tests the creation then deletion of an OpenStack stack to ensure
272 clean() does not raise an Exception.
275 template_dict = heat_utils.parse_heat_template_str(
276 file_utils.read_file(self.heat_tmplt_path))
277 stack_settings = StackConfig(
278 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
279 template=template_dict,
280 env_values=self.env_values)
281 self.stack_creator = OpenStackHeatStack(
282 self.os_creds, stack_settings)
283 created_stack = self.stack_creator.create()
284 self.assertIsNotNone(created_stack)
286 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
288 self.assertIsNotNone(retrieved_stack)
289 self.assertEqual(created_stack.name, retrieved_stack.name)
290 self.assertEqual(created_stack.id, retrieved_stack.id)
291 self.assertEqual(0, len(self.stack_creator.get_outputs()))
292 self.assertEqual(snaps.config.stack.STATUS_CREATE_COMPLETE,
293 self.stack_creator.get_status())
295 # Delete Stack manually
296 heat_utils.delete_stack(self.heat_cli, created_stack)
298 end_time = time.time() + 90
300 while time.time() < end_time:
301 status = heat_utils.get_stack_status(self.heat_cli,
303 if status == snaps.config.stack.STATUS_DELETE_COMPLETE:
307 self.assertTrue(deleted)
309 # Must not throw an exception when attempting to cleanup non-existent
311 self.stack_creator.clean()
312 self.assertIsNone(self.stack_creator.get_stack())
314 def test_create_same_stack(self):
316 Tests the creation of an OpenStack stack when the stack already exists.
319 template_dict = heat_utils.parse_heat_template_str(
320 file_utils.read_file(self.heat_tmplt_path))
321 stack_settings = StackConfig(
322 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
323 template=template_dict,
324 env_values=self.env_values)
325 self.stack_creator = OpenStackHeatStack(
326 self.os_creds, stack_settings)
327 created_stack1 = self.stack_creator.create()
329 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
331 self.assertIsNotNone(retrieved_stack)
332 self.assertEqual(created_stack1.name, retrieved_stack.name)
333 self.assertEqual(created_stack1.id, retrieved_stack.id)
334 self.assertEqual(0, len(self.stack_creator.get_outputs()))
336 # Should be retrieving the instance data
337 stack_creator2 = OpenStackHeatStack(self.os_creds, stack_settings)
338 stack2 = stack_creator2.create()
339 self.assertEqual(created_stack1.id, stack2.id)
341 def test_retrieve_network_creators(self):
343 Tests the creation of an OpenStack stack from Heat template file and
344 the retrieval of the network creator.
346 stack_settings = StackConfig(
347 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
348 template_path=self.heat_tmplt_path,
349 env_values=self.env_values)
350 self.stack_creator = OpenStackHeatStack(
351 self.os_creds, stack_settings)
352 created_stack = self.stack_creator.create()
353 self.assertIsNotNone(created_stack)
355 net_creators = self.stack_creator.get_network_creators()
356 self.assertIsNotNone(net_creators)
357 self.assertEqual(1, len(net_creators))
358 self.assertEqual(self.network_name, net_creators[0].get_network().name)
360 # Need to use 'admin' creds as heat creates objects under it's own
362 neutron = neutron_utils.neutron_client(
363 self.os_creds, self.os_session)
364 keystone = keystone_utils.keystone_client(
365 self.os_creds, self.os_session)
366 net_by_name = neutron_utils.get_network(
367 neutron, keystone, network_name=net_creators[0].get_network().name)
368 self.assertEqual(net_creators[0].get_network(), net_by_name)
369 self.assertIsNotNone(neutron_utils.get_network_by_id(
370 neutron, net_creators[0].get_network().id))
372 self.assertEqual(1, len(net_creators[0].get_network().subnets))
373 subnet = net_creators[0].get_network().subnets[0]
374 subnet_by_name = neutron_utils.get_subnet(
375 neutron, net_creators[0].get_network(), subnet_name=subnet.name)
376 self.assertEqual(subnet, subnet_by_name)
378 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
379 self.assertIsNotNone(subnet_by_id)
380 self.assertEqual(subnet_by_name, subnet_by_id)
382 def test_retrieve_vm_inst_creators(self):
384 Tests the creation of an OpenStack stack from Heat template file and
385 the retrieval of the network creator.
387 stack_settings = StackConfig(
388 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
389 template_path=self.heat_tmplt_path,
390 env_values=self.env_values)
391 self.stack_creator = OpenStackHeatStack(
392 self.os_creds, stack_settings)
393 created_stack = self.stack_creator.create()
394 self.assertIsNotNone(created_stack)
396 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
397 self.assertIsNotNone(vm_inst_creators)
398 self.assertEqual(1, len(vm_inst_creators))
399 self.assertEqual(self.vm_inst_name,
400 vm_inst_creators[0].get_vm_inst().name)
402 nova = nova_utils.nova_client(self.os_creds, self.os_session)
403 neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
404 keystone = keystone_utils.keystone_client(self.os_creds, self.os_session)
405 vm_inst_by_name = nova_utils.get_server(
406 nova, neutron, keystone,
407 server_name=vm_inst_creators[0].get_vm_inst().name)
409 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
410 self.assertIsNotNone(nova_utils.get_server_object_by_id(
411 nova, neutron, keystone, vm_inst_creators[0].get_vm_inst().id))
414 class CreateStackFloatingIpTests(OSIntegrationTestCase):
416 Tests to ensure that floating IPs can be accessed via an
417 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
421 self.user_roles = ['heat_stack_owner', 'admin']
423 super(self.__class__, self).__start__()
425 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
427 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
428 self.stack_creator = None
430 self.image_creator = OpenStackImage(
431 self.os_creds, openstack_tests.cirros_image_settings(
432 name=self.guid + '-image',
433 image_metadata=self.image_metadata))
434 self.image_creator.create()
436 self.network_name = self.guid + '-net'
437 self.subnet_name = self.guid + '-subnet'
438 self.flavor1_name = self.guid + '-flavor1'
439 self.flavor2_name = self.guid + '-flavor2'
440 self.sec_grp_name = self.guid + '-sec_grp'
441 self.vm_inst1_name = self.guid + '-inst1'
442 self.vm_inst2_name = self.guid + '-inst2'
443 self.keypair_name = self.guid + '-kp'
446 'image1_name': self.image_creator.image_settings.name,
447 'image2_name': self.image_creator.image_settings.name,
448 'flavor1_name': self.flavor1_name,
449 'flavor2_name': self.flavor2_name,
450 'net_name': self.network_name,
451 'subnet_name': self.subnet_name,
452 'inst1_name': self.vm_inst1_name,
453 'inst2_name': self.vm_inst2_name,
454 'keypair_name': self.keypair_name,
455 'external_net_name': self.ext_net_name,
456 'security_group_name': self.sec_grp_name}
458 self.heat_tmplt_path = pkg_resources.resource_filename(
459 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
461 self.vm_inst_creators = list()
465 Cleans the stack and downloaded stack file
467 if self.stack_creator:
469 self.stack_creator.clean()
473 if self.image_creator:
475 self.image_creator.clean()
479 for vm_inst_creator in self.vm_inst_creators:
481 keypair_settings = vm_inst_creator.keypair_settings
482 if keypair_settings and keypair_settings.private_filepath:
483 expanded_path = os.path.expanduser(
484 keypair_settings.private_filepath)
485 os.chmod(expanded_path, 0o755)
486 os.remove(expanded_path)
490 super(self.__class__, self).__clean__()
492 def test_connect_via_ssh_heat_vm(self):
494 Tests the creation of an OpenStack stack from Heat template file and
495 the retrieval of two VM instance creators and attempt to connect via
496 SSH to the first one with a floating IP.
498 stack_settings = StackConfig(
499 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
500 template_path=self.heat_tmplt_path,
501 env_values=self.env_values)
502 self.stack_creator = OpenStackHeatStack(
503 self.os_creds, stack_settings,
504 [self.image_creator.image_settings])
505 created_stack = self.stack_creator.create()
506 self.assertIsNotNone(created_stack)
508 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
509 heat_keypair_option='private_key')
510 self.assertIsNotNone(self.vm_inst_creators)
511 self.assertEqual(2, len(self.vm_inst_creators))
513 for vm_inst_creator in self.vm_inst_creators:
514 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
516 create_instance_tests.validate_ssh_client(vm_inst_creator))
518 vm_settings = vm_inst_creator.instance_settings
519 self.assertEqual(0, len(vm_settings.floating_ip_settings))
521 def test_connect_via_ssh_heat_vm_derived(self):
523 Tests the the retrieval of two VM instance creators from a derived
524 OpenStackHeatStack object and attempt to connect via
525 SSH to the first one with a floating IP.
527 stack_settings = StackConfig(
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 = OpenStackHeatStack(
532 self.os_creds, stack_settings,
533 [self.image_creator.image_settings])
534 created_stack = self.stack_creator.create()
535 self.assertIsNotNone(created_stack)
537 derived_stack = create_stack.generate_creator(
538 self.os_creds, created_stack,
539 [self.image_creator.image_settings])
541 self.vm_inst_creators = derived_stack.get_vm_inst_creators(
542 heat_keypair_option='private_key')
543 self.assertIsNotNone(self.vm_inst_creators)
544 self.assertEqual(2, len(self.vm_inst_creators))
546 for vm_inst_creator in self.vm_inst_creators:
547 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
549 create_instance_tests.validate_ssh_client(vm_inst_creator))
551 vm_settings = vm_inst_creator.instance_settings
552 self.assertEqual(0, len(vm_settings.floating_ip_settings))
555 class CreateStackNestedResourceTests(OSIntegrationTestCase):
557 Tests to ensure that nested heat templates work
561 self.user_roles = ['heat_stack_owner']
563 super(self.__class__, self).__start__()
565 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
567 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
568 self.stack_creator = None
570 self.image_creator = OpenStackImage(
571 self.os_creds, openstack_tests.cirros_image_settings(
572 name="{}-{}".format(self.guid, 'image'),
573 image_metadata=self.image_metadata))
574 self.image_creator.create()
576 flavor_config = openstack_tests.get_flavor_config(
577 name="{}-{}".format(self.guid, 'flavor-name'), ram=256, disk=10,
578 vcpus=1, metadata=self.flavor_metadata)
579 self.flavor_creator = OpenStackFlavor(
580 self.admin_os_creds, flavor_config)
581 self.flavor_creator.create()
584 'network_name': self.guid + '-network',
585 'public_network': self.ext_net_name,
586 'agent_image': self.image_creator.image_settings.name,
587 'agent_flavor': self.flavor_creator.flavor_settings.name,
588 'key_name': self.guid + '-key',
591 heat_tmplt_path = pkg_resources.resource_filename(
592 'snaps.openstack.tests.heat', 'agent-group.yaml')
593 heat_resource_path = pkg_resources.resource_filename(
594 'snaps.openstack.tests.heat', 'agent.yaml')
596 stack_settings = StackConfig(
598 self.__class__.__name__, str(self.guid) + '-stack'),
599 template_path=heat_tmplt_path,
600 resource_files=[heat_resource_path],
601 env_values=env_values)
603 self.stack_creator = OpenStackHeatStack(
604 self.os_creds, stack_settings,
605 [self.image_creator.image_settings])
607 self.vm_inst_creators = list()
611 Cleans the stack and downloaded stack file
613 if self.stack_creator:
615 self.stack_creator.clean()
619 if self.image_creator:
621 self.image_creator.clean()
625 if self.flavor_creator:
627 self.flavor_creator.clean()
631 for vm_inst_creator in self.vm_inst_creators:
633 keypair_settings = vm_inst_creator.keypair_settings
634 if keypair_settings and keypair_settings.private_filepath:
635 expanded_path = os.path.expanduser(
636 keypair_settings.private_filepath)
637 os.chmod(expanded_path, 0o755)
638 os.remove(expanded_path)
642 super(self.__class__, self).__clean__()
644 def test_nested(self):
646 Tests the creation of an OpenStack stack from Heat template file and
647 the retrieval of two VM instance creators and attempt to connect via
648 SSH to the first one with a floating IP.
650 created_stack = self.stack_creator.create()
651 self.assertIsNotNone(created_stack)
653 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
654 heat_keypair_option='private_key')
655 self.assertIsNotNone(self.vm_inst_creators)
656 self.assertEqual(1, len(self.vm_inst_creators))
658 for vm_inst_creator in self.vm_inst_creators:
660 create_instance_tests.validate_ssh_client(vm_inst_creator))
663 class CreateStackRouterTests(OSIntegrationTestCase):
665 Tests for the CreateStack class defined in create_stack.py where the
666 target is a Network, Subnet, and Router
671 Instantiates the CreateStack object that is responsible for downloading
672 and creating an OS stack file within OpenStack
674 self.user_roles = ['heat_stack_owner']
676 super(self.__class__, self).__start__()
678 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
680 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
681 self.neutron = neutron_utils.neutron_client(
682 self.os_creds, self.os_session)
683 self.stack_creator = None
685 self.net_name = self.guid + '-net'
686 self.subnet_name = self.guid + '-subnet'
687 self.router_name = self.guid + '-router'
690 'net_name': self.net_name,
691 'subnet_name': self.subnet_name,
692 'router_name': self.router_name,
693 'external_net_name': self.ext_net_name}
695 self.heat_tmplt_path = pkg_resources.resource_filename(
696 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
698 stack_settings = StackConfig(
699 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
700 template_path=self.heat_tmplt_path,
701 env_values=self.env_values)
702 self.stack_creator = OpenStackHeatStack(
703 self.os_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_router_creator(self):
721 Tests the creation of an OpenStack stack from Heat template file and
722 the retrieval of an OpenStackRouter creator/state machine instance
724 router_creators = self.stack_creator.get_router_creators()
725 self.assertEqual(1, len(router_creators))
727 creator = router_creators[0]
728 self.assertEqual(self.router_name, creator.router_settings.name)
730 router = creator.get_router()
732 ext_net = neutron_utils.get_network(
733 self.neutron, self.keystone, network_name=self.ext_net_name)
734 self.assertEqual(ext_net.id, router.external_network_id)
737 class CreateStackVolumeTests(OSIntegrationTestCase):
739 Tests to ensure that floating IPs can be accessed via an
740 OpenStackVolume object obtained from the OpenStackHeatStack instance
745 self.user_roles = ['heat_stack_owner', 'admin']
747 super(self.__class__, self).__start__()
749 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
751 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
752 self.stack_creator = None
754 self.volume_name = self.guid + '-volume'
755 self.volume_type_name = self.guid + '-volume-type'
758 'volume_name': self.volume_name,
759 'volume_type_name': self.volume_type_name}
761 self.heat_tmplt_path = pkg_resources.resource_filename(
762 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
764 stack_settings = StackConfig(
765 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
766 template_path=self.heat_tmplt_path,
767 env_values=self.env_values)
768 self.stack_creator = OpenStackHeatStack(
769 self.os_creds, stack_settings)
770 self.created_stack = self.stack_creator.create()
771 self.assertIsNotNone(self.created_stack)
775 Cleans the stack and downloaded stack file
777 if self.stack_creator:
779 self.stack_creator.clean()
783 super(self.__class__, self).__clean__()
785 def test_retrieve_volume_creator(self):
787 Tests the creation of an OpenStack stack from Heat template file and
788 the retrieval of an OpenStackVolume creator/state machine instance
790 volume_creators = self.stack_creator.get_volume_creators()
791 self.assertEqual(1, len(volume_creators))
793 creator = volume_creators[0]
794 self.assertEqual(self.volume_name, creator.volume_settings.name)
795 self.assertEqual(self.volume_name, creator.get_volume().name)
796 self.assertEqual(self.volume_type_name,
797 creator.volume_settings.type_name)
798 self.assertEqual(self.volume_type_name, creator.get_volume().type)
799 self.assertEqual(1, creator.volume_settings.size)
800 self.assertEqual(1, creator.get_volume().size)
802 def test_retrieve_volume_type_creator(self):
804 Tests the creation of an OpenStack stack from Heat template file and
805 the retrieval of an OpenStackVolume creator/state machine instance
807 volume_type_creators = self.stack_creator.get_volume_type_creators()
808 self.assertEqual(1, len(volume_type_creators))
810 creator = volume_type_creators[0]
811 self.assertIsNotNone(creator)
813 volume_type = creator.get_volume_type()
814 self.assertIsNotNone(volume_type)
816 self.assertEqual(self.volume_type_name, volume_type.name)
817 self.assertTrue(volume_type.public)
818 self.assertIsNone(volume_type.qos_spec)
820 # TODO - Add encryption back and find out why it broke in Pike
821 # encryption = volume_type.encryption
822 # self.assertIsNotNone(encryption)
823 # self.assertIsNone(encryption.cipher)
824 # self.assertEqual('front-end', encryption.control_location)
825 # self.assertIsNone(encryption.key_size)
826 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
827 # encryption.provider)
828 # self.assertEqual(volume_type.id, encryption.volume_type_id)
831 class CreateStackFlavorTests(OSIntegrationTestCase):
833 Tests to ensure that floating IPs can be accessed via an
834 OpenStackFlavor object obtained from the OpenStackHeatStack instance
839 self.user_roles = ['heat_stack_owner', 'admin']
841 super(self.__class__, self).__start__()
843 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
845 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
846 self.stack_creator = None
848 self.heat_tmplt_path = pkg_resources.resource_filename(
849 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
851 stack_settings = StackConfig(
852 name=self.guid + '-stack',
853 template_path=self.heat_tmplt_path)
854 self.stack_creator = OpenStackHeatStack(
855 self.os_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_flavor_creator(self):
873 Tests the creation of an OpenStack stack from Heat template file and
874 the retrieval of an OpenStackVolume creator/state machine instance
876 flavor_creators = self.stack_creator.get_flavor_creators()
877 self.assertEqual(1, len(flavor_creators))
879 creator = flavor_creators[0]
880 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
881 self.assertEqual(1024, creator.get_flavor().ram)
882 self.assertEqual(200, creator.get_flavor().disk)
883 self.assertEqual(8, creator.get_flavor().vcpus)
884 self.assertEqual(0, creator.get_flavor().ephemeral)
885 self.assertIsNone(creator.get_flavor().swap)
886 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
887 self.assertTrue(creator.get_flavor().is_public)
890 class CreateStackKeypairTests(OSIntegrationTestCase):
892 Tests to ensure that floating IPs can be accessed via an
893 OpenStackKeypair object obtained from the OpenStackHeatStack instance
898 self.user_roles = ['heat_stack_owner']
900 super(self.__class__, self).__start__()
902 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
904 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
905 self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
906 self.stack_creator = None
908 self.keypair_name = self.guid + '-kp'
911 'keypair_name': self.keypair_name}
913 self.heat_tmplt_path = pkg_resources.resource_filename(
914 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
916 stack_settings = StackConfig(
917 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
918 template_path=self.heat_tmplt_path,
919 env_values=self.env_values)
920 self.stack_creator = OpenStackHeatStack(
921 self.os_creds, stack_settings)
922 self.created_stack = self.stack_creator.create()
923 self.assertIsNotNone(self.created_stack)
925 self.keypair_creators = list()
929 Cleans the stack and downloaded stack file
931 if self.stack_creator:
933 self.stack_creator.clean()
936 for keypair_creator in self.keypair_creators:
938 keypair_creator.clean()
942 super(self.__class__, self).__clean__()
944 def test_retrieve_keypair_creator(self):
946 Tests the creation of an OpenStack stack from Heat template file and
947 the retrieval of an OpenStackKeypair creator/state machine instance
949 self.kp_creators = self.stack_creator.get_keypair_creators(
951 self.assertEqual(1, len(self.kp_creators))
953 self.keypair_creator = self.kp_creators[0]
955 self.assertEqual(self.keypair_name,
956 self.keypair_creator.get_keypair().name)
957 self.assertIsNotNone(
958 self.keypair_creator.keypair_settings.private_filepath)
960 private_file_contents = file_utils.read_file(
961 self.keypair_creator.keypair_settings.private_filepath)
962 self.assertTrue(private_file_contents.startswith(
963 '-----BEGIN RSA PRIVATE KEY-----'))
965 keypair = nova_utils.get_keypair_by_id(
966 self.nova, self.keypair_creator.get_keypair().id)
967 self.assertIsNotNone(keypair)
968 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
971 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
973 Tests for the OpenStackHeatStack class to ensure it returns an
974 OpenStackSecurityGroup object
979 Instantiates the CreateStack object that is responsible for downloading
980 and creating an OS stack file within OpenStack
982 self.user_roles = ['heat_stack_owner']
984 super(self.__class__, self).__start__()
986 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
988 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
989 self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
990 self.stack_creator = None
992 self.security_group_name = self.guid + '-sec-grp'
995 'security_group_name': self.security_group_name}
997 self.heat_tmplt_path = pkg_resources.resource_filename(
998 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
1000 stack_settings = StackConfig(
1001 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1002 template_path=self.heat_tmplt_path,
1003 env_values=self.env_values)
1004 self.stack_creator = OpenStackHeatStack(
1005 self.os_creds, stack_settings)
1006 self.created_stack = self.stack_creator.create()
1007 self.assertIsNotNone(self.created_stack)
1011 Cleans the stack and downloaded stack file
1013 if self.stack_creator:
1015 self.stack_creator.clean()
1019 super(self.__class__, self).__clean__()
1021 def test_retrieve_security_group_creator(self):
1023 Tests the creation of an OpenStack stack from Heat template file and
1024 the retrieval of an OpenStackSecurityGroup creator/state machine
1027 sec_grp_creators = self.stack_creator.get_security_group_creators()
1028 self.assertEqual(1, len(sec_grp_creators))
1030 creator = sec_grp_creators[0]
1031 sec_grp = creator.get_security_group()
1033 self.assertEqual(self.security_group_name, sec_grp.name)
1034 self.assertEqual('Test description', sec_grp.description)
1035 self.assertEqual(2, len(sec_grp.rules))
1037 has_ssh_rule = False
1038 has_icmp_rule = False
1040 for rule in sec_grp.rules:
1041 if (rule.security_group_id == sec_grp.id
1042 and rule.direction == 'egress'
1043 and rule.ethertype == 'IPv4'
1044 and rule.port_range_min == 22
1045 and rule.port_range_max == 22
1046 and rule.protocol == 'tcp'
1047 and rule.remote_group_id is None
1048 and rule.remote_ip_prefix == '0.0.0.0/0'):
1050 if (rule.security_group_id == sec_grp.id
1051 and rule.direction == 'ingress'
1052 and rule.ethertype == 'IPv4'
1053 and rule.port_range_min is None
1054 and rule.port_range_max is None
1055 and rule.protocol == 'icmp'
1056 and rule.remote_group_id is None
1057 and rule.remote_ip_prefix == '0.0.0.0/0'):
1058 has_icmp_rule = True
1060 self.assertTrue(has_ssh_rule)
1061 self.assertTrue(has_icmp_rule)
1064 class CreateStackNegativeTests(OSIntegrationTestCase):
1066 Negative test cases for the OpenStackHeatStack class with poor
1071 self.user_roles = ['heat_stack_owner']
1073 super(self.__class__, self).__start__()
1075 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1076 self.stack_creator = None
1077 self.heat_tmplt_path = pkg_resources.resource_filename(
1078 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1081 if self.stack_creator:
1082 self.stack_creator.clean()
1084 super(self.__class__, self).__clean__()
1086 def test_missing_dependencies(self):
1088 Expect an StackCreationError when the stack file does not exist
1090 stack_settings = StackConfig(name=self.stack_name,
1091 template_path=self.heat_tmplt_path)
1092 self.stack_creator = OpenStackHeatStack(
1093 self.os_creds, stack_settings)
1094 with self.assertRaises(HTTPBadRequest):
1095 self.stack_creator.create()
1097 def test_bad_stack_file(self):
1099 Expect an StackCreationError when the stack file does not exist
1101 stack_settings = StackConfig(
1102 name=self.stack_name, template_path='foo')
1103 self.stack_creator = OpenStackHeatStack(
1104 self.os_creds, stack_settings)
1105 with self.assertRaises(IOError):
1106 self.stack_creator.create()
1109 class CreateStackFailureTests(OSIntegrationTestCase):
1111 Tests for the OpenStackHeatStack class defined in create_stack.py for
1112 when failures occur. Failures are being triggered by allocating 1 million
1117 self.user_roles = ['heat_stack_owner']
1119 super(self.__class__, self).__start__()
1121 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1123 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
1124 self.stack_creator = None
1126 self.tmp_file = file_utils.save_string_to_file(
1127 ' ', str(uuid.uuid4()) + '-bad-image')
1128 self.image_creator = OpenStackImage(
1129 self.os_creds, ImageConfig(
1130 name=self.guid + 'image', image_file=self.tmp_file.name,
1131 image_user='foo', img_format='qcow2'))
1132 self.image_creator.create()
1135 self.flavor_creator = OpenStackFlavor(
1136 self.admin_os_creds,
1138 name=self.guid + '-flavor-name', ram=256, disk=10,
1140 self.flavor_creator.create()
1142 self.network_name = self.guid + '-net'
1143 self.subnet_name = self.guid + '-subnet'
1144 self.vm_inst_name = self.guid + '-inst'
1147 'image_name': self.image_creator.image_settings.name,
1148 'flavor_name': self.flavor_creator.flavor_settings.name,
1149 'net_name': self.network_name,
1150 'subnet_name': self.subnet_name,
1151 'inst_name': self.vm_inst_name}
1153 self.heat_tmplt_path = pkg_resources.resource_filename(
1154 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1158 Cleans the stack and downloaded stack file
1160 if self.stack_creator:
1162 self.stack_creator.clean()
1166 if self.image_creator:
1168 self.image_creator.clean()
1172 if self.flavor_creator:
1174 self.flavor_creator.clean()
1180 os.remove(self.tmp_file.name)
1184 super(self.__class__, self).__clean__()
1186 def test_stack_failure(self):
1188 Tests the creation of an OpenStack stack from Heat template file that
1189 should always fail due to too many CPU cores
1192 # Set the default stack settings, then set any custom parameters sent
1194 stack_settings = StackConfig(
1195 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1196 template_path=self.heat_tmplt_path,
1197 env_values=self.env_values)
1198 self.stack_creator = OpenStackHeatStack(
1199 self.os_creds, stack_settings)
1201 with self.assertRaises(StackError):
1203 self.stack_creator.create()
1205 resources = heat_utils.get_resources(
1206 self.heat_cli, self.stack_creator.get_stack().id)
1209 for resource in resources:
1210 if (resource.status ==
1211 snaps.config.stack.STATUS_CREATE_COMPLETE):
1213 self.assertTrue(found)