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 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.os_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 derived_creator = create_stack.generate_creator(
221 self.os_creds, retrieved_stack,
222 [self.image_creator.image_settings])
223 derived_stack = derived_creator.get_stack()
224 self.assertEqual(retrieved_stack, derived_stack)
226 def test_create_stack_short_timeout(self):
228 Tests the creation of an OpenStack stack from Heat template file.
231 # Set the default stack settings, then set any custom parameters sent
233 stack_settings = StackConfig(
234 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
235 template_path=self.heat_tmplt_path,
236 env_values=self.env_values, stack_create_timeout=0)
238 self.stack_creator = OpenStackHeatStack(
239 self.os_creds, stack_settings)
240 with self.assertRaises(StackCreationError):
241 self.stack_creator.create()
243 def test_create_stack_template_dict(self):
245 Tests the creation of an OpenStack stack from a heat dict() object.
248 # Set the default stack settings, then set any custom parameters sent
250 template_dict = heat_utils.parse_heat_template_str(
251 file_utils.read_file(self.heat_tmplt_path))
252 stack_settings = StackConfig(
253 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
254 template=template_dict,
255 env_values=self.env_values)
256 self.stack_creator = OpenStackHeatStack(
257 self.os_creds, stack_settings)
258 created_stack = self.stack_creator.create()
259 self.assertIsNotNone(created_stack)
261 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
263 self.assertIsNotNone(retrieved_stack)
264 self.assertEqual(created_stack.name, retrieved_stack.name)
265 self.assertEqual(created_stack.id, retrieved_stack.id)
266 self.assertEqual(0, len(self.stack_creator.get_outputs()))
268 def test_create_delete_stack(self):
270 Tests the creation then deletion of an OpenStack stack to ensure
271 clean() does not raise an Exception.
274 template_dict = heat_utils.parse_heat_template_str(
275 file_utils.read_file(self.heat_tmplt_path))
276 stack_settings = StackConfig(
277 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
278 template=template_dict,
279 env_values=self.env_values)
280 self.stack_creator = OpenStackHeatStack(
281 self.os_creds, stack_settings)
282 created_stack = self.stack_creator.create()
283 self.assertIsNotNone(created_stack)
285 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
287 self.assertIsNotNone(retrieved_stack)
288 self.assertEqual(created_stack.name, retrieved_stack.name)
289 self.assertEqual(created_stack.id, retrieved_stack.id)
290 self.assertEqual(0, len(self.stack_creator.get_outputs()))
291 self.assertEqual(snaps.config.stack.STATUS_CREATE_COMPLETE,
292 self.stack_creator.get_status())
294 # Delete Stack manually
295 heat_utils.delete_stack(self.heat_cli, created_stack)
297 end_time = time.time() + 90
299 while time.time() < end_time:
300 status = heat_utils.get_stack_status(self.heat_cli,
302 if status == snaps.config.stack.STATUS_DELETE_COMPLETE:
306 self.assertTrue(deleted)
308 # Must not throw an exception when attempting to cleanup non-existent
310 self.stack_creator.clean()
311 self.assertIsNone(self.stack_creator.get_stack())
313 def test_create_same_stack(self):
315 Tests the creation of an OpenStack stack when the stack already exists.
318 template_dict = heat_utils.parse_heat_template_str(
319 file_utils.read_file(self.heat_tmplt_path))
320 stack_settings = StackConfig(
321 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
322 template=template_dict,
323 env_values=self.env_values)
324 self.stack_creator = OpenStackHeatStack(
325 self.os_creds, stack_settings)
326 created_stack1 = self.stack_creator.create()
328 retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
330 self.assertIsNotNone(retrieved_stack)
331 self.assertEqual(created_stack1.name, retrieved_stack.name)
332 self.assertEqual(created_stack1.id, retrieved_stack.id)
333 self.assertEqual(0, len(self.stack_creator.get_outputs()))
335 # Should be retrieving the instance data
336 stack_creator2 = OpenStackHeatStack(self.os_creds, stack_settings)
337 stack2 = stack_creator2.create()
338 self.assertEqual(created_stack1.id, stack2.id)
340 def test_retrieve_network_creators(self):
342 Tests the creation of an OpenStack stack from Heat template file and
343 the retrieval of the network creator.
345 stack_settings = StackConfig(
346 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
347 template_path=self.heat_tmplt_path,
348 env_values=self.env_values)
349 self.stack_creator = OpenStackHeatStack(
350 self.os_creds, stack_settings)
351 created_stack = self.stack_creator.create()
352 self.assertIsNotNone(created_stack)
354 net_creators = self.stack_creator.get_network_creators()
355 self.assertIsNotNone(net_creators)
356 self.assertEqual(1, len(net_creators))
357 self.assertEqual(self.network_name, net_creators[0].get_network().name)
359 # Need to use 'admin' creds as heat creates objects under it's own
361 neutron = neutron_utils.neutron_client(
362 self.os_creds, self.os_session)
363 keystone = keystone_utils.keystone_client(
364 self.os_creds, self.os_session)
365 net_by_name = neutron_utils.get_network(
366 neutron, keystone, network_name=net_creators[0].get_network().name)
367 self.assertEqual(net_creators[0].get_network(), net_by_name)
368 self.assertIsNotNone(neutron_utils.get_network_by_id(
369 neutron, net_creators[0].get_network().id))
371 self.assertEqual(1, len(net_creators[0].get_network().subnets))
372 subnet = net_creators[0].get_network().subnets[0]
373 subnet_by_name = neutron_utils.get_subnet(
374 neutron, subnet_name=subnet.name)
375 self.assertEqual(subnet, subnet_by_name)
377 subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
378 self.assertIsNotNone(subnet_by_id)
379 self.assertEqual(subnet_by_name, subnet_by_id)
381 def test_retrieve_vm_inst_creators(self):
383 Tests the creation of an OpenStack stack from Heat template file and
384 the retrieval of the network creator.
386 stack_settings = StackConfig(
387 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
388 template_path=self.heat_tmplt_path,
389 env_values=self.env_values)
390 self.stack_creator = OpenStackHeatStack(
391 self.os_creds, stack_settings)
392 created_stack = self.stack_creator.create()
393 self.assertIsNotNone(created_stack)
395 vm_inst_creators = self.stack_creator.get_vm_inst_creators()
396 self.assertIsNotNone(vm_inst_creators)
397 self.assertEqual(1, len(vm_inst_creators))
398 self.assertEqual(self.vm_inst_name,
399 vm_inst_creators[0].get_vm_inst().name)
401 nova = nova_utils.nova_client(self.os_creds, self.os_session)
402 neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
403 keystone = keystone_utils.keystone_client(self.os_creds, self.os_session)
404 vm_inst_by_name = nova_utils.get_server(
405 nova, neutron, keystone,
406 server_name=vm_inst_creators[0].get_vm_inst().name)
408 self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
409 self.assertIsNotNone(nova_utils.get_server_object_by_id(
410 nova, neutron, keystone, vm_inst_creators[0].get_vm_inst().id))
413 class CreateStackFloatingIpTests(OSIntegrationTestCase):
415 Tests to ensure that floating IPs can be accessed via an
416 OpenStackVmInstance object obtained from the OpenStackHeatStack instance
420 self.user_roles = ['heat_stack_owner', 'admin']
422 super(self.__class__, self).__start__()
424 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
426 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
427 self.stack_creator = None
429 self.image_creator = OpenStackImage(
430 self.os_creds, openstack_tests.cirros_image_settings(
431 name=self.guid + '-image',
432 image_metadata=self.image_metadata))
433 self.image_creator.create()
435 self.network_name = self.guid + '-net'
436 self.subnet_name = self.guid + '-subnet'
437 self.flavor1_name = self.guid + '-flavor1'
438 self.flavor2_name = self.guid + '-flavor2'
439 self.sec_grp_name = self.guid + '-sec_grp'
440 self.vm_inst1_name = self.guid + '-inst1'
441 self.vm_inst2_name = self.guid + '-inst2'
442 self.keypair_name = self.guid + '-kp'
445 'image1_name': self.image_creator.image_settings.name,
446 'image2_name': self.image_creator.image_settings.name,
447 'flavor1_name': self.flavor1_name,
448 'flavor2_name': self.flavor2_name,
449 'net_name': self.network_name,
450 'subnet_name': self.subnet_name,
451 'inst1_name': self.vm_inst1_name,
452 'inst2_name': self.vm_inst2_name,
453 'keypair_name': self.keypair_name,
454 'external_net_name': self.ext_net_name,
455 'security_group_name': self.sec_grp_name}
457 self.heat_tmplt_path = pkg_resources.resource_filename(
458 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml')
460 self.vm_inst_creators = list()
464 Cleans the stack and downloaded stack file
466 if self.stack_creator:
468 self.stack_creator.clean()
472 if self.image_creator:
474 self.image_creator.clean()
478 for vm_inst_creator in self.vm_inst_creators:
480 keypair_settings = vm_inst_creator.keypair_settings
481 if keypair_settings and keypair_settings.private_filepath:
482 expanded_path = os.path.expanduser(
483 keypair_settings.private_filepath)
484 os.chmod(expanded_path, 0o755)
485 os.remove(expanded_path)
489 super(self.__class__, self).__clean__()
491 def test_connect_via_ssh_heat_vm(self):
493 Tests the creation of an OpenStack stack from Heat template file and
494 the retrieval of two VM instance creators and attempt to connect via
495 SSH to the first one with a floating IP.
497 stack_settings = StackConfig(
498 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
499 template_path=self.heat_tmplt_path,
500 env_values=self.env_values)
501 self.stack_creator = OpenStackHeatStack(
502 self.os_creds, stack_settings,
503 [self.image_creator.image_settings])
504 created_stack = self.stack_creator.create()
505 self.assertIsNotNone(created_stack)
507 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
508 heat_keypair_option='private_key')
509 self.assertIsNotNone(self.vm_inst_creators)
510 self.assertEqual(2, len(self.vm_inst_creators))
512 for vm_inst_creator in self.vm_inst_creators:
513 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
515 create_instance_tests.validate_ssh_client(vm_inst_creator))
517 vm_settings = vm_inst_creator.instance_settings
518 self.assertEqual(0, len(vm_settings.floating_ip_settings))
520 def test_connect_via_ssh_heat_vm_derived(self):
522 Tests the the retrieval of two VM instance creators from a derived
523 OpenStackHeatStack object and attempt to connect via
524 SSH to the first one with a floating IP.
526 stack_settings = StackConfig(
527 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
528 template_path=self.heat_tmplt_path,
529 env_values=self.env_values)
530 self.stack_creator = OpenStackHeatStack(
531 self.os_creds, stack_settings,
532 [self.image_creator.image_settings])
533 created_stack = self.stack_creator.create()
534 self.assertIsNotNone(created_stack)
536 derived_stack = create_stack.generate_creator(
537 self.os_creds, created_stack,
538 [self.image_creator.image_settings])
540 self.vm_inst_creators = derived_stack.get_vm_inst_creators(
541 heat_keypair_option='private_key')
542 self.assertIsNotNone(self.vm_inst_creators)
543 self.assertEqual(2, len(self.vm_inst_creators))
545 for vm_inst_creator in self.vm_inst_creators:
546 if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
548 create_instance_tests.validate_ssh_client(vm_inst_creator))
550 vm_settings = vm_inst_creator.instance_settings
551 self.assertEqual(0, len(vm_settings.floating_ip_settings))
554 class CreateStackNestedResourceTests(OSIntegrationTestCase):
556 Tests to ensure that nested heat templates work
560 self.user_roles = ['heat_stack_owner']
562 super(self.__class__, self).__start__()
564 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
566 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
567 self.stack_creator = None
569 self.image_creator = OpenStackImage(
570 self.os_creds, openstack_tests.cirros_image_settings(
571 name=self.guid + '-image',
572 image_metadata=self.image_metadata))
573 self.image_creator.create()
575 self.flavor_creator = OpenStackFlavor(
578 name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
579 self.flavor_creator.create()
582 'network_name': self.guid + '-network',
583 'public_network': self.ext_net_name,
584 'agent_image': self.image_creator.image_settings.name,
585 'agent_flavor': self.flavor_creator.flavor_settings.name,
586 'key_name': self.guid + '-key',
589 heat_tmplt_path = pkg_resources.resource_filename(
590 'snaps.openstack.tests.heat', 'agent-group.yaml')
591 heat_resource_path = pkg_resources.resource_filename(
592 'snaps.openstack.tests.heat', 'agent.yaml')
594 stack_settings = StackConfig(
595 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
596 template_path=heat_tmplt_path,
597 resource_files=[heat_resource_path],
598 env_values=env_values)
600 self.stack_creator = OpenStackHeatStack(
601 self.os_creds, stack_settings,
602 [self.image_creator.image_settings])
604 self.vm_inst_creators = list()
608 Cleans the stack and downloaded stack file
610 if self.stack_creator:
612 self.stack_creator.clean()
616 if self.image_creator:
618 self.image_creator.clean()
622 if self.flavor_creator:
624 self.flavor_creator.clean()
628 for vm_inst_creator in self.vm_inst_creators:
630 keypair_settings = vm_inst_creator.keypair_settings
631 if keypair_settings and keypair_settings.private_filepath:
632 expanded_path = os.path.expanduser(
633 keypair_settings.private_filepath)
634 os.chmod(expanded_path, 0o755)
635 os.remove(expanded_path)
639 super(self.__class__, self).__clean__()
641 def test_nested(self):
643 Tests the creation of an OpenStack stack from Heat template file and
644 the retrieval of two VM instance creators and attempt to connect via
645 SSH to the first one with a floating IP.
647 created_stack = self.stack_creator.create()
648 self.assertIsNotNone(created_stack)
650 self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
651 heat_keypair_option='private_key')
652 self.assertIsNotNone(self.vm_inst_creators)
653 self.assertEqual(1, len(self.vm_inst_creators))
655 for vm_inst_creator in self.vm_inst_creators:
657 create_instance_tests.validate_ssh_client(vm_inst_creator))
660 class CreateStackRouterTests(OSIntegrationTestCase):
662 Tests for the CreateStack class defined in create_stack.py where the
663 target is a Network, Subnet, and Router
668 Instantiates the CreateStack object that is responsible for downloading
669 and creating an OS stack file within OpenStack
671 self.user_roles = ['heat_stack_owner']
673 super(self.__class__, self).__start__()
675 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
677 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
678 self.neutron = neutron_utils.neutron_client(
679 self.os_creds, self.os_session)
680 self.stack_creator = None
682 self.net_name = self.guid + '-net'
683 self.subnet_name = self.guid + '-subnet'
684 self.router_name = self.guid + '-router'
687 'net_name': self.net_name,
688 'subnet_name': self.subnet_name,
689 'router_name': self.router_name,
690 'external_net_name': self.ext_net_name}
692 self.heat_tmplt_path = pkg_resources.resource_filename(
693 'snaps.openstack.tests.heat', 'router_heat_template.yaml')
695 stack_settings = StackConfig(
696 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
697 template_path=self.heat_tmplt_path,
698 env_values=self.env_values)
699 self.stack_creator = OpenStackHeatStack(
700 self.os_creds, stack_settings)
701 self.created_stack = self.stack_creator.create()
702 self.assertIsNotNone(self.created_stack)
706 Cleans the stack and downloaded stack file
708 if self.stack_creator:
710 self.stack_creator.clean()
714 super(self.__class__, self).__clean__()
716 def test_retrieve_router_creator(self):
718 Tests the creation of an OpenStack stack from Heat template file and
719 the retrieval of an OpenStackRouter creator/state machine instance
721 router_creators = self.stack_creator.get_router_creators()
722 self.assertEqual(1, len(router_creators))
724 creator = router_creators[0]
725 self.assertEqual(self.router_name, creator.router_settings.name)
727 router = creator.get_router()
729 ext_net = neutron_utils.get_network(
730 self.neutron, self.keystone, network_name=self.ext_net_name)
731 self.assertEqual(ext_net.id, router.external_network_id)
734 class CreateStackVolumeTests(OSIntegrationTestCase):
736 Tests to ensure that floating IPs can be accessed via an
737 OpenStackVolume object obtained from the OpenStackHeatStack instance
742 self.user_roles = ['heat_stack_owner', 'admin']
744 super(self.__class__, self).__start__()
746 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
748 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
749 self.stack_creator = None
751 self.volume_name = self.guid + '-volume'
752 self.volume_type_name = self.guid + '-volume-type'
755 'volume_name': self.volume_name,
756 'volume_type_name': self.volume_type_name}
758 self.heat_tmplt_path = pkg_resources.resource_filename(
759 'snaps.openstack.tests.heat', 'volume_heat_template.yaml')
761 stack_settings = StackConfig(
762 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
763 template_path=self.heat_tmplt_path,
764 env_values=self.env_values)
765 self.stack_creator = OpenStackHeatStack(
766 self.os_creds, stack_settings)
767 self.created_stack = self.stack_creator.create()
768 self.assertIsNotNone(self.created_stack)
772 Cleans the stack and downloaded stack file
774 if self.stack_creator:
776 self.stack_creator.clean()
780 super(self.__class__, self).__clean__()
782 def test_retrieve_volume_creator(self):
784 Tests the creation of an OpenStack stack from Heat template file and
785 the retrieval of an OpenStackVolume creator/state machine instance
787 volume_creators = self.stack_creator.get_volume_creators()
788 self.assertEqual(1, len(volume_creators))
790 creator = volume_creators[0]
791 self.assertEqual(self.volume_name, creator.volume_settings.name)
792 self.assertEqual(self.volume_name, creator.get_volume().name)
793 self.assertEqual(self.volume_type_name,
794 creator.volume_settings.type_name)
795 self.assertEqual(self.volume_type_name, creator.get_volume().type)
796 self.assertEqual(1, creator.volume_settings.size)
797 self.assertEqual(1, creator.get_volume().size)
799 def test_retrieve_volume_type_creator(self):
801 Tests the creation of an OpenStack stack from Heat template file and
802 the retrieval of an OpenStackVolume creator/state machine instance
804 volume_type_creators = self.stack_creator.get_volume_type_creators()
805 self.assertEqual(1, len(volume_type_creators))
807 creator = volume_type_creators[0]
808 self.assertIsNotNone(creator)
810 volume_type = creator.get_volume_type()
811 self.assertIsNotNone(volume_type)
813 self.assertEqual(self.volume_type_name, volume_type.name)
814 self.assertTrue(volume_type.public)
815 self.assertIsNone(volume_type.qos_spec)
817 # TODO - Add encryption back and find out why it broke in Pike
818 # encryption = volume_type.encryption
819 # self.assertIsNotNone(encryption)
820 # self.assertIsNone(encryption.cipher)
821 # self.assertEqual('front-end', encryption.control_location)
822 # self.assertIsNone(encryption.key_size)
823 # self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor',
824 # encryption.provider)
825 # self.assertEqual(volume_type.id, encryption.volume_type_id)
828 class CreateStackFlavorTests(OSIntegrationTestCase):
830 Tests to ensure that floating IPs can be accessed via an
831 OpenStackFlavor object obtained from the OpenStackHeatStack instance
836 self.user_roles = ['heat_stack_owner', 'admin']
838 super(self.__class__, self).__start__()
840 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
842 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
843 self.stack_creator = None
845 self.heat_tmplt_path = pkg_resources.resource_filename(
846 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml')
848 stack_settings = StackConfig(
849 name=self.guid + '-stack',
850 template_path=self.heat_tmplt_path)
851 self.stack_creator = OpenStackHeatStack(
852 self.os_creds, stack_settings)
853 self.created_stack = self.stack_creator.create()
854 self.assertIsNotNone(self.created_stack)
858 Cleans the stack and downloaded stack file
860 if self.stack_creator:
862 self.stack_creator.clean()
866 super(self.__class__, self).__clean__()
868 def test_retrieve_flavor_creator(self):
870 Tests the creation of an OpenStack stack from Heat template file and
871 the retrieval of an OpenStackVolume creator/state machine instance
873 flavor_creators = self.stack_creator.get_flavor_creators()
874 self.assertEqual(1, len(flavor_creators))
876 creator = flavor_creators[0]
877 self.assertTrue(creator.get_flavor().name.startswith(self.guid))
878 self.assertEqual(1024, creator.get_flavor().ram)
879 self.assertEqual(200, creator.get_flavor().disk)
880 self.assertEqual(8, creator.get_flavor().vcpus)
881 self.assertEqual(0, creator.get_flavor().ephemeral)
882 self.assertIsNone(creator.get_flavor().swap)
883 self.assertEqual(1.0, creator.get_flavor().rxtx_factor)
884 self.assertTrue(creator.get_flavor().is_public)
887 class CreateStackKeypairTests(OSIntegrationTestCase):
889 Tests to ensure that floating IPs can be accessed via an
890 OpenStackKeypair object obtained from the OpenStackHeatStack instance
895 self.user_roles = ['heat_stack_owner']
897 super(self.__class__, self).__start__()
899 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
901 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
902 self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
903 self.stack_creator = None
905 self.keypair_name = self.guid + '-kp'
908 'keypair_name': self.keypair_name}
910 self.heat_tmplt_path = pkg_resources.resource_filename(
911 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml')
913 stack_settings = StackConfig(
914 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
915 template_path=self.heat_tmplt_path,
916 env_values=self.env_values)
917 self.stack_creator = OpenStackHeatStack(
918 self.os_creds, stack_settings)
919 self.created_stack = self.stack_creator.create()
920 self.assertIsNotNone(self.created_stack)
922 self.keypair_creators = list()
926 Cleans the stack and downloaded stack file
928 if self.stack_creator:
930 self.stack_creator.clean()
933 for keypair_creator in self.keypair_creators:
935 keypair_creator.clean()
939 super(self.__class__, self).__clean__()
941 def test_retrieve_keypair_creator(self):
943 Tests the creation of an OpenStack stack from Heat template file and
944 the retrieval of an OpenStackKeypair creator/state machine instance
946 self.kp_creators = self.stack_creator.get_keypair_creators(
948 self.assertEqual(1, len(self.kp_creators))
950 self.keypair_creator = self.kp_creators[0]
952 self.assertEqual(self.keypair_name,
953 self.keypair_creator.get_keypair().name)
954 self.assertIsNotNone(
955 self.keypair_creator.keypair_settings.private_filepath)
957 private_file_contents = file_utils.read_file(
958 self.keypair_creator.keypair_settings.private_filepath)
959 self.assertTrue(private_file_contents.startswith(
960 '-----BEGIN RSA PRIVATE KEY-----'))
962 keypair = nova_utils.get_keypair_by_id(
963 self.nova, self.keypair_creator.get_keypair().id)
964 self.assertIsNotNone(keypair)
965 self.assertEqual(self.keypair_creator.get_keypair(), keypair)
968 class CreateStackSecurityGroupTests(OSIntegrationTestCase):
970 Tests for the OpenStackHeatStack class to ensure it returns an
971 OpenStackSecurityGroup object
976 Instantiates the CreateStack object that is responsible for downloading
977 and creating an OS stack file within OpenStack
979 self.user_roles = ['heat_stack_owner']
981 super(self.__class__, self).__start__()
983 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
985 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
986 self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
987 self.stack_creator = None
989 self.security_group_name = self.guid + '-sec-grp'
992 'security_group_name': self.security_group_name}
994 self.heat_tmplt_path = pkg_resources.resource_filename(
995 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml')
997 stack_settings = StackConfig(
998 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
999 template_path=self.heat_tmplt_path,
1000 env_values=self.env_values)
1001 self.stack_creator = OpenStackHeatStack(
1002 self.os_creds, stack_settings)
1003 self.created_stack = self.stack_creator.create()
1004 self.assertIsNotNone(self.created_stack)
1008 Cleans the stack and downloaded stack file
1010 if self.stack_creator:
1012 self.stack_creator.clean()
1016 super(self.__class__, self).__clean__()
1018 def test_retrieve_security_group_creator(self):
1020 Tests the creation of an OpenStack stack from Heat template file and
1021 the retrieval of an OpenStackSecurityGroup creator/state machine
1024 sec_grp_creators = self.stack_creator.get_security_group_creators()
1025 self.assertEqual(1, len(sec_grp_creators))
1027 creator = sec_grp_creators[0]
1028 sec_grp = creator.get_security_group()
1030 self.assertEqual(self.security_group_name, sec_grp.name)
1031 self.assertEqual('Test description', sec_grp.description)
1032 self.assertEqual(2, len(sec_grp.rules))
1034 has_ssh_rule = False
1035 has_icmp_rule = False
1037 for rule in sec_grp.rules:
1038 if (rule.security_group_id == sec_grp.id
1039 and rule.direction == 'egress'
1040 and rule.ethertype == 'IPv4'
1041 and rule.port_range_min == 22
1042 and rule.port_range_max == 22
1043 and rule.protocol == 'tcp'
1044 and rule.remote_group_id is None
1045 and rule.remote_ip_prefix == '0.0.0.0/0'):
1047 if (rule.security_group_id == sec_grp.id
1048 and rule.direction == 'ingress'
1049 and rule.ethertype == 'IPv4'
1050 and rule.port_range_min is None
1051 and rule.port_range_max is None
1052 and rule.protocol == 'icmp'
1053 and rule.remote_group_id is None
1054 and rule.remote_ip_prefix == '0.0.0.0/0'):
1055 has_icmp_rule = True
1057 self.assertTrue(has_ssh_rule)
1058 self.assertTrue(has_icmp_rule)
1061 class CreateStackNegativeTests(OSIntegrationTestCase):
1063 Negative test cases for the OpenStackHeatStack class with poor
1068 self.user_roles = ['heat_stack_owner']
1070 super(self.__class__, self).__start__()
1072 self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1073 self.stack_creator = None
1074 self.heat_tmplt_path = pkg_resources.resource_filename(
1075 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1078 if self.stack_creator:
1079 self.stack_creator.clean()
1081 super(self.__class__, self).__clean__()
1083 def test_missing_dependencies(self):
1085 Expect an StackCreationError when the stack file does not exist
1087 stack_settings = StackConfig(name=self.stack_name,
1088 template_path=self.heat_tmplt_path)
1089 self.stack_creator = OpenStackHeatStack(
1090 self.os_creds, stack_settings)
1091 with self.assertRaises(HTTPBadRequest):
1092 self.stack_creator.create()
1094 def test_bad_stack_file(self):
1096 Expect an StackCreationError when the stack file does not exist
1098 stack_settings = StackConfig(
1099 name=self.stack_name, template_path='foo')
1100 self.stack_creator = OpenStackHeatStack(
1101 self.os_creds, stack_settings)
1102 with self.assertRaises(IOError):
1103 self.stack_creator.create()
1106 class CreateStackFailureTests(OSIntegrationTestCase):
1108 Tests for the OpenStackHeatStack class defined in create_stack.py for
1109 when failures occur. Failures are being triggered by allocating 1 million
1114 self.user_roles = ['heat_stack_owner']
1116 super(self.__class__, self).__start__()
1118 self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1120 self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
1121 self.stack_creator = None
1123 self.tmp_file = file_utils.save_string_to_file(
1124 ' ', str(uuid.uuid4()) + '-bad-image')
1125 self.image_creator = OpenStackImage(
1126 self.os_creds, ImageConfig(
1127 name=self.guid + 'image', image_file=self.tmp_file.name,
1128 image_user='foo', img_format='qcow2'))
1129 self.image_creator.create()
1132 self.flavor_creator = OpenStackFlavor(
1133 self.admin_os_creds,
1135 name=self.guid + '-flavor-name', ram=256, disk=10,
1137 self.flavor_creator.create()
1139 self.network_name = self.guid + '-net'
1140 self.subnet_name = self.guid + '-subnet'
1141 self.vm_inst_name = self.guid + '-inst'
1144 'image_name': self.image_creator.image_settings.name,
1145 'flavor_name': self.flavor_creator.flavor_settings.name,
1146 'net_name': self.network_name,
1147 'subnet_name': self.subnet_name,
1148 'inst_name': self.vm_inst_name}
1150 self.heat_tmplt_path = pkg_resources.resource_filename(
1151 'snaps.openstack.tests.heat', 'test_heat_template.yaml')
1155 Cleans the stack and downloaded stack file
1157 if self.stack_creator:
1159 self.stack_creator.clean()
1163 if self.image_creator:
1165 self.image_creator.clean()
1169 if self.flavor_creator:
1171 self.flavor_creator.clean()
1177 os.remove(self.tmp_file.name)
1181 super(self.__class__, self).__clean__()
1183 def test_stack_failure(self):
1185 Tests the creation of an OpenStack stack from Heat template file that
1186 should always fail due to too many CPU cores
1189 # Set the default stack settings, then set any custom parameters sent
1191 stack_settings = StackConfig(
1192 name=self.__class__.__name__ + '-' + str(self.guid) + '-stack',
1193 template_path=self.heat_tmplt_path,
1194 env_values=self.env_values)
1195 self.stack_creator = OpenStackHeatStack(
1196 self.os_creds, stack_settings)
1198 with self.assertRaises(StackError):
1200 self.stack_creator.create()
1202 resources = heat_utils.get_resources(
1203 self.heat_cli, self.stack_creator.get_stack().id)
1206 for resource in resources:
1207 if (resource.status ==
1208 snaps.config.stack.STATUS_CREATE_COMPLETE):
1210 self.assertTrue(found)