blob: 87c062b9a2072ae17a25357de678456d44226d88 [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
Jay Pipes13b479b2012-06-11 14:52:27 -04002# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
David Kranzcf0040c2012-06-26 09:46:56 -040016import time
Jay Pipesf38eaac2012-06-21 13:37:35 -040017
Doug Hellmann583ce2c2015-03-11 14:55:46 +000018from oslo_log import log as logging
Matthew Treinish01472ff2015-02-20 17:26:52 -050019
Ghanshyam05049dd2016-02-12 17:44:48 +090020from tempest.api.compute import api_microversion_fixture
Joseph Lanouxb3e1f872015-01-30 11:13:07 +000021from tempest.common import compute
Ken'ichi Ohmichi8b9c7802015-07-08 05:57:37 +000022from tempest.common import waiters
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000023from tempest import config
Sean Dague20e98612016-01-06 14:33:28 -050024from tempest import exceptions
Sergey Nikitin8654e5b2017-06-04 22:09:56 +040025from tempest.lib.common import api_version_request
Ghanshyam1f47cf92016-02-25 04:57:18 +090026from tempest.lib.common import api_version_utils
Ken'ichi Ohmichi757833a2017-03-10 10:30:30 -080027from tempest.lib.common.utils import data_utils
Jordan Pittier9e227c52016-02-09 14:35:18 +010028from tempest.lib.common.utils import test_utils
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050029from tempest.lib import exceptions as lib_exc
Attila Fazekasdc216422013-01-29 15:12:14 +010030import tempest.test
Jay Pipesf38eaac2012-06-21 13:37:35 -040031
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000032CONF = config.CONF
Tiago Melloeda03b52012-08-22 23:47:29 -030033
Jay Pipesf38eaac2012-06-21 13:37:35 -040034LOG = logging.getLogger(__name__)
Daryl Walleckc7251962012-03-12 17:26:54 -050035
36
Ken'ichi Ohmichi4d237e72015-11-05 06:32:33 +000037class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
38 tempest.test.BaseTestCase):
Sean Daguef237ccb2013-01-04 15:19:14 -050039 """Base test case class for all Compute API tests."""
Daryl Walleckc7251962012-03-12 17:26:54 -050040
Attila Fazekas430dae32013-10-17 15:19:32 +020041 force_tenant_isolation = False
Chris Yeoh8a79b9d2013-01-18 19:32:47 +103042
Andrea Frittolib21de6c2015-02-06 20:12:38 +000043 # TODO(andreaf) We should care also for the alt_manager here
44 # but only once client lazy load in the manager is done
45 credentials = ['primary']
46
Jay Pipesf38eaac2012-06-21 13:37:35 -040047 @classmethod
Emily Hugenbruche7991d92014-12-12 16:53:36 +000048 def skip_checks(cls):
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +000049 super(BaseV2ComputeTest, cls).skip_checks()
Matthew Treinishf8ff3582015-08-25 12:41:56 -040050 if not CONF.service_available.nova:
51 raise cls.skipException("Nova is not available")
ghanshyam29591532016-03-11 17:12:43 +090052 cfg_min_version = CONF.compute.min_microversion
53 cfg_max_version = CONF.compute.max_microversion
Ken'ichi Ohmichi4d237e72015-11-05 06:32:33 +000054 api_version_utils.check_skip_with_microversion(cls.min_microversion,
55 cls.max_microversion,
56 cfg_min_version,
57 cfg_max_version)
Jay Pipesf38eaac2012-06-21 13:37:35 -040058
Emily Hugenbruche7991d92014-12-12 16:53:36 +000059 @classmethod
60 def setup_credentials(cls):
61 cls.set_network_resources()
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +000062 super(BaseV2ComputeTest, cls).setup_credentials()
Daryl Walleckc7251962012-03-12 17:26:54 -050063
Emily Hugenbruche7991d92014-12-12 16:53:36 +000064 @classmethod
65 def setup_clients(cls):
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +000066 super(BaseV2ComputeTest, cls).setup_clients()
Jordan Pittier8160d312017-04-18 11:52:23 +020067 cls.servers_client = cls.os_primary.servers_client
68 cls.server_groups_client = cls.os_primary.server_groups_client
69 cls.flavors_client = cls.os_primary.flavors_client
70 cls.compute_images_client = cls.os_primary.compute_images_client
71 cls.extensions_client = cls.os_primary.extensions_client
72 cls.floating_ip_pools_client = cls.os_primary.floating_ip_pools_client
73 cls.floating_ips_client = cls.os_primary.compute_floating_ips_client
74 cls.keypairs_client = cls.os_primary.keypairs_client
John Warren5cdbf422016-01-05 12:42:43 -050075 cls.security_group_rules_client = (
Jordan Pittier8160d312017-04-18 11:52:23 +020076 cls.os_primary.compute_security_group_rules_client)
77 cls.security_groups_client =\
78 cls.os_primary.compute_security_groups_client
79 cls.quotas_client = cls.os_primary.quotas_client
80 cls.compute_networks_client = cls.os_primary.compute_networks_client
81 cls.limits_client = cls.os_primary.limits_client
82 cls.volumes_extensions_client =\
83 cls.os_primary.volumes_extensions_client
84 cls.snapshots_extensions_client =\
85 cls.os_primary.snapshots_extensions_client
86 cls.interfaces_client = cls.os_primary.interfaces_client
87 cls.fixed_ips_client = cls.os_primary.fixed_ips_client
88 cls.availability_zone_client = cls.os_primary.availability_zone_client
89 cls.agents_client = cls.os_primary.agents_client
90 cls.aggregates_client = cls.os_primary.aggregates_client
91 cls.services_client = cls.os_primary.services_client
Emily Hugenbruche7991d92014-12-12 16:53:36 +000092 cls.instance_usages_audit_log_client = (
Jordan Pittier8160d312017-04-18 11:52:23 +020093 cls.os_primary.instance_usages_audit_log_client)
94 cls.hypervisor_client = cls.os_primary.hypervisor_client
95 cls.certificates_client = cls.os_primary.certificates_client
96 cls.migrations_client = cls.os_primary.migrations_client
Emily Hugenbruche7991d92014-12-12 16:53:36 +000097 cls.security_group_default_rules_client = (
Jordan Pittier8160d312017-04-18 11:52:23 +020098 cls.os_primary.security_group_default_rules_client)
99 cls.versions_client = cls.os_primary.compute_versions_client
Andrea Frittolia6b30152017-08-04 10:46:10 +0100100 if CONF.service_available.cinder:
101 cls.volumes_client = cls.os_primary.volumes_client_latest
Ivan Kolodyazhnybcfc32e2015-08-06 13:31:36 +0300102
Emily Hugenbruche7991d92014-12-12 16:53:36 +0000103 @classmethod
104 def resource_setup(cls):
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +0000105 super(BaseV2ComputeTest, cls).resource_setup()
Ghanshyam05049dd2016-02-12 17:44:48 +0900106 cls.request_microversion = (
107 api_version_utils.select_request_microversion(
108 cls.min_microversion,
ghanshyam29591532016-03-11 17:12:43 +0900109 CONF.compute.min_microversion))
Matthew Treinishb0a78fc2014-01-29 16:49:12 +0000110 cls.build_interval = CONF.compute.build_interval
111 cls.build_timeout = CONF.compute.build_timeout
Matthew Treinishb0a78fc2014-01-29 16:49:12 +0000112 cls.image_ref = CONF.compute.image_ref
113 cls.image_ref_alt = CONF.compute.image_ref_alt
114 cls.flavor_ref = CONF.compute.flavor_ref
115 cls.flavor_ref_alt = CONF.compute.flavor_ref_alt
lanoux283273b2015-12-04 03:01:54 -0800116 cls.ssh_user = CONF.validation.image_ssh_user
117 cls.image_ssh_user = CONF.validation.image_ssh_user
118 cls.image_ssh_password = CONF.validation.image_ssh_password
Jay Pipesf38eaac2012-06-21 13:37:35 -0400119 cls.servers = []
Sean Dagued62bf1c2013-06-05 14:36:25 -0400120 cls.images = []
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800121 cls.security_groups = []
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530122 cls.server_groups = []
Matt Riedemann342b37c2016-09-21 15:38:12 -0400123 cls.volumes = []
Matthew Treinishf7fca6a2013-12-09 16:27:23 +0000124
Emily Hugenbruche7991d92014-12-12 16:53:36 +0000125 @classmethod
126 def resource_cleanup(cls):
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900127 cls.clear_resources('images', cls.images,
128 cls.compute_images_client.delete_image)
Emily Hugenbruche7991d92014-12-12 16:53:36 +0000129 cls.clear_servers()
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900130 cls.clear_resources('security groups', cls.security_groups,
131 cls.security_groups_client.delete_security_group)
132 cls.clear_resources('server groups', cls.server_groups,
133 cls.server_groups_client.delete_server_group)
Matt Riedemann342b37c2016-09-21 15:38:12 -0400134 cls.clear_volumes()
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +0000135 super(BaseV2ComputeTest, cls).resource_cleanup()
Ken'ichi Ohmichi543a5d42014-05-02 08:44:15 +0900136
Matthew Treinishf7fca6a2013-12-09 16:27:23 +0000137 @classmethod
Jay Pipes444c3e62012-10-04 19:26:35 -0400138 def clear_servers(cls):
Salvatore1422a9a2014-10-08 15:53:25 +0200139 LOG.debug('Clearing servers: %s', ','.join(
140 server['id'] for server in cls.servers))
Jay Pipes444c3e62012-10-04 19:26:35 -0400141 for server in cls.servers:
Dan Smith74e7bcb2012-08-21 09:18:26 -0700142 try:
Jordan Pittier9e227c52016-02-09 14:35:18 +0100143 test_utils.call_and_ignore_notfound_exc(
144 cls.servers_client.delete_server, server['id'])
Joe Gordon0c335792014-09-23 12:36:11 -0700145 except Exception:
Jordan Pittier525ec712016-12-07 17:51:26 +0100146 LOG.exception('Deleting server %s failed', server['id'])
Dan Smith74e7bcb2012-08-21 09:18:26 -0700147
Jay Pipes444c3e62012-10-04 19:26:35 -0400148 for server in cls.servers:
Dan Smith74e7bcb2012-08-21 09:18:26 -0700149 try:
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000150 waiters.wait_for_server_termination(cls.servers_client,
151 server['id'])
Dan Smith74e7bcb2012-08-21 09:18:26 -0700152 except Exception:
Jordan Pittier525ec712016-12-07 17:51:26 +0100153 LOG.exception('Waiting for deletion of server %s failed',
154 server['id'])
Dan Smith74e7bcb2012-08-21 09:18:26 -0700155
156 @classmethod
Attila Fazekas305e65b2013-10-29 13:23:07 +0100157 def server_check_teardown(cls):
158 """Checks is the shared server clean enough for subsequent test.
Ken'ichi Ohmichi88363cb2015-11-19 08:00:54 +0000159
Attila Fazekas305e65b2013-10-29 13:23:07 +0100160 Method will delete the server when it's dirty.
161 The setUp method is responsible for creating a new server.
162 Exceptions raised in tearDown class are fails the test case,
Marian Horban6afb0232015-11-10 22:47:12 -0500163 This method supposed to use only by tearDown methods, when
Attila Fazekas305e65b2013-10-29 13:23:07 +0100164 the shared server_id is stored in the server_id of the class.
165 """
166 if getattr(cls, 'server_id', None) is not None:
167 try:
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000168 waiters.wait_for_server_status(cls.servers_client,
169 cls.server_id, 'ACTIVE')
Attila Fazekas305e65b2013-10-29 13:23:07 +0100170 except Exception as exc:
171 LOG.exception(exc)
172 cls.servers_client.delete_server(cls.server_id)
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000173 waiters.wait_for_server_termination(cls.servers_client,
174 cls.server_id)
Attila Fazekas305e65b2013-10-29 13:23:07 +0100175 cls.server_id = None
176 raise
177
178 @classmethod
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900179 def clear_resources(cls, resource_name, resources, resource_del_func):
180 LOG.debug('Clearing %s: %s', resource_name,
181 ','.join(map(str, resources)))
182 for res_id in resources:
Sean Dagued62bf1c2013-06-05 14:36:25 -0400183 try:
Jordan Pittier9e227c52016-02-09 14:35:18 +0100184 test_utils.call_and_ignore_notfound_exc(
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900185 resource_del_func, res_id)
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800186 except Exception as exc:
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900187 LOG.exception('Exception raised deleting %s: %s',
188 resource_name, res_id)
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800189 LOG.exception(exc)
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800190
191 @classmethod
Joe Gordon8843f0f2015-03-17 15:07:34 -0700192 def create_test_server(cls, validatable=False, volume_backed=False,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100193 validation_resources=None, **kwargs):
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000194 """Wrapper utility that returns a test server.
Rohit Karajgidc300b22012-05-04 08:11:00 -0700195
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000196 This wrapper utility calls the common create test server and
197 returns a test server. The purpose of this wrapper is to minimize
198 the impact on the code of the tests already using this
199 function.
Joe Gordon8843f0f2015-03-17 15:07:34 -0700200
201 :param validatable: Whether the server will be pingable or sshable.
202 :param volume_backed: Whether the instance is volume backed or not.
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100203 :param validation_resources: Dictionary of validation resources as
204 returned by `get_class_validation_resources`.
205 :param kwargs: Extra arguments are passed down to the
206 `compute.create_test_server` call.
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000207 """
zhufl7ae22682016-09-18 15:22:33 +0800208 if 'name' not in kwargs:
209 kwargs['name'] = data_utils.rand_name(cls.__name__ + "-server")
Sergey Nikitin8654e5b2017-06-04 22:09:56 +0400210
211 request_version = api_version_request.APIVersionRequest(
212 cls.request_microversion)
213 v2_37_version = api_version_request.APIVersionRequest('2.37')
214
215 # NOTE(snikitin): since microversion v2.37 'networks' field is required
216 if request_version >= v2_37_version and 'networks' not in kwargs:
217 kwargs['networks'] = 'none'
218
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000219 tenant_network = cls.get_tenant_network()
220 body, servers = compute.create_test_server(
zhufl04190882017-05-23 10:21:48 +0800221 cls.os_primary,
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000222 validatable,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100223 validation_resources=validation_resources,
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000224 tenant_network=tenant_network,
Joe Gordon8843f0f2015-03-17 15:07:34 -0700225 volume_backed=volume_backed,
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000226 **kwargs)
Ken'ichi Ohmichi51c8c262013-12-21 03:30:37 +0900227
228 cls.servers.extend(servers)
Sean Dague9b669e32012-12-13 18:40:08 -0500229
David Kranz0fb14292015-02-11 15:55:20 -0500230 return body
Sean Dague9b669e32012-12-13 18:40:08 -0500231
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800232 @classmethod
233 def create_security_group(cls, name=None, description=None):
234 if name is None:
235 name = data_utils.rand_name(cls.__name__ + "-securitygroup")
236 if description is None:
Ken'ichi Ohmichi4937f562015-03-23 00:15:01 +0000237 description = data_utils.rand_name('description')
ghanshyamb610b772015-08-24 17:29:38 +0900238 body = cls.security_groups_client.create_security_group(
239 name=name, description=description)['security_group']
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900240 cls.security_groups.append(body['id'])
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800241
David Kranz9964b4e2015-02-06 15:45:29 -0500242 return body
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800243
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530244 @classmethod
Ghanshyam2a180b82014-06-16 13:54:22 +0900245 def create_test_server_group(cls, name="", policy=None):
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530246 if not name:
247 name = data_utils.rand_name(cls.__name__ + "-Server-Group")
Ghanshyam2a180b82014-06-16 13:54:22 +0900248 if policy is None:
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530249 policy = ['affinity']
Ken'ichi Ohmichi1f36daa2015-09-30 01:41:34 +0000250 body = cls.server_groups_client.create_server_group(
251 name=name, policies=policy)['server_group']
David Kranzda5d4ec2014-06-24 16:04:57 -0400252 cls.server_groups.append(body['id'])
David Kranzae99b9a2015-02-16 13:37:01 -0500253 return body
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530254
David Kranzcf0040c2012-06-26 09:46:56 -0400255 def wait_for(self, condition):
Sean Daguef237ccb2013-01-04 15:19:14 -0500256 """Repeatedly calls condition() until a timeout."""
David Kranzcf0040c2012-06-26 09:46:56 -0400257 start_time = int(time.time())
258 while True:
259 try:
260 condition()
Matthew Treinish05d9fb92012-12-07 16:14:05 -0500261 except Exception:
David Kranzcf0040c2012-06-26 09:46:56 -0400262 pass
263 else:
264 return
265 if int(time.time()) - start_time >= self.build_timeout:
266 condition()
267 return
268 time.sleep(self.build_interval)
Jay Pipesf38eaac2012-06-21 13:37:35 -0400269
Matt Riedemann807d0562014-01-27 12:03:10 -0800270 @staticmethod
271 def _delete_volume(volumes_client, volume_id):
272 """Deletes the given volume and waits for it to be gone."""
273 try:
Joseph Lanoux6809bab2014-12-18 14:57:18 +0000274 volumes_client.delete_volume(volume_id)
Matt Riedemann807d0562014-01-27 12:03:10 -0800275 # TODO(mriedem): We should move the wait_for_resource_deletion
276 # into the delete_volume method as a convenience to the caller.
277 volumes_client.wait_for_resource_deletion(volume_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900278 except lib_exc.NotFound:
zhangguoqing6c096642016-01-04 06:17:21 +0000279 LOG.warning("Unable to delete volume '%s' since it was not found. "
Jordan Pittier525ec712016-12-07 17:51:26 +0100280 "Maybe it was already deleted?", volume_id)
Matt Riedemann807d0562014-01-27 12:03:10 -0800281
Attila Fazekas423834d2014-03-14 17:33:13 +0100282 @classmethod
283 def prepare_instance_network(cls):
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000284 if (CONF.validation.auth_method != 'disabled' and
285 CONF.validation.connect_method == 'floating'):
Attila Fazekas423834d2014-03-14 17:33:13 +0100286 cls.set_network_resources(network=True, subnet=True, router=True,
287 dhcp=True)
288
ivan-zhu8f992be2013-07-31 14:56:58 +0800289 @classmethod
290 def create_image_from_server(cls, server_id, **kwargs):
291 """Wrapper utility that returns an image created from the server."""
zhufl35a694b2017-02-14 17:10:53 +0800292 name = kwargs.pop('name',
293 data_utils.rand_name(cls.__name__ + "-image"))
294 wait_until = kwargs.pop('wait_until', None)
295 wait_for_server = kwargs.pop('wait_for_server', True)
ivan-zhu8f992be2013-07-31 14:56:58 +0800296
zhufl35a694b2017-02-14 17:10:53 +0800297 image = cls.compute_images_client.create_image(server_id, name=name,
298 **kwargs)
David Kranza5299eb2015-01-15 17:24:05 -0500299 image_id = data_utils.parse_image_id(image.response['location'])
ivan-zhu8f992be2013-07-31 14:56:58 +0800300 cls.images.append(image_id)
301
zhufl35a694b2017-02-14 17:10:53 +0800302 if wait_until is not None:
Matt Riedemann13954352017-02-07 14:03:54 -0500303 try:
304 waiters.wait_for_image_status(cls.compute_images_client,
zhufl35a694b2017-02-14 17:10:53 +0800305 image_id, wait_until)
Matt Riedemann13954352017-02-07 14:03:54 -0500306 except lib_exc.NotFound:
zhufl35a694b2017-02-14 17:10:53 +0800307 if wait_until.upper() == 'ACTIVE':
Matt Riedemann13954352017-02-07 14:03:54 -0500308 # If the image is not found after create_image returned
309 # that means the snapshot failed in nova-compute and nova
310 # deleted the image. There should be a compute fault
311 # recorded with the server in that case, so get the server
312 # and dump some details.
313 server = (
314 cls.servers_client.show_server(server_id)['server'])
315 if 'fault' in server:
316 raise exceptions.SnapshotNotFoundException(
317 server['fault'], image_id=image_id)
318 else:
319 raise exceptions.SnapshotNotFoundException(
320 image_id=image_id)
321 else:
322 raise
Ghanshyamae76c122015-12-22 13:41:35 +0900323 image = cls.compute_images_client.show_image(image_id)['image']
ivan-zhu8f992be2013-07-31 14:56:58 +0800324
zhufl35a694b2017-02-14 17:10:53 +0800325 if wait_until.upper() == 'ACTIVE':
326 if wait_for_server:
Bob Ball5fe62392017-02-20 09:51:00 +0000327 waiters.wait_for_server_status(cls.servers_client,
328 server_id, 'ACTIVE')
David Kranza5299eb2015-01-15 17:24:05 -0500329 return image
ivan-zhu8f992be2013-07-31 14:56:58 +0800330
331 @classmethod
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000332 def rebuild_server(cls, server_id, validatable=False, **kwargs):
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100333 """Destroy an existing class level server and creates a new one
334
335 Some test classes use a test server that can be used by multiple
336 tests. This is done to optimise runtime and test load.
337 If something goes wrong with the test server, it can be rebuilt
338 using this helper.
339
340 This helper can also be used for the initial provisioning if no
341 server_id is specified.
342
343 :param server_id: UUID of the server to be rebuilt. If None is
344 specified, a new server is provisioned.
345 :param validatable: whether to the server needs to be
346 validatable. When True, validation resources are acquired via
347 the `get_class_validation_resources` helper.
348 :param kwargs: extra paramaters are passed through to the
349 `create_test_server` call.
350 :return: the UUID of the created server.
351 """
Matthew Treinish2cd19a42013-12-02 21:54:42 +0000352 if server_id:
zhufl9b682902016-12-15 09:16:34 +0800353 cls.delete_server(server_id)
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000354
Ghanshyam3390d9f2015-12-25 12:48:02 +0900355 cls.password = data_utils.rand_password()
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000356 server = cls.create_test_server(
357 validatable,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100358 validation_resources=cls.get_class_validation_resources(
359 cls.os_primary),
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000360 wait_until='ACTIVE',
Ghanshyam3390d9f2015-12-25 12:48:02 +0900361 adminPass=cls.password,
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000362 **kwargs)
Matthew Treinish2cd19a42013-12-02 21:54:42 +0000363 return server['id']
ivan-zhu8f992be2013-07-31 14:56:58 +0800364
Matt Riedemann5dc594c2014-01-27 11:40:28 -0800365 @classmethod
Jesse Keating613b4982015-05-04 15:05:19 -0700366 def delete_server(cls, server_id):
367 """Deletes an existing server and waits for it to be gone."""
368 try:
369 cls.servers_client.delete_server(server_id)
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000370 waiters.wait_for_server_termination(cls.servers_client,
371 server_id)
Jesse Keating613b4982015-05-04 15:05:19 -0700372 except Exception:
Jordan Pittier525ec712016-12-07 17:51:26 +0100373 LOG.exception('Failed to delete server %s', server_id)
Jesse Keating613b4982015-05-04 15:05:19 -0700374
375 @classmethod
zhufl3d018b02016-11-25 16:43:04 +0800376 def resize_server(cls, server_id, new_flavor_id, **kwargs):
377 """resize and confirm_resize an server, waits for it to be ACTIVE."""
378 cls.servers_client.resize_server(server_id, new_flavor_id, **kwargs)
379 waiters.wait_for_server_status(cls.servers_client, server_id,
380 'VERIFY_RESIZE')
381 cls.servers_client.confirm_resize_server(server_id)
382 waiters.wait_for_server_status(cls.servers_client, server_id, 'ACTIVE')
383
384 @classmethod
Matt Riedemann5dc594c2014-01-27 11:40:28 -0800385 def delete_volume(cls, volume_id):
386 """Deletes the given volume and waits for it to be gone."""
Felipe Monteiroa40e9b72017-05-05 17:47:10 +0100387 cls._delete_volume(cls.volumes_client, volume_id)
Ken'ichi Ohmichi543a5d42014-05-02 08:44:15 +0900388
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000389 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100390 def get_server_ip(cls, server, validation_resources=None):
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000391 """Get the server fixed or floating IP.
392
Sean Dague20e98612016-01-06 14:33:28 -0500393 Based on the configuration we're in, return a correct ip
394 address for validating that a guest is up.
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100395
396 :param server: The server dict as returned by the API
397 :param validation_resources: The dict of validation resources
398 provisioned for the server.
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000399 """
400 if CONF.validation.connect_method == 'floating':
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100401 if validation_resources:
402 return validation_resources['floating_ip']['ip']
403 else:
404 msg = ('When validation.connect_method equals floating, '
405 'validation_resources cannot be None')
406 raise exceptions.InvalidParam(invalid_param=msg)
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000407 elif CONF.validation.connect_method == 'fixed':
Sean Dague20e98612016-01-06 14:33:28 -0500408 addresses = server['addresses'][CONF.validation.network_for_ssh]
409 for address in addresses:
410 if address['version'] == CONF.validation.ip_version_for_ssh:
411 return address['addr']
zhufl955f82b2016-07-22 11:14:34 +0800412 raise exceptions.ServerUnreachable(server_id=server['id'])
Sean Dague20e98612016-01-06 14:33:28 -0500413 else:
guo yunxianffc4fc02016-11-15 09:56:08 +0800414 raise lib_exc.InvalidConfiguration()
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000415
Ghanshyam05049dd2016-02-12 17:44:48 +0900416 def setUp(self):
417 super(BaseV2ComputeTest, self).setUp()
418 self.useFixture(api_microversion_fixture.APIMicroversionFixture(
419 self.request_microversion))
420
Matt Riedemann342b37c2016-09-21 15:38:12 -0400421 @classmethod
zhufl8d23f922016-12-12 17:29:42 +0800422 def create_volume(cls, image_ref=None, **kwargs):
Matt Riedemann342b37c2016-09-21 15:38:12 -0400423 """Create a volume and wait for it to become 'available'.
424
Artom Lifshitzfc8f8e62016-04-13 11:08:32 +0000425 :param image_ref: Specify an image id to create a bootable volume.
zhufl8d23f922016-12-12 17:29:42 +0800426 :**kwargs: other parameters to create volume.
Matt Riedemann342b37c2016-09-21 15:38:12 -0400427 :returns: The available volume.
428 """
zhufl8d23f922016-12-12 17:29:42 +0800429 if 'size' not in kwargs:
430 kwargs['size'] = CONF.volume.volume_size
431 if 'display_name' not in kwargs:
432 vol_name = data_utils.rand_name(cls.__name__ + '-volume')
433 kwargs['display_name'] = vol_name
Artom Lifshitzfc8f8e62016-04-13 11:08:32 +0000434 if image_ref is not None:
zhufl8d23f922016-12-12 17:29:42 +0800435 kwargs['imageRef'] = image_ref
436 volume = cls.volumes_client.create_volume(**kwargs)['volume']
Matt Riedemann342b37c2016-09-21 15:38:12 -0400437 cls.volumes.append(volume)
lkuchlan52d7b0d2016-11-07 20:53:19 +0200438 waiters.wait_for_volume_resource_status(cls.volumes_client,
439 volume['id'], 'available')
Matt Riedemann342b37c2016-09-21 15:38:12 -0400440 return volume
441
442 @classmethod
443 def clear_volumes(cls):
444 LOG.debug('Clearing volumes: %s', ','.join(
445 volume['id'] for volume in cls.volumes))
446 for volume in cls.volumes:
447 try:
448 test_utils.call_and_ignore_notfound_exc(
449 cls.volumes_client.delete_volume, volume['id'])
450 except Exception:
451 LOG.exception('Deleting volume %s failed', volume['id'])
452
453 for volume in cls.volumes:
454 try:
455 cls.volumes_client.wait_for_resource_deletion(volume['id'])
456 except Exception:
457 LOG.exception('Waiting for deletion of volume %s failed',
458 volume['id'])
459
John Griffith030dd172017-06-27 23:22:14 +0000460 def attach_volume(self, server, volume, device=None, check_reserved=False):
Matt Riedemanncb16a662016-10-01 18:30:05 -0400461 """Attaches volume to server and waits for 'in-use' volume status.
462
463 The volume will be detached when the test tears down.
464
465 :param server: The server to which the volume will be attached.
466 :param volume: The volume to attach.
467 :param device: Optional mountpoint for the attached volume. Note that
468 this is not guaranteed for all hypervisors and is not recommended.
John Griffith030dd172017-06-27 23:22:14 +0000469 :param check_reserved: Consider a status of reserved as valid for
470 completion. This is to handle new Cinder attach where we more
471 accurately use 'reserved' for things like attaching to a shelved
472 server.
Matt Riedemanncb16a662016-10-01 18:30:05 -0400473 """
474 attach_kwargs = dict(volumeId=volume['id'])
475 if device:
476 attach_kwargs['device'] = device
John Griffith030dd172017-06-27 23:22:14 +0000477
zhufl36f0a972017-02-28 15:43:33 +0800478 attachment = self.servers_client.attach_volume(
479 server['id'], **attach_kwargs)['volumeAttachment']
Matt Riedemann342b37c2016-09-21 15:38:12 -0400480 # On teardown detach the volume and wait for it to be available. This
481 # is so we don't error out when trying to delete the volume during
482 # teardown.
lkuchlan52d7b0d2016-11-07 20:53:19 +0200483 self.addCleanup(waiters.wait_for_volume_resource_status,
Matt Riedemann342b37c2016-09-21 15:38:12 -0400484 self.volumes_client, volume['id'], 'available')
485 # Ignore 404s on detach in case the server is deleted or the volume
486 # is already detached.
487 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
488 self.servers_client.detach_volume,
489 server['id'], volume['id'])
John Griffith030dd172017-06-27 23:22:14 +0000490 statuses = ['in-use']
491 if check_reserved:
492 statuses.append('reserved')
lkuchlan52d7b0d2016-11-07 20:53:19 +0200493 waiters.wait_for_volume_resource_status(self.volumes_client,
John Griffith030dd172017-06-27 23:22:14 +0000494 volume['id'], statuses)
zhufl36f0a972017-02-28 15:43:33 +0800495 return attachment
Matt Riedemann342b37c2016-09-21 15:38:12 -0400496
Ken'ichi Ohmichi543a5d42014-05-02 08:44:15 +0900497
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +0000498class BaseV2ComputeAdminTest(BaseV2ComputeTest):
Ken'ichi Ohmichibcefa3d2014-05-09 08:14:05 +0900499 """Base test case class for Compute Admin API tests."""
ivan-zhuf2b00502013-10-18 10:06:52 +0800500
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000501 credentials = ['primary', 'admin']
Emily Hugenbruche7991d92014-12-12 16:53:36 +0000502
503 @classmethod
504 def setup_clients(cls):
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +0000505 super(BaseV2ComputeAdminTest, cls).setup_clients()
Ken'ichi Ohmichi9f5adf82014-12-12 04:01:32 +0000506 cls.availability_zone_admin_client = (
Jordan Pittier8160d312017-04-18 11:52:23 +0200507 cls.os_admin.availability_zone_client)
508 cls.admin_flavors_client = cls.os_admin.flavors_client
509 cls.admin_servers_client = cls.os_admin.servers_client
zhufl36eeab02017-01-18 11:49:04 +0800510
511 def create_flavor(self, ram, vcpus, disk, name=None,
512 is_public='True', **kwargs):
513 if name is None:
514 name = data_utils.rand_name(self.__class__.__name__ + "-flavor")
515 id = kwargs.pop('id', data_utils.rand_int_id(start=1000))
516 client = self.admin_flavors_client
517 flavor = client.create_flavor(
518 ram=ram, vcpus=vcpus, disk=disk, name=name,
519 id=id, is_public=is_public, **kwargs)['flavor']
520 self.addCleanup(client.wait_for_resource_deletion, flavor['id'])
521 self.addCleanup(client.delete_flavor, flavor['id'])
522 return flavor
Duc Truong09941202017-06-07 10:15:20 -0700523
524 def get_host_for_server(self, server_id):
525 server_details = self.admin_servers_client.show_server(server_id)
526 return server_details['server']['OS-EXT-SRV-ATTR:host']
527
528 def get_host_other_than(self, server_id):
529 source_host = self.get_host_for_server(server_id)
530
531 list_hosts_resp = self.os_admin.hosts_client.list_hosts()['hosts']
532 hosts = [
533 host_record['host_name']
534 for host_record in list_hosts_resp
535 if host_record['service'] == 'compute'
536 ]
537
538 for target_host in hosts:
539 if source_host != target_host:
540 return target_host