blob: 2b32a86d861a57f3debc4e2d0e5a2075060d4b03 [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
Ken'ichi Ohmichi543a5d42014-05-02 08:44:15 +0900119
Matthew Treinishf7fca6a2013-12-09 16:27:23 +0000120 @classmethod
Attila Fazekas305e65b2013-10-29 13:23:07 +0100121 def server_check_teardown(cls):
122 """Checks is the shared server clean enough for subsequent test.
Ken'ichi Ohmichi88363cb2015-11-19 08:00:54 +0000123
Attila Fazekas305e65b2013-10-29 13:23:07 +0100124 Method will delete the server when it's dirty.
125 The setUp method is responsible for creating a new server.
126 Exceptions raised in tearDown class are fails the test case,
Marian Horban6afb0232015-11-10 22:47:12 -0500127 This method supposed to use only by tearDown methods, when
Attila Fazekas305e65b2013-10-29 13:23:07 +0100128 the shared server_id is stored in the server_id of the class.
129 """
130 if getattr(cls, 'server_id', None) is not None:
131 try:
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000132 waiters.wait_for_server_status(cls.servers_client,
133 cls.server_id, 'ACTIVE')
Attila Fazekas305e65b2013-10-29 13:23:07 +0100134 except Exception as exc:
135 LOG.exception(exc)
136 cls.servers_client.delete_server(cls.server_id)
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000137 waiters.wait_for_server_termination(cls.servers_client,
138 cls.server_id)
Attila Fazekas305e65b2013-10-29 13:23:07 +0100139 cls.server_id = None
140 raise
141
142 @classmethod
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900143 def clear_resources(cls, resource_name, resources, resource_del_func):
144 LOG.debug('Clearing %s: %s', resource_name,
145 ','.join(map(str, resources)))
146 for res_id in resources:
Sean Dagued62bf1c2013-06-05 14:36:25 -0400147 try:
Jordan Pittier9e227c52016-02-09 14:35:18 +0100148 test_utils.call_and_ignore_notfound_exc(
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900149 resource_del_func, res_id)
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800150 except Exception as exc:
Masayuki Igawa77d3f0f2017-03-10 18:57:00 +0900151 LOG.exception('Exception raised deleting %s: %s',
152 resource_name, res_id)
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800153 LOG.exception(exc)
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800154
155 @classmethod
Joe Gordon8843f0f2015-03-17 15:07:34 -0700156 def create_test_server(cls, validatable=False, volume_backed=False,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100157 validation_resources=None, **kwargs):
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000158 """Wrapper utility that returns a test server.
Rohit Karajgidc300b22012-05-04 08:11:00 -0700159
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000160 This wrapper utility calls the common create test server and
161 returns a test server. The purpose of this wrapper is to minimize
162 the impact on the code of the tests already using this
163 function.
Joe Gordon8843f0f2015-03-17 15:07:34 -0700164
165 :param validatable: Whether the server will be pingable or sshable.
166 :param volume_backed: Whether the instance is volume backed or not.
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100167 :param validation_resources: Dictionary of validation resources as
168 returned by `get_class_validation_resources`.
169 :param kwargs: Extra arguments are passed down to the
170 `compute.create_test_server` call.
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000171 """
zhufl7ae22682016-09-18 15:22:33 +0800172 if 'name' not in kwargs:
173 kwargs['name'] = data_utils.rand_name(cls.__name__ + "-server")
Sergey Nikitin8654e5b2017-06-04 22:09:56 +0400174
175 request_version = api_version_request.APIVersionRequest(
176 cls.request_microversion)
177 v2_37_version = api_version_request.APIVersionRequest('2.37')
178
179 # NOTE(snikitin): since microversion v2.37 'networks' field is required
180 if request_version >= v2_37_version and 'networks' not in kwargs:
181 kwargs['networks'] = 'none'
182
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000183 tenant_network = cls.get_tenant_network()
184 body, servers = compute.create_test_server(
zhufl04190882017-05-23 10:21:48 +0800185 cls.os_primary,
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000186 validatable,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100187 validation_resources=validation_resources,
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000188 tenant_network=tenant_network,
Joe Gordon8843f0f2015-03-17 15:07:34 -0700189 volume_backed=volume_backed,
Joseph Lanouxb3e1f872015-01-30 11:13:07 +0000190 **kwargs)
Ken'ichi Ohmichi51c8c262013-12-21 03:30:37 +0900191
Andrea Frittoli0d0a3f32017-08-29 18:21:37 +0100192 # For each server schedule wait and delete, so we first delete all
193 # and then wait for all
194 for server in servers:
195 cls.addClassResourceCleanup(waiters.wait_for_server_termination,
196 cls.servers_client, server['id'])
197 for server in servers:
198 cls.addClassResourceCleanup(
199 test_utils.call_and_ignore_notfound_exc,
200 cls.servers_client.delete_server, server['id'])
Sean Dague9b669e32012-12-13 18:40:08 -0500201
David Kranz0fb14292015-02-11 15:55:20 -0500202 return body
Sean Dague9b669e32012-12-13 18:40:08 -0500203
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800204 @classmethod
205 def create_security_group(cls, name=None, description=None):
206 if name is None:
207 name = data_utils.rand_name(cls.__name__ + "-securitygroup")
208 if description is None:
Ken'ichi Ohmichi4937f562015-03-23 00:15:01 +0000209 description = data_utils.rand_name('description')
ghanshyamb610b772015-08-24 17:29:38 +0900210 body = cls.security_groups_client.create_security_group(
211 name=name, description=description)['security_group']
Andrea Frittoli238818c2017-08-29 18:28:11 +0100212 cls.addClassResourceCleanup(
213 test_utils.call_and_ignore_notfound_exc,
214 cls.security_groups_client.delete_security_group,
215 body['id'])
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800216
David Kranz9964b4e2015-02-06 15:45:29 -0500217 return body
Zhi Kun Liu02e7a7b2014-01-08 16:08:32 +0800218
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530219 @classmethod
Ghanshyam2a180b82014-06-16 13:54:22 +0900220 def create_test_server_group(cls, name="", policy=None):
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530221 if not name:
222 name = data_utils.rand_name(cls.__name__ + "-Server-Group")
Ghanshyam2a180b82014-06-16 13:54:22 +0900223 if policy is None:
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530224 policy = ['affinity']
Ken'ichi Ohmichi1f36daa2015-09-30 01:41:34 +0000225 body = cls.server_groups_client.create_server_group(
226 name=name, policies=policy)['server_group']
Andrea Frittoli238818c2017-08-29 18:28:11 +0100227 cls.addClassResourceCleanup(
228 test_utils.call_and_ignore_notfound_exc,
229 cls.server_groups_client.delete_server_group,
230 body['id'])
David Kranzae99b9a2015-02-16 13:37:01 -0500231 return body
Abhijeet.Jain87dd4452014-04-23 15:51:23 +0530232
David Kranzcf0040c2012-06-26 09:46:56 -0400233 def wait_for(self, condition):
Sean Daguef237ccb2013-01-04 15:19:14 -0500234 """Repeatedly calls condition() until a timeout."""
David Kranzcf0040c2012-06-26 09:46:56 -0400235 start_time = int(time.time())
236 while True:
237 try:
238 condition()
Matthew Treinish05d9fb92012-12-07 16:14:05 -0500239 except Exception:
David Kranzcf0040c2012-06-26 09:46:56 -0400240 pass
241 else:
242 return
243 if int(time.time()) - start_time >= self.build_timeout:
244 condition()
245 return
246 time.sleep(self.build_interval)
Jay Pipesf38eaac2012-06-21 13:37:35 -0400247
Attila Fazekas423834d2014-03-14 17:33:13 +0100248 @classmethod
249 def prepare_instance_network(cls):
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000250 if (CONF.validation.auth_method != 'disabled' and
251 CONF.validation.connect_method == 'floating'):
Attila Fazekas423834d2014-03-14 17:33:13 +0100252 cls.set_network_resources(network=True, subnet=True, router=True,
253 dhcp=True)
254
ivan-zhu8f992be2013-07-31 14:56:58 +0800255 @classmethod
256 def create_image_from_server(cls, server_id, **kwargs):
257 """Wrapper utility that returns an image created from the server."""
zhufl35a694b2017-02-14 17:10:53 +0800258 name = kwargs.pop('name',
259 data_utils.rand_name(cls.__name__ + "-image"))
260 wait_until = kwargs.pop('wait_until', None)
261 wait_for_server = kwargs.pop('wait_for_server', True)
ivan-zhu8f992be2013-07-31 14:56:58 +0800262
zhufl35a694b2017-02-14 17:10:53 +0800263 image = cls.compute_images_client.create_image(server_id, name=name,
264 **kwargs)
Felipe Monteiroe65ec452017-09-26 06:47:03 +0100265 if api_version_utils.compare_version_header_to_response(
266 "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
267 image_id = image['image_id']
268 else:
269 image_id = data_utils.parse_image_id(image.response['location'])
Andrea Frittolib17f7a32017-08-29 17:45:58 +0100270 cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
271 cls.compute_images_client.delete_image,
272 image_id)
ivan-zhu8f992be2013-07-31 14:56:58 +0800273
zhufl35a694b2017-02-14 17:10:53 +0800274 if wait_until is not None:
Matt Riedemann13954352017-02-07 14:03:54 -0500275 try:
276 waiters.wait_for_image_status(cls.compute_images_client,
zhufl35a694b2017-02-14 17:10:53 +0800277 image_id, wait_until)
Matt Riedemann13954352017-02-07 14:03:54 -0500278 except lib_exc.NotFound:
zhufl35a694b2017-02-14 17:10:53 +0800279 if wait_until.upper() == 'ACTIVE':
Matt Riedemann13954352017-02-07 14:03:54 -0500280 # If the image is not found after create_image returned
281 # that means the snapshot failed in nova-compute and nova
282 # deleted the image. There should be a compute fault
283 # recorded with the server in that case, so get the server
284 # and dump some details.
285 server = (
286 cls.servers_client.show_server(server_id)['server'])
287 if 'fault' in server:
288 raise exceptions.SnapshotNotFoundException(
289 server['fault'], image_id=image_id)
290 else:
291 raise exceptions.SnapshotNotFoundException(
292 image_id=image_id)
293 else:
294 raise
Ghanshyamae76c122015-12-22 13:41:35 +0900295 image = cls.compute_images_client.show_image(image_id)['image']
ivan-zhu8f992be2013-07-31 14:56:58 +0800296
zhufl35a694b2017-02-14 17:10:53 +0800297 if wait_until.upper() == 'ACTIVE':
298 if wait_for_server:
Bob Ball5fe62392017-02-20 09:51:00 +0000299 waiters.wait_for_server_status(cls.servers_client,
300 server_id, 'ACTIVE')
David Kranza5299eb2015-01-15 17:24:05 -0500301 return image
ivan-zhu8f992be2013-07-31 14:56:58 +0800302
303 @classmethod
zhuflba0e5532017-09-13 10:51:07 +0800304 def recreate_server(cls, server_id, validatable=False, **kwargs):
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100305 """Destroy an existing class level server and creates a new one
306
307 Some test classes use a test server that can be used by multiple
308 tests. This is done to optimise runtime and test load.
309 If something goes wrong with the test server, it can be rebuilt
310 using this helper.
311
312 This helper can also be used for the initial provisioning if no
313 server_id is specified.
314
315 :param server_id: UUID of the server to be rebuilt. If None is
316 specified, a new server is provisioned.
317 :param validatable: whether to the server needs to be
318 validatable. When True, validation resources are acquired via
319 the `get_class_validation_resources` helper.
320 :param kwargs: extra paramaters are passed through to the
321 `create_test_server` call.
322 :return: the UUID of the created server.
323 """
Matthew Treinish2cd19a42013-12-02 21:54:42 +0000324 if server_id:
zhufl9b682902016-12-15 09:16:34 +0800325 cls.delete_server(server_id)
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000326
Ghanshyam3390d9f2015-12-25 12:48:02 +0900327 cls.password = data_utils.rand_password()
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000328 server = cls.create_test_server(
329 validatable,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100330 validation_resources=cls.get_class_validation_resources(
331 cls.os_primary),
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000332 wait_until='ACTIVE',
Ghanshyam3390d9f2015-12-25 12:48:02 +0900333 adminPass=cls.password,
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000334 **kwargs)
Matthew Treinish2cd19a42013-12-02 21:54:42 +0000335 return server['id']
ivan-zhu8f992be2013-07-31 14:56:58 +0800336
Matt Riedemann5dc594c2014-01-27 11:40:28 -0800337 @classmethod
Jesse Keating613b4982015-05-04 15:05:19 -0700338 def delete_server(cls, server_id):
339 """Deletes an existing server and waits for it to be gone."""
340 try:
341 cls.servers_client.delete_server(server_id)
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000342 waiters.wait_for_server_termination(cls.servers_client,
343 server_id)
Jesse Keating613b4982015-05-04 15:05:19 -0700344 except Exception:
Jordan Pittier525ec712016-12-07 17:51:26 +0100345 LOG.exception('Failed to delete server %s', server_id)
Jesse Keating613b4982015-05-04 15:05:19 -0700346
347 @classmethod
zhufl3d018b02016-11-25 16:43:04 +0800348 def resize_server(cls, server_id, new_flavor_id, **kwargs):
349 """resize and confirm_resize an server, waits for it to be ACTIVE."""
350 cls.servers_client.resize_server(server_id, new_flavor_id, **kwargs)
351 waiters.wait_for_server_status(cls.servers_client, server_id,
352 'VERIFY_RESIZE')
353 cls.servers_client.confirm_resize_server(server_id)
354 waiters.wait_for_server_status(cls.servers_client, server_id, 'ACTIVE')
355
356 @classmethod
Matt Riedemann5dc594c2014-01-27 11:40:28 -0800357 def delete_volume(cls, volume_id):
358 """Deletes the given volume and waits for it to be gone."""
zhufldecdcf62017-09-13 10:27:28 +0800359 try:
360 cls.volumes_client.delete_volume(volume_id)
361 # TODO(mriedem): We should move the wait_for_resource_deletion
362 # into the delete_volume method as a convenience to the caller.
363 cls.volumes_client.wait_for_resource_deletion(volume_id)
364 except lib_exc.NotFound:
365 LOG.warning("Unable to delete volume '%s' since it was not found. "
366 "Maybe it was already deleted?", volume_id)
Ken'ichi Ohmichi543a5d42014-05-02 08:44:15 +0900367
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000368 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100369 def get_server_ip(cls, server, validation_resources=None):
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000370 """Get the server fixed or floating IP.
371
Sean Dague20e98612016-01-06 14:33:28 -0500372 Based on the configuration we're in, return a correct ip
373 address for validating that a guest is up.
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100374
375 :param server: The server dict as returned by the API
376 :param validation_resources: The dict of validation resources
377 provisioned for the server.
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000378 """
379 if CONF.validation.connect_method == 'floating':
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100380 if validation_resources:
381 return validation_resources['floating_ip']['ip']
382 else:
383 msg = ('When validation.connect_method equals floating, '
384 'validation_resources cannot be None')
385 raise exceptions.InvalidParam(invalid_param=msg)
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000386 elif CONF.validation.connect_method == 'fixed':
Sean Dague20e98612016-01-06 14:33:28 -0500387 addresses = server['addresses'][CONF.validation.network_for_ssh]
388 for address in addresses:
389 if address['version'] == CONF.validation.ip_version_for_ssh:
390 return address['addr']
zhufl955f82b2016-07-22 11:14:34 +0800391 raise exceptions.ServerUnreachable(server_id=server['id'])
Sean Dague20e98612016-01-06 14:33:28 -0500392 else:
guo yunxianffc4fc02016-11-15 09:56:08 +0800393 raise lib_exc.InvalidConfiguration()
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000394
Ghanshyam05049dd2016-02-12 17:44:48 +0900395 def setUp(self):
396 super(BaseV2ComputeTest, self).setUp()
397 self.useFixture(api_microversion_fixture.APIMicroversionFixture(
398 self.request_microversion))
399
Matt Riedemann342b37c2016-09-21 15:38:12 -0400400 @classmethod
zhufl8d23f922016-12-12 17:29:42 +0800401 def create_volume(cls, image_ref=None, **kwargs):
Matt Riedemann342b37c2016-09-21 15:38:12 -0400402 """Create a volume and wait for it to become 'available'.
403
Artom Lifshitzfc8f8e62016-04-13 11:08:32 +0000404 :param image_ref: Specify an image id to create a bootable volume.
zhufl8d23f922016-12-12 17:29:42 +0800405 :**kwargs: other parameters to create volume.
Matt Riedemann342b37c2016-09-21 15:38:12 -0400406 :returns: The available volume.
407 """
zhufl8d23f922016-12-12 17:29:42 +0800408 if 'size' not in kwargs:
409 kwargs['size'] = CONF.volume.volume_size
410 if 'display_name' not in kwargs:
411 vol_name = data_utils.rand_name(cls.__name__ + '-volume')
412 kwargs['display_name'] = vol_name
Artom Lifshitzfc8f8e62016-04-13 11:08:32 +0000413 if image_ref is not None:
zhufl8d23f922016-12-12 17:29:42 +0800414 kwargs['imageRef'] = image_ref
415 volume = cls.volumes_client.create_volume(**kwargs)['volume']
Andrea Frittoli1fc499e2017-08-29 18:33:03 +0100416 cls.addClassResourceCleanup(
417 cls.volumes_client.wait_for_resource_deletion, volume['id'])
418 cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
419 cls.volumes_client.delete_volume,
420 volume['id'])
lkuchlan52d7b0d2016-11-07 20:53:19 +0200421 waiters.wait_for_volume_resource_status(cls.volumes_client,
422 volume['id'], 'available')
Matt Riedemann342b37c2016-09-21 15:38:12 -0400423 return volume
424
John Griffith030dd172017-06-27 23:22:14 +0000425 def attach_volume(self, server, volume, device=None, check_reserved=False):
Matt Riedemanncb16a662016-10-01 18:30:05 -0400426 """Attaches volume to server and waits for 'in-use' volume status.
427
428 The volume will be detached when the test tears down.
429
430 :param server: The server to which the volume will be attached.
431 :param volume: The volume to attach.
432 :param device: Optional mountpoint for the attached volume. Note that
433 this is not guaranteed for all hypervisors and is not recommended.
John Griffith030dd172017-06-27 23:22:14 +0000434 :param check_reserved: Consider a status of reserved as valid for
435 completion. This is to handle new Cinder attach where we more
436 accurately use 'reserved' for things like attaching to a shelved
437 server.
Matt Riedemanncb16a662016-10-01 18:30:05 -0400438 """
439 attach_kwargs = dict(volumeId=volume['id'])
440 if device:
441 attach_kwargs['device'] = device
John Griffith030dd172017-06-27 23:22:14 +0000442
zhufl36f0a972017-02-28 15:43:33 +0800443 attachment = self.servers_client.attach_volume(
444 server['id'], **attach_kwargs)['volumeAttachment']
Matt Riedemann342b37c2016-09-21 15:38:12 -0400445 # On teardown detach the volume and wait for it to be available. This
446 # is so we don't error out when trying to delete the volume during
447 # teardown.
lkuchlan52d7b0d2016-11-07 20:53:19 +0200448 self.addCleanup(waiters.wait_for_volume_resource_status,
Matt Riedemann342b37c2016-09-21 15:38:12 -0400449 self.volumes_client, volume['id'], 'available')
450 # Ignore 404s on detach in case the server is deleted or the volume
451 # is already detached.
452 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
453 self.servers_client.detach_volume,
454 server['id'], volume['id'])
John Griffith030dd172017-06-27 23:22:14 +0000455 statuses = ['in-use']
456 if check_reserved:
457 statuses.append('reserved')
lkuchlan52d7b0d2016-11-07 20:53:19 +0200458 waiters.wait_for_volume_resource_status(self.volumes_client,
John Griffith030dd172017-06-27 23:22:14 +0000459 volume['id'], statuses)
zhufl36f0a972017-02-28 15:43:33 +0800460 return attachment
Matt Riedemann342b37c2016-09-21 15:38:12 -0400461
Ken'ichi Ohmichi543a5d42014-05-02 08:44:15 +0900462
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +0000463class BaseV2ComputeAdminTest(BaseV2ComputeTest):
Ken'ichi Ohmichibcefa3d2014-05-09 08:14:05 +0900464 """Base test case class for Compute Admin API tests."""
ivan-zhuf2b00502013-10-18 10:06:52 +0800465
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000466 credentials = ['primary', 'admin']
Emily Hugenbruche7991d92014-12-12 16:53:36 +0000467
468 @classmethod
469 def setup_clients(cls):
Ken'ichi Ohmichi02a8ccd2015-11-05 06:05:29 +0000470 super(BaseV2ComputeAdminTest, cls).setup_clients()
Ken'ichi Ohmichi9f5adf82014-12-12 04:01:32 +0000471 cls.availability_zone_admin_client = (
Jordan Pittier8160d312017-04-18 11:52:23 +0200472 cls.os_admin.availability_zone_client)
473 cls.admin_flavors_client = cls.os_admin.flavors_client
474 cls.admin_servers_client = cls.os_admin.servers_client
zhufl36eeab02017-01-18 11:49:04 +0800475
476 def create_flavor(self, ram, vcpus, disk, name=None,
477 is_public='True', **kwargs):
478 if name is None:
479 name = data_utils.rand_name(self.__class__.__name__ + "-flavor")
480 id = kwargs.pop('id', data_utils.rand_int_id(start=1000))
481 client = self.admin_flavors_client
482 flavor = client.create_flavor(
483 ram=ram, vcpus=vcpus, disk=disk, name=name,
484 id=id, is_public=is_public, **kwargs)['flavor']
485 self.addCleanup(client.wait_for_resource_deletion, flavor['id'])
486 self.addCleanup(client.delete_flavor, flavor['id'])
487 return flavor
Duc Truong09941202017-06-07 10:15:20 -0700488
489 def get_host_for_server(self, server_id):
490 server_details = self.admin_servers_client.show_server(server_id)
491 return server_details['server']['OS-EXT-SRV-ATTR:host']
492
493 def get_host_other_than(self, server_id):
494 source_host = self.get_host_for_server(server_id)
495
zhufl1dc2e232017-09-04 10:19:17 +0800496 hypers = self.os_admin.hypervisor_client.list_hypervisors(
497 )['hypervisors']
498 hosts = [hyper['hypervisor_hostname'] for hyper in hypers
499 if hyper['state'] == 'up' and hyper['status'] == 'enabled']
Duc Truong09941202017-06-07 10:15:20 -0700500
501 for target_host in hosts:
502 if source_host != target_host:
503 return target_host