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