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=self.guid + '-image',
573 image_metadata=self.image_metadata))
574 self.image_creator.create()
576 self.flavor_creator = OpenStackFlavor(
579 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
580 self.flavor_creator.create()
583 'network_name': self.guid + '-network',
584 'public_network': self.ext_net_name,
585 'agent_image': self.image_creator.image_settings.name,
586 'agent_flavor': self.flavor_creator.flavor_settings.name,
587 'key_name': self.guid + '-key',
590 heat_tmplt_path = pkg_resources.resource_filename(
591 'snaps.openstack.tests.heat', 'agent-group.yaml')
592 heat_resource_path = pkg_resources.resource_filename(
593 'snaps.openstack.tests.heat', 'agent.yaml')
595 stack_settings = StackConfig(
596 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
597 template_path=heat_tmplt_path,
598 resource_files=[heat_resource_path],
599 env_values=env_values)
601 self.stack_creator = OpenStackHeatStack(
602 self.os_creds, stack_settings,
603 [self.image_creator.image_settings])
605 self.vm_inst_creators = list()
609 Cleans the stack and downloaded stack file
611 if self.stack_creator:
613 self.stack_creator.clean()
617 if self.image_creator:
619 self.image_creator.clean()
623 if self.flavor_creator:
625 self.flavor_creator.clean()
629 for vm_inst_creator in self.vm_inst_creators:
631 keypair_settings = vm_inst_creator.keypair_settings
632 if keypair_settings and keypair_settings.private_filepath:
633 expanded_path = os.path.expanduser(
634 keypair_settings.private_filepath)
635 os.chmod(expanded_path, 0o755)
636 os.remove(expanded_path)
640 super(self.__class__, self).__clean__()
642 def test_nested(self):
644 Tests the creation of an OpenStack stack from Heat template file and
645 the retrieval of two VM instance creators and attempt to connect via
646 SSH to the first one with a floating IP.
648 created_stack = self.stack_creator.create()
649 self.assertIsNotNone(created_stack)
651 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
652 heat_keypair_option='private_key')
653 self.assertIsNotNone(self.vm_inst_creators)
654 self.assertEqual(1, len(self.vm_inst_creators))
656 for vm_inst_creator in self.vm_inst_creators:
658 create_instance_tests.validate_ssh_client(vm_inst_creator))
661 class CreateStackRouterTests(OSIntegrationTestCase):
663 Tests for the CreateStack class defined in create_stack.py where the
664 target is a Network, Subnet, and Router
669 Instantiates the CreateStack object that is responsible for downloading
670 and creating an OS stack file within OpenStack
672 self.user_roles = ['heat_stack_owner']
674 super(self.__class__, self).__start__()
676 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
678 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
679 self.neutron = neutron_utils.neutron_client(
680 self.os_creds, self.os_session)
681 self.stack_creator = None
683 self.net_name = self.guid + '-net'
684 self.subnet_name = self.guid + '-subnet'
685 self.router_name = self.guid + '-router'
688 'net_name': self.net_name,
689 'subnet_name': self.subnet_name,
690 'router_name': self.router_name,
691 'external_net_name': self.ext_net_name}
693 self.heat_tmplt_path = pkg_resources.resource_filename(
694 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
696 stack_settings = StackConfig(
697 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
698 template_path=self.heat_tmplt_path,
699 env_values=self.env_values)
700 self.stack_creator = OpenStackHeatStack(
701 self.os_creds, stack_settings)
702 self.created_stack = self.stack_creator.create()
703 self.assertIsNotNone(self.created_stack)
707 Cleans the stack and downloaded stack file
709 if self.stack_creator:
711 self.stack_creator.clean()
715 super(self.__class__, self).__clean__()
717 def test_retrieve_router_creator(self):
719 Tests the creation of an OpenStack stack from Heat template file and
720 the retrieval of an OpenStackRouter creator/state machine instance
722 router_creators = self.stack_creator.get_router_creators()
723 self.assertEqual(1, len(router_creators))
725 creator = router_creators[0]
726 self.assertEqual(self.router_name, creator.router_settings.name)
728 router = creator.get_router()
730 ext_net = neutron_utils.get_network(
731 self.neutron, self.keystone, network_name=self.ext_net_name)
732 self.assertEqual(ext_net.id, router.external_network_id)
735 class CreateStackVolumeTests(OSIntegrationTestCase):
737 Tests to ensure that floating IPs can be accessed via an
738 OpenStackVolume object obtained from the OpenStackHeatStack instance
743 self.user_roles = ['heat_stack_owner', 'admin']
745 super(self.__class__, self).__start__()
747 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
749 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
750 self.stack_creator = None
752 self.volume_name = self.guid + '-volume'
753 self.volume_type_name = self.guid + '-volume-type'
756 'volume_name': self.volume_name,
757 'volume_type_name': self.volume_type_name}
759 self.heat_tmplt_path = pkg_resources.resource_filename(
760 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
762 stack_settings = StackConfig(
763 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
764 template_path=self.heat_tmplt_path,
765 env_values=self.env_values)
766 self.stack_creator = OpenStackHeatStack(
767 self.os_creds, stack_settings)
768 self.created_stack = self.stack_creator.create()
769 self.assertIsNotNone(self.created_stack)
773 Cleans the stack and downloaded stack file
775 if self.stack_creator:
777 self.stack_creator.clean()
781 super(self.__class__, self).__clean__()
783 def test_retrieve_volume_creator(self):
785 Tests the creation of an OpenStack stack from Heat template file and
786 the retrieval of an OpenStackVolume creator/state machine instance
788 volume_creators = self.stack_creator.get_volume_creators()
789 self.assertEqual(1, len(volume_creators))
791 creator = volume_creators[0]
792 self.assertEqual(self.volume_name, creator.volume_settings.name)
793 self.assertEqual(self.volume_name, creator.get_volume().name)
794 self.assertEqual(self.volume_type_name,
795 creator.volume_settings.type_name)
796 self.assertEqual(self.volume_type_name, creator.get_volume().type)
797 self.assertEqual(1, creator.volume_settings.size)
798 self.assertEqual(1, creator.get_volume().size)
800 def test_retrieve_volume_type_creator(self):
802 Tests the creation of an OpenStack stack from Heat template file and
803 the retrieval of an OpenStackVolume creator/state machine instance
805 volume_type_creators = self.stack_creator.get_volume_type_creators()
806 self.assertEqual(1, len(volume_type_creators))
808 creator = volume_type_creators[0]
809 self.assertIsNotNone(creator)
811 volume_type = creator.get_volume_type()
812 self.assertIsNotNone(volume_type)
814 self.assertEqual(self.volume_type_name, volume_type.name)
815 self.assertTrue(volume_type.public)
816 self.assertIsNone(volume_type.qos_spec)
818 # TODO - Add encryption back and find out why it broke in Pike
819 # encryption = volume_type.encryption
820 # self.assertIsNotNone(encryption)
821 # self.assertIsNone(encryption.cipher)
822 # self.assertEqual('front-end', encryption.control_location)
823 # self.assertIsNone(encryption.key_size)
824 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
825 # encryption.provider)
826 # self.assertEqual(volume_type.id, encryption.volume_type_id)
829 class CreateStackFlavorTests(OSIntegrationTestCase):
831 Tests to ensure that floating IPs can be accessed via an
832 OpenStackFlavor object obtained from the OpenStackHeatStack instance
837 self.user_roles = ['heat_stack_owner', 'admin']
839 super(self.__class__, self).__start__()
841 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
843 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
844 self.stack_creator = None
846 self.heat_tmplt_path = pkg_resources.resource_filename(
847 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
849 stack_settings = StackConfig(
850 name=self.guid + '-stack',
851 template_path=self.heat_tmplt_path)
852 self.stack_creator = OpenStackHeatStack(
853 self.os_creds, stack_settings)
854 self.created_stack = self.stack_creator.create()
855 self.assertIsNotNone(self.created_stack)
859 Cleans the stack and downloaded stack file
861 if self.stack_creator:
863 self.stack_creator.clean()
867 super(self.__class__, self).__clean__()
869 def test_retrieve_flavor_creator(self):
871 Tests the creation of an OpenStack stack from Heat template file and
872 the retrieval of an OpenStackVolume creator/state machine instance
874 flavor_creators = self.stack_creator.get_flavor_creators()
875 self.assertEqual(1, len(flavor_creators))
877 creator = flavor_creators[0]
878 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
879 self.assertEqual(1024, creator.get_flavor().ram)
880 self.assertEqual(200, creator.get_flavor().disk)
881 self.assertEqual(8, creator.get_flavor().vcpus)
882 self.assertEqual(0, creator.get_flavor().ephemeral)
883 self.assertIsNone(creator.get_flavor().swap)
884 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
885 self.assertTrue(creator.get_flavor().is_public)
888 class CreateStackKeypairTests(OSIntegrationTestCase):
890 Tests to ensure that floating IPs can be accessed via an
891 OpenStackKeypair object obtained from the OpenStackHeatStack instance
896 self.user_roles = ['heat_stack_owner']
898 super(self.__class__, self).__start__()
900 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
902 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
903 self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
904 self.stack_creator = None
906 self.keypair_name = self.guid + '-kp'
909 'keypair_name': self.keypair_name}
911 self.heat_tmplt_path = pkg_resources.resource_filename(
912 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
914 stack_settings = StackConfig(
915 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
916 template_path=self.heat_tmplt_path,
917 env_values=self.env_values)
918 self.stack_creator = OpenStackHeatStack(
919 self.os_creds, stack_settings)
920 self.created_stack = self.stack_creator.create()
921 self.assertIsNotNone(self.created_stack)
923 self.keypair_creators = list()
927 Cleans the stack and downloaded stack file
929 if self.stack_creator:
931 self.stack_creator.clean()
934 for keypair_creator in self.keypair_creators:
936 keypair_creator.clean()
940 super(self.__class__, self).__clean__()
942 def test_retrieve_keypair_creator(self):
944 Tests the creation of an OpenStack stack from Heat template file and
945 the retrieval of an OpenStackKeypair creator/state machine instance
947 self.kp_creators = self.stack_creator.get_keypair_creators(
949 self.assertEqual(1, len(self.kp_creators))
951 self.keypair_creator = self.kp_creators[0]
953 self.assertEqual(self.keypair_name,
954 self.keypair_creator.get_keypair().name)
955 self.assertIsNotNone(
956 self.keypair_creator.keypair_settings.private_filepath)
958 private_file_contents = file_utils.read_file(
959 self.keypair_creator.keypair_settings.private_filepath)
960 self.assertTrue(private_file_contents.startswith(
961 '-----BEGIN RSA PRIVATE KEY-----'))
963 keypair = nova_utils.get_keypair_by_id(
964 self.nova, self.keypair_creator.get_keypair().id)
965 self.assertIsNotNone(keypair)
966 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
969 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
971 Tests for the OpenStackHeatStack class to ensure it returns an
972 OpenStackSecurityGroup object
977 Instantiates the CreateStack object that is responsible for downloading
978 and creating an OS stack file within OpenStack
980 self.user_roles = ['heat_stack_owner']
982 super(self.__class__, self).__start__()
984 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
986 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
987 self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
988 self.stack_creator = None
990 self.security_group_name = self.guid + '-sec-grp'
993 'security_group_name': self.security_group_name}
995 self.heat_tmplt_path = pkg_resources.resource_filename(
996 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
998 stack_settings = StackConfig(
999 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1000 template_path=self.heat_tmplt_path,
1001 env_values=self.env_values)
1002 self.stack_creator = OpenStackHeatStack(
1003 self.os_creds, stack_settings)
1004 self.created_stack = self.stack_creator.create()
1005 self.assertIsNotNone(self.created_stack)
1009 Cleans the stack and downloaded stack file
1011 if self.stack_creator:
1013 self.stack_creator.clean()
1017 super(self.__class__, self).__clean__()
1019 def test_retrieve_security_group_creator(self):
1021 Tests the creation of an OpenStack stack from Heat template file and
1022 the retrieval of an OpenStackSecurityGroup creator/state machine
1025 sec_grp_creators = self.stack_creator.get_security_group_creators()
1026 self.assertEqual(1, len(sec_grp_creators))
1028 creator = sec_grp_creators[0]
1029 sec_grp = creator.get_security_group()
1031 self.assertEqual(self.security_group_name, sec_grp.name)
1032 self.assertEqual('Test description', sec_grp.description)
1033 self.assertEqual(2, len(sec_grp.rules))
1035 has_ssh_rule = False
1036 has_icmp_rule = False
1038 for rule in sec_grp.rules:
1039 if (rule.security_group_id == sec_grp.id
1040 and rule.direction == 'egress'
1041 and rule.ethertype == 'IPv4'
1042 and rule.port_range_min == 22
1043 and rule.port_range_max == 22
1044 and rule.protocol == 'tcp'
1045 and rule.remote_group_id is None
1046 and rule.remote_ip_prefix == '0.0.0.0/0'):
1048 if (rule.security_group_id == sec_grp.id
1049 and rule.direction == 'ingress'
1050 and rule.ethertype == 'IPv4'
1051 and rule.port_range_min is None
1052 and rule.port_range_max is None
1053 and rule.protocol == 'icmp'
1054 and rule.remote_group_id is None
1055 and rule.remote_ip_prefix == '0.0.0.0/0'):
1056 has_icmp_rule = True
1058 self.assertTrue(has_ssh_rule)
1059 self.assertTrue(has_icmp_rule)
1062 class CreateStackNegativeTests(OSIntegrationTestCase):
1064 Negative test cases for the OpenStackHeatStack class with poor
1069 self.user_roles = ['heat_stack_owner']
1071 super(self.__class__, self).__start__()
1073 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1074 self.stack_creator = None
1075 self.heat_tmplt_path = pkg_resources.resource_filename(
1076 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1079 if self.stack_creator:
1080 self.stack_creator.clean()
1082 super(self.__class__, self).__clean__()
1084 def test_missing_dependencies(self):
1086 Expect an StackCreationError when the stack file does not exist
1088 stack_settings = StackConfig(name=self.stack_name,
1089 template_path=self.heat_tmplt_path)
1090 self.stack_creator = OpenStackHeatStack(
1091 self.os_creds, stack_settings)
1092 with self.assertRaises(HTTPBadRequest):
1093 self.stack_creator.create()
1095 def test_bad_stack_file(self):
1097 Expect an StackCreationError when the stack file does not exist
1099 stack_settings = StackConfig(
1100 name=self.stack_name, template_path='foo')
1101 self.stack_creator = OpenStackHeatStack(
1102 self.os_creds, stack_settings)
1103 with self.assertRaises(IOError):
1104 self.stack_creator.create()
1107 class CreateStackFailureTests(OSIntegrationTestCase):
1109 Tests for the OpenStackHeatStack class defined in create_stack.py for
1110 when failures occur. Failures are being triggered by allocating 1 million
1115 self.user_roles = ['heat_stack_owner']
1117 super(self.__class__, self).__start__()
1119 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1121 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
1122 self.stack_creator = None
1124 self.tmp_file = file_utils.save_string_to_file(
1125 ' ', str(uuid.uuid4()) + '-bad-image')
1126 self.image_creator = OpenStackImage(
1127 self.os_creds, ImageConfig(
1128 name=self.guid + 'image', image_file=self.tmp_file.name,
1129 image_user='foo', img_format='qcow2'))
1130 self.image_creator.create()
1133 self.flavor_creator = OpenStackFlavor(
1134 self.admin_os_creds,
1136 name=self.guid + '-flavor-name', ram=256, disk=10,
1138 self.flavor_creator.create()
1140 self.network_name = self.guid + '-net'
1141 self.subnet_name = self.guid + '-subnet'
1142 self.vm_inst_name = self.guid + '-inst'
1145 'image_name': self.image_creator.image_settings.name,
1146 'flavor_name': self.flavor_creator.flavor_settings.name,
1147 'net_name': self.network_name,
1148 'subnet_name': self.subnet_name,
1149 'inst_name': self.vm_inst_name}
1151 self.heat_tmplt_path = pkg_resources.resource_filename(
1152 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1156 Cleans the stack and downloaded stack file
1158 if self.stack_creator:
1160 self.stack_creator.clean()
1164 if self.image_creator:
1166 self.image_creator.clean()
1170 if self.flavor_creator:
1172 self.flavor_creator.clean()
1178 os.remove(self.tmp_file.name)
1182 super(self.__class__, self).__clean__()
1184 def test_stack_failure(self):
1186 Tests the creation of an OpenStack stack from Heat template file that
1187 should always fail due to too many CPU cores
1190 # Set the default stack settings, then set any custom parameters sent
1192 stack_settings = StackConfig(
1193 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1194 template_path=self.heat_tmplt_path,
1195 env_values=self.env_values)
1196 self.stack_creator = OpenStackHeatStack(
1197 self.os_creds, stack_settings)
1199 with self.assertRaises(StackError):
1201 self.stack_creator.create()
1203 resources = heat_utils.get_resources(
1204 self.heat_cli, self.stack_creator.get_stack().id)
1207 for resource in resources:
1208 if (resource.status ==
1209 snaps.config.stack.STATUS_CREATE_COMPLETE):
1211 self.assertTrue(found)