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 | |
Doug Hellmann | 583ce2c | 2015-03-11 14:55:46 +0000 | [diff] [blame] | 15 | from oslo_log import log as logging |
Masayuki Igawa | bfa0760 | 2015-01-20 18:47:17 +0900 | [diff] [blame] | 16 | from tempest_lib import exceptions as lib_exc |
Ghanshyam | 961ea1a | 2014-06-09 10:56:00 +0900 | [diff] [blame] | 17 | import yaml |
Sean Dague | e0a65d1 | 2014-03-25 15:59:16 -0400 | [diff] [blame] | 18 | |
Fei Long Wang | d39431f | 2015-05-14 11:30:48 +1200 | [diff] [blame] | 19 | from tempest.common.utils import data_utils |
Matthew Treinish | cb09bbb | 2014-01-29 18:20:25 +0000 | [diff] [blame] | 20 | from tempest import config |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 21 | import tempest.test |
| 22 | |
Matthew Treinish | cb09bbb | 2014-01-29 18:20:25 +0000 | [diff] [blame] | 23 | CONF = config.CONF |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 24 | |
| 25 | LOG = logging.getLogger(__name__) |
| 26 | |
| 27 | |
| 28 | class BaseOrchestrationTest(tempest.test.BaseTestCase): |
| 29 | """Base test case class for all Orchestration API tests.""" |
| 30 | |
Andrea Frittoli | b21de6c | 2015-02-06 20:12:38 +0000 | [diff] [blame] | 31 | credentials = ['primary'] |
| 32 | |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 33 | @classmethod |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 34 | def skip_checks(cls): |
| 35 | super(BaseOrchestrationTest, cls).skip_checks() |
Matthew Treinish | cb09bbb | 2014-01-29 18:20:25 +0000 | [diff] [blame] | 36 | if not CONF.service_available.heat: |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 37 | raise cls.skipException("Heat support is required") |
| 38 | |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 39 | @classmethod |
| 40 | def setup_credentials(cls): |
| 41 | super(BaseOrchestrationTest, cls).setup_credentials() |
Matthew Treinish | db9721d | 2015-03-18 14:21:28 -0400 | [diff] [blame] | 42 | stack_owner_role = CONF.orchestration.stack_owner_role |
Andrea Frittoli (andreaf) | 737fac9 | 2015-05-12 16:14:35 +0100 | [diff] [blame] | 43 | cls.os = cls.get_client_manager(roles=[stack_owner_role]) |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 44 | |
| 45 | @classmethod |
| 46 | def setup_clients(cls): |
| 47 | super(BaseOrchestrationTest, cls).setup_clients() |
Sean Dague | e0a65d1 | 2014-03-25 15:59:16 -0400 | [diff] [blame] | 48 | cls.orchestration_client = cls.os.orchestration_client |
| 49 | cls.client = cls.orchestration_client |
| 50 | cls.servers_client = cls.os.servers_client |
| 51 | cls.keypairs_client = cls.os.keypairs_client |
| 52 | cls.network_client = cls.os.network_client |
Steven Hardy | b1f9198 | 2014-04-04 15:35:55 +0100 | [diff] [blame] | 53 | cls.volumes_client = cls.os.volumes_client |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 54 | cls.images_v2_client = cls.os.image_client_v2 |
Rohan Kanade | 80b938a | 2015-02-07 10:58:56 +0530 | [diff] [blame] | 55 | |
| 56 | @classmethod |
| 57 | def resource_setup(cls): |
| 58 | super(BaseOrchestrationTest, cls).resource_setup() |
| 59 | cls.build_timeout = CONF.orchestration.build_timeout |
| 60 | cls.build_interval = CONF.orchestration.build_interval |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 61 | cls.stacks = [] |
Steve Baker | b1f67b5 | 2013-06-24 14:42:30 +1200 | [diff] [blame] | 62 | cls.keypairs = [] |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 63 | cls.images = [] |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 64 | |
| 65 | @classmethod |
Ghanshyam | 2a180b8 | 2014-06-16 13:54:22 +0900 | [diff] [blame] | 66 | def create_stack(cls, stack_name, template_data, parameters=None, |
Steven Hardy | 1b25fe0 | 2014-05-07 16:21:28 +0100 | [diff] [blame] | 67 | environment=None, files=None): |
Ghanshyam | 2a180b8 | 2014-06-16 13:54:22 +0900 | [diff] [blame] | 68 | if parameters is None: |
| 69 | parameters = {} |
David Kranz | 8ad924b | 2015-01-16 16:50:18 -0500 | [diff] [blame] | 70 | body = cls.client.create_stack( |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 71 | stack_name, |
| 72 | template=template_data, |
Steven Hardy | 00de758 | 2014-05-07 15:18:52 +0100 | [diff] [blame] | 73 | parameters=parameters, |
Steven Hardy | 1b25fe0 | 2014-05-07 16:21:28 +0100 | [diff] [blame] | 74 | environment=environment, |
| 75 | files=files) |
David Kranz | 8ad924b | 2015-01-16 16:50:18 -0500 | [diff] [blame] | 76 | stack_id = body.response['location'].split('/')[-1] |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 77 | stack_identifier = '%s/%s' % (stack_name, stack_id) |
Steve Baker | b794277 | 2013-06-27 10:23:28 +1200 | [diff] [blame] | 78 | cls.stacks.append(stack_identifier) |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 79 | return stack_identifier |
| 80 | |
| 81 | @classmethod |
Steven Hardy | 5be93e8 | 2014-04-02 21:24:05 +0100 | [diff] [blame] | 82 | def _clear_stacks(cls): |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 83 | for stack_identifier in cls.stacks: |
| 84 | try: |
Sean Dague | ad82491 | 2014-03-25 14:56:35 -0400 | [diff] [blame] | 85 | cls.client.delete_stack(stack_identifier) |
Masayuki Igawa | bfa0760 | 2015-01-20 18:47:17 +0900 | [diff] [blame] | 86 | except lib_exc.NotFound: |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 87 | pass |
| 88 | |
| 89 | for stack_identifier in cls.stacks: |
Zhi Kun Liu | 03aec1d | 2014-08-12 16:57:05 +0800 | [diff] [blame] | 90 | try: |
| 91 | cls.client.wait_for_stack_status( |
| 92 | stack_identifier, 'DELETE_COMPLETE') |
Masayuki Igawa | bfa0760 | 2015-01-20 18:47:17 +0900 | [diff] [blame] | 93 | except lib_exc.NotFound: |
Zhi Kun Liu | 03aec1d | 2014-08-12 16:57:05 +0800 | [diff] [blame] | 94 | pass |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 95 | |
Steve Baker | b794277 | 2013-06-27 10:23:28 +1200 | [diff] [blame] | 96 | @classmethod |
Bartosz Górski | ab33b7e | 2013-06-27 00:39:47 -0700 | [diff] [blame] | 97 | def _create_keypair(cls, name_start='keypair-heat-'): |
Masayuki Igawa | 259c113 | 2013-10-31 17:48:44 +0900 | [diff] [blame] | 98 | kp_name = data_utils.rand_name(name_start) |
David Kranz | 173f0e0 | 2015-02-06 13:47:57 -0500 | [diff] [blame] | 99 | body = cls.keypairs_client.create_keypair(kp_name) |
Steve Baker | b794277 | 2013-06-27 10:23:28 +1200 | [diff] [blame] | 100 | cls.keypairs.append(kp_name) |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 101 | return body |
| 102 | |
| 103 | @classmethod |
Steven Hardy | 5be93e8 | 2014-04-02 21:24:05 +0100 | [diff] [blame] | 104 | def _clear_keypairs(cls): |
Steve Baker | b1f67b5 | 2013-06-24 14:42:30 +1200 | [diff] [blame] | 105 | for kp_name in cls.keypairs: |
| 106 | try: |
| 107 | cls.keypairs_client.delete_keypair(kp_name) |
| 108 | except Exception: |
| 109 | pass |
| 110 | |
| 111 | @classmethod |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 112 | def _create_image(cls, name_start='image-heat-', container_format='bare', |
| 113 | disk_format='iso'): |
| 114 | image_name = data_utils.rand_name(name_start) |
David Kranz | 34f1878 | 2015-01-06 13:43:55 -0500 | [diff] [blame] | 115 | body = cls.images_v2_client.create_image(image_name, |
| 116 | container_format, |
| 117 | disk_format) |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 118 | image_id = body['id'] |
| 119 | cls.images.append(image_id) |
| 120 | return body |
| 121 | |
| 122 | @classmethod |
| 123 | def _clear_images(cls): |
| 124 | for image_id in cls.images: |
| 125 | try: |
| 126 | cls.images_v2_client.delete_image(image_id) |
Masayuki Igawa | bfa0760 | 2015-01-20 18:47:17 +0900 | [diff] [blame] | 127 | except lib_exc.NotFound: |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 128 | pass |
| 129 | |
| 130 | @classmethod |
Ghanshyam | 961ea1a | 2014-06-09 10:56:00 +0900 | [diff] [blame] | 131 | def read_template(cls, name, ext='yaml'): |
Qiu Hua Qiao | f636877 | 2014-04-01 01:12:39 -0500 | [diff] [blame] | 132 | loc = ["stacks", "templates", "%s.%s" % (name, ext)] |
| 133 | fullpath = os.path.join(os.path.dirname(__file__), *loc) |
Sean Dague | e0a65d1 | 2014-03-25 15:59:16 -0400 | [diff] [blame] | 134 | |
| 135 | with open(fullpath, "r") as f: |
| 136 | content = f.read() |
| 137 | return content |
| 138 | |
| 139 | @classmethod |
Ghanshyam | 961ea1a | 2014-06-09 10:56:00 +0900 | [diff] [blame] | 140 | def load_template(cls, name, ext='yaml'): |
| 141 | loc = ["stacks", "templates", "%s.%s" % (name, ext)] |
| 142 | fullpath = os.path.join(os.path.dirname(__file__), *loc) |
| 143 | |
| 144 | with open(fullpath, "r") as f: |
| 145 | return yaml.safe_load(f) |
| 146 | |
| 147 | @classmethod |
Andrea Frittoli | 556f796 | 2014-09-15 13:14:54 +0100 | [diff] [blame] | 148 | def resource_cleanup(cls): |
Steven Hardy | 5be93e8 | 2014-04-02 21:24:05 +0100 | [diff] [blame] | 149 | cls._clear_stacks() |
| 150 | cls._clear_keypairs() |
huangtianhua | 01cba0a | 2014-04-30 16:18:03 +0800 | [diff] [blame] | 151 | cls._clear_images() |
Andrea Frittoli | 556f796 | 2014-09-15 13:14:54 +0100 | [diff] [blame] | 152 | super(BaseOrchestrationTest, cls).resource_cleanup() |
Steve Baker | d2525a9 | 2013-05-06 15:29:03 +1200 | [diff] [blame] | 153 | |
Steve Baker | 38d8f09 | 2013-06-12 12:47:16 +1200 | [diff] [blame] | 154 | @staticmethod |
| 155 | def stack_output(stack, output_key): |
Steven Hardy | 48ec705 | 2014-03-28 14:06:27 +0000 | [diff] [blame] | 156 | """Return a stack output value for a given key.""" |
Steve Baker | 38d8f09 | 2013-06-12 12:47:16 +1200 | [diff] [blame] | 157 | return next((o['output_value'] for o in stack['outputs'] |
| 158 | if o['output_key'] == output_key), None) |
Steven Hardy | e2a7444 | 2014-03-25 12:10:52 +0000 | [diff] [blame] | 159 | |
| 160 | def assert_fields_in_dict(self, obj, *fields): |
| 161 | for field in fields: |
| 162 | self.assertIn(field, obj) |
| 163 | |
| 164 | def list_resources(self, stack_identifier): |
| 165 | """Get a dict mapping of resource names to types.""" |
David Kranz | 8ad924b | 2015-01-16 16:50:18 -0500 | [diff] [blame] | 166 | resources = self.client.list_resources(stack_identifier) |
Steven Hardy | e2a7444 | 2014-03-25 12:10:52 +0000 | [diff] [blame] | 167 | self.assertIsInstance(resources, list) |
| 168 | for res in resources: |
| 169 | self.assert_fields_in_dict(res, 'logical_resource_id', |
| 170 | 'resource_type', 'resource_status', |
| 171 | 'updated_time') |
| 172 | |
| 173 | return dict((r['resource_name'], r['resource_type']) |
| 174 | for r in resources) |
Steven Hardy | 8b54fc5 | 2014-03-28 16:15:51 +0000 | [diff] [blame] | 175 | |
| 176 | def get_stack_output(self, stack_identifier, output_key): |
Ken'ichi Ohmichi | e06f0e7 | 2015-04-06 02:52:11 +0000 | [diff] [blame] | 177 | body = self.client.show_stack(stack_identifier) |
Steven Hardy | 8b54fc5 | 2014-03-28 16:15:51 +0000 | [diff] [blame] | 178 | return self.stack_output(body, output_key) |