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