Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 2 | # not use this file except in compliance with the License. You may obtain |
| 3 | # a copy of the License at |
| 4 | # |
| 5 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 6 | # |
| 7 | # Unless required by applicable law or agreed to in writing, software |
| 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 10 | # License for the specific language governing permissions and limitations |
| 11 | # under the License. |
| 12 | |
Sean Dague | e0a65d1 | 2014-03-25 15:59:16 -0400 | [diff] [blame] | 13 | import os.path |
Matthew Treinish | 96e9e88 | 2014-06-09 18:37:19 -0400 | [diff] [blame] | 14 | |
Ghanshyam | 961ea1a | 2014-06-09 10:56:00 +0900 | [diff] [blame] | 15 | import yaml |
Sean Dague | e0a65d1 | 2014-03-25 15:59:16 -0400 | [diff] [blame] | 16 | |
Matthew Treinish | cb09bbb | 2014-01-29 18:20:25 +0000 | [diff] [blame] | 17 | from tempest import config |
Ken'ichi Ohmichi | 60680a8 | 2017-03-10 11:03:16 -0800 | [diff] [blame] | 18 | from tempest.lib.common.utils import data_utils |
Jordan Pittier | 9e227c5 | 2016-02-09 14:35:18 +0100 | [diff] [blame] | 19 | from tempest.lib.common.utils import test_utils |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 20 | import tempest.test |
| 21 | |
Matthew Treinish | cb09bbb | 2014-01-29 18:20:25 +0000 | [diff] [blame] | 22 | CONF = config.CONF |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 23 | |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 24 | |
| 25 | class BaseOrchestrationTest(tempest.test.BaseTestCase): |
| 26 | """Base test case class for all Orchestration API tests.""" |
| 27 | |
Andrea Frittoli | b21de6c | 2015-02-06 20:12:38 +0000 | [diff] [blame] | 28 | credentials = ['primary'] |
| 29 | |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 30 | @classmethod |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 31 | def skip_checks(cls): |
| 32 | super(BaseOrchestrationTest, cls).skip_checks() |
Matthew Treinish | cb09bbb | 2014-01-29 18:20:25 +0000 | [diff] [blame] | 33 | if not CONF.service_available.heat: |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 34 | raise cls.skipException("Heat support is required") |
| 35 | |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 36 | @classmethod |
Emilien Macchi | e7740ea | 2016-02-09 20:13:13 +0000 | [diff] [blame] | 37 | def setup_credentials(cls): |
| 38 | super(BaseOrchestrationTest, cls).setup_credentials() |
| 39 | stack_owner_role = CONF.orchestration.stack_owner_role |
| 40 | cls.os = cls.get_client_manager(roles=[stack_owner_role]) |
| 41 | |
| 42 | @classmethod |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 43 | def setup_clients(cls): |
| 44 | super(BaseOrchestrationTest, cls).setup_clients() |
Sean Dague | e0a65d1 | 2014-03-25 15:59:16 -0400 | [diff] [blame] | 45 | cls.orchestration_client = cls.os.orchestration_client |
| 46 | cls.client = cls.orchestration_client |
| 47 | cls.servers_client = cls.os.servers_client |
| 48 | cls.keypairs_client = cls.os.keypairs_client |
John Warren | 94d8faf | 2015-09-15 12:22:24 -0400 | [diff] [blame] | 49 | cls.networks_client = cls.os.networks_client |
| 50 | cls.volumes_client = cls.os.volumes_client |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 51 | cls.images_v2_client = cls.os.image_client_v2 |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 52 | |
Rabi Mishra | e42bfe4 | 2015-09-29 18:02:13 +0530 | [diff] [blame] | 53 | if CONF.volume_feature_enabled.api_v2: |
| 54 | cls.volumes_client = cls.os.volumes_v2_client |
| 55 | else: |
| 56 | cls.volumes_client = cls.os.volumes_client |
| 57 | |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 58 | @classmethod |
| 59 | def resource_setup(cls): |
| 60 | super(BaseOrchestrationTest, cls).resource_setup() |
| 61 | cls.build_timeout = CONF.orchestration.build_timeout |
| 62 | cls.build_interval = CONF.orchestration.build_interval |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 63 | cls.stacks = [] |
Steve Baker | b1f67b5 | 2013-06-24 14:42:30 +1200 | [diff] [blame] | 64 | cls.keypairs = [] |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 65 | cls.images = [] |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 66 | |
| 67 | @classmethod |
Ghanshyam | 2a180b8 | 2014-06-16 13:54:22 +0900 | [diff] [blame] | 68 | def create_stack(cls, stack_name, template_data, parameters=None, |
Steven Hardy | 1b25fe0 | 2014-05-07 16:21:28 +0100 | [diff] [blame] | 69 | environment=None, files=None): |
Ghanshyam | 2a180b8 | 2014-06-16 13:54:22 +0900 | [diff] [blame] | 70 | if parameters is None: |
| 71 | parameters = {} |
David Kranz | 8ad924b | 2015-01-16 16:50:18 -0500 | [diff] [blame] | 72 | body = cls.client.create_stack( |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 73 | stack_name, |
| 74 | template=template_data, |
Steven Hardy | 00de758 | 2014-05-07 15:18:52 +0100 | [diff] [blame] | 75 | parameters=parameters, |
Steven Hardy | 1b25fe0 | 2014-05-07 16:21:28 +0100 | [diff] [blame] | 76 | environment=environment, |
| 77 | files=files) |
David Kranz | 8ad924b | 2015-01-16 16:50:18 -0500 | [diff] [blame] | 78 | stack_id = body.response['location'].split('/')[-1] |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 79 | stack_identifier = '%s/%s' % (stack_name, stack_id) |
Steve Baker | b794277 | 2013-06-27 10:23:28 +1200 | [diff] [blame] | 80 | cls.stacks.append(stack_identifier) |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 81 | return stack_identifier |
| 82 | |
| 83 | @classmethod |
Steven Hardy | 5be93e8 | 2014-04-02 21:24:05 +0100 | [diff] [blame] | 84 | def _clear_stacks(cls): |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 85 | for stack_identifier in cls.stacks: |
Jordan Pittier | 9e227c5 | 2016-02-09 14:35:18 +0100 | [diff] [blame] | 86 | test_utils.call_and_ignore_notfound_exc( |
| 87 | cls.client.delete_stack, stack_identifier) |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 88 | |
| 89 | for stack_identifier in cls.stacks: |
Jordan Pittier | 9e227c5 | 2016-02-09 14:35:18 +0100 | [diff] [blame] | 90 | test_utils.call_and_ignore_notfound_exc( |
| 91 | cls.client.wait_for_stack_status, stack_identifier, |
| 92 | 'DELETE_COMPLETE') |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 93 | |
Steve Baker | b794277 | 2013-06-27 10:23:28 +1200 | [diff] [blame] | 94 | @classmethod |
Bartosz Górski | ab33b7e | 2013-06-27 00:39:47 -0700 | [diff] [blame] | 95 | def _create_keypair(cls, name_start='keypair-heat-'): |
Masayuki Igawa | 259c113 | 2013-10-31 17:48:44 +0900 | [diff] [blame] | 96 | kp_name = data_utils.rand_name(name_start) |
ghanshyam | dee01f2 | 2015-08-17 11:41:47 +0900 | [diff] [blame] | 97 | body = cls.keypairs_client.create_keypair(name=kp_name)['keypair'] |
Steve Baker | b794277 | 2013-06-27 10:23:28 +1200 | [diff] [blame] | 98 | cls.keypairs.append(kp_name) |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 99 | return body |
| 100 | |
| 101 | @classmethod |
Steven Hardy | 5be93e8 | 2014-04-02 21:24:05 +0100 | [diff] [blame] | 102 | def _clear_keypairs(cls): |
Steve Baker | b1f67b5 | 2013-06-24 14:42:30 +1200 | [diff] [blame] | 103 | for kp_name in cls.keypairs: |
| 104 | try: |
| 105 | cls.keypairs_client.delete_keypair(kp_name) |
| 106 | except Exception: |
| 107 | pass |
| 108 | |
| 109 | @classmethod |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 110 | def _create_image(cls, name_start='image-heat-', container_format='bare', |
| 111 | disk_format='iso'): |
| 112 | image_name = data_utils.rand_name(name_start) |
David Kranz | 34f1878 | 2015-01-06 13:43:55 -0500 | [diff] [blame] | 113 | body = cls.images_v2_client.create_image(image_name, |
| 114 | container_format, |
| 115 | disk_format) |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 116 | image_id = body['id'] |
| 117 | cls.images.append(image_id) |
| 118 | return body |
| 119 | |
| 120 | @classmethod |
| 121 | def _clear_images(cls): |
| 122 | for image_id in cls.images: |
Jordan Pittier | 9e227c5 | 2016-02-09 14:35:18 +0100 | [diff] [blame] | 123 | test_utils.call_and_ignore_notfound_exc( |
| 124 | cls.images_v2_client.delete_image, image_id) |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 125 | |
| 126 | @classmethod |
Ghanshyam | 961ea1a | 2014-06-09 10:56:00 +0900 | [diff] [blame] | 127 | def read_template(cls, name, ext='yaml'): |
Qiu Hua Qiao | f636877 | 2014-04-01 01:12:39 -0500 | [diff] [blame] | 128 | loc = ["stacks", "templates", "%s.%s" % (name, ext)] |
| 129 | fullpath = os.path.join(os.path.dirname(__file__), *loc) |
Sean Dague | e0a65d1 | 2014-03-25 15:59:16 -0400 | [diff] [blame] | 130 | |
| 131 | with open(fullpath, "r") as f: |
| 132 | content = f.read() |
| 133 | return content |
| 134 | |
| 135 | @classmethod |
Ghanshyam | 961ea1a | 2014-06-09 10:56:00 +0900 | [diff] [blame] | 136 | def load_template(cls, name, ext='yaml'): |
| 137 | loc = ["stacks", "templates", "%s.%s" % (name, ext)] |
| 138 | fullpath = os.path.join(os.path.dirname(__file__), *loc) |
| 139 | |
| 140 | with open(fullpath, "r") as f: |
| 141 | return yaml.safe_load(f) |
| 142 | |
| 143 | @classmethod |
Andrea Frittoli | 556f796 | 2014-09-15 13:14:54 +0100 | [diff] [blame] | 144 | def resource_cleanup(cls): |
Steven Hardy | 5be93e8 | 2014-04-02 21:24:05 +0100 | [diff] [blame] | 145 | cls._clear_stacks() |
| 146 | cls._clear_keypairs() |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 147 | cls._clear_images() |
Andrea Frittoli | 556f796 | 2014-09-15 13:14:54 +0100 | [diff] [blame] | 148 | super(BaseOrchestrationTest, cls).resource_cleanup() |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 149 | |
Steve Baker | 38d8f09 | 2013-06-12 12:47:16 +1200 | [diff] [blame] | 150 | @staticmethod |
| 151 | def stack_output(stack, output_key): |
Steven Hardy | 48ec705 | 2014-03-28 14:06:27 +0000 | [diff] [blame] | 152 | """Return a stack output value for a given key.""" |
Steve Baker | 38d8f09 | 2013-06-12 12:47:16 +1200 | [diff] [blame] | 153 | return next((o['output_value'] for o in stack['outputs'] |
| 154 | if o['output_key'] == output_key), None) |
Steven Hardy | e2a7444 | 2014-03-25 12:10:52 +0000 | [diff] [blame] | 155 | |
| 156 | def assert_fields_in_dict(self, obj, *fields): |
| 157 | for field in fields: |
| 158 | self.assertIn(field, obj) |
| 159 | |
| 160 | def list_resources(self, stack_identifier): |
| 161 | """Get a dict mapping of resource names to types.""" |
Anusha Ramineni | ab6c3a3 | 2015-08-18 08:33:09 +0530 | [diff] [blame] | 162 | resources = self.client.list_resources(stack_identifier)['resources'] |
Steven Hardy | e2a7444 | 2014-03-25 12:10:52 +0000 | [diff] [blame] | 163 | self.assertIsInstance(resources, list) |
| 164 | for res in resources: |
| 165 | self.assert_fields_in_dict(res, 'logical_resource_id', |
| 166 | 'resource_type', 'resource_status', |
| 167 | 'updated_time') |
| 168 | |
| 169 | return dict((r['resource_name'], r['resource_type']) |
| 170 | for r in resources) |
Steven Hardy | 8b54fc5 | 2014-03-28 16:15:51 +0000 | [diff] [blame] | 171 | |
| 172 | def get_stack_output(self, stack_identifier, output_key): |
Anusha Ramineni | ab6c3a3 | 2015-08-18 08:33:09 +0530 | [diff] [blame] | 173 | body = self.client.show_stack(stack_identifier)['stack'] |
Steven Hardy | 8b54fc5 | 2014-03-28 16:15:51 +0000 | [diff] [blame] | 174 | return self.stack_output(body, output_key) |