blob: fa465af64cafeecf3e1e4b18feca0dfb66f8d77e [file] [log] [blame]
Matt Riedemannbc8dbd32013-08-02 14:02:12 -07001# Copyright 2013 IBM Corp.
Dan Smithc18d8c62012-07-02 08:09:26 -07002# 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
Anusha Raminenif3eb9472017-01-13 08:54:01 +053016from oslo_log import log as logging
ivan-zhu1feeb382013-01-24 10:14:39 +080017import testtools
Dan Smithc18d8c62012-07-02 08:09:26 -070018
Sean Dague1937d092013-05-17 16:36:38 -040019from tempest.api.compute import base
lanoux2746ba02016-03-16 17:41:01 +090020from tempest.common import compute
Masayuki Igawa209fd502014-02-17 14:46:43 +090021from tempest.common.utils.linux import remote_client
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +000022from tempest.common import waiters
Sean Dague86bd8422013-12-20 09:56:44 -050023from tempest import config
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030024from tempest.lib import exceptions as lib_exc
Masayuki Igawa209fd502014-02-17 14:46:43 +090025from tempest import test
Dan Smithc18d8c62012-07-02 08:09:26 -070026
Sean Dague86bd8422013-12-20 09:56:44 -050027CONF = config.CONF
28
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030029LOG = logging.getLogger(__name__)
30
Dan Smithc18d8c62012-07-02 08:09:26 -070031
ivan-zhuf2b00502013-10-18 10:06:52 +080032class AttachVolumeTestJSON(base.BaseV2ComputeTest):
lanoux2746ba02016-03-16 17:41:01 +090033 max_microversion = '2.19'
Dan Smithc18d8c62012-07-02 08:09:26 -070034
Attila Fazekas19044d52013-02-16 07:35:06 +010035 @classmethod
Emily Hugenbruch8284a342014-12-11 22:04:55 +000036 def skip_checks(cls):
37 super(AttachVolumeTestJSON, cls).skip_checks()
Matthew Treinishb0a78fc2014-01-29 16:49:12 +000038 if not CONF.service_available.cinder:
Matthew Treinish4c412922013-07-16 15:27:42 -040039 skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
40 raise cls.skipException(skip_msg)
Dan Smithc18d8c62012-07-02 08:09:26 -070041
Emily Hugenbruch8284a342014-12-11 22:04:55 +000042 @classmethod
43 def setup_credentials(cls):
44 cls.prepare_instance_network()
45 super(AttachVolumeTestJSON, cls).setup_credentials()
46
47 @classmethod
48 def resource_setup(cls):
Joseph Lanouxffe09dd2015-03-18 16:45:33 +000049 cls.set_validation_resources()
Emily Hugenbruch8284a342014-12-11 22:04:55 +000050 super(AttachVolumeTestJSON, cls).resource_setup()
51 cls.device = CONF.compute.volume_device_name
52
Fabian Zimmermannbbef2762016-06-23 14:05:33 +020053 def _create_server(self):
Dan Smithc18d8c62012-07-02 08:09:26 -070054 # Start a server and wait for it to become ready
Fabian Zimmermannbbef2762016-06-23 14:05:33 +020055 server = self.create_test_server(
Joseph Lanouxffe09dd2015-03-18 16:45:33 +000056 validatable=True,
57 wait_until='ACTIVE',
Fabian Zimmermannbbef2762016-06-23 14:05:33 +020058 adminPass=self.image_ssh_password)
Dan Smithc18d8c62012-07-02 08:09:26 -070059 # Record addresses so that we can ssh later
Fabian Zimmermannbbef2762016-06-23 14:05:33 +020060 server['addresses'] = self.servers_client.list_addresses(
61 server['id'])['addresses']
62 return server
Dan Smithc18d8c62012-07-02 08:09:26 -070063
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030064 def _detach_volume(self, server_id, volume_id):
65 try:
66 self.servers_client.detach_volume(server_id, volume_id)
67 waiters.wait_for_volume_status(self.volumes_client,
68 volume_id, 'available')
69 except lib_exc.NotFound:
70 LOG.warning("Unable to detach volume %s from server %s "
Jordan Pittier525ec712016-12-07 17:51:26 +010071 "possibly it was already detached", volume_id,
72 server_id)
Dan Smithc18d8c62012-07-02 08:09:26 -070073
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030074 def _attach_volume(self, server_id, volume_id, device=None):
Dan Smithc18d8c62012-07-02 08:09:26 -070075 # Attach the volume to the server
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030076 kwargs = {'volumeId': volume_id}
Ken'ichi Ohmichi2b74f102016-11-22 17:18:36 -080077 if device:
78 kwargs.update({'device': '/dev/%s' % device})
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030079 attachment = self.servers_client.attach_volume(
80 server_id, **kwargs)['volumeAttachment']
Yaroslav Lobankoved3a35b2016-03-24 22:41:30 -050081 waiters.wait_for_volume_status(self.volumes_client,
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030082 volume_id, 'in-use')
83 self.addCleanup(self._detach_volume, server_id,
84 volume_id)
Dan Smithc18d8c62012-07-02 08:09:26 -070085
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030086 return attachment
Dan Smithc18d8c62012-07-02 08:09:26 -070087
Chris Hoge7579c1a2015-02-26 14:12:15 -080088 @test.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
Dan Smithc18d8c62012-07-02 08:09:26 -070089 def test_attach_detach_volume(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050090 # Stop and Start a server with an attached volume, ensuring that
91 # the volume remains attached.
Fabian Zimmermannbbef2762016-06-23 14:05:33 +020092 server = self._create_server()
Benny Kopilov5c5f7d82016-09-13 14:19:53 +030093 volume = self.create_volume()
94 attachment = self._attach_volume(server['id'], volume['id'],
95 device=self.device)
ivan-zhu2f54b282013-03-11 16:39:25 +080096
Fabian Zimmermannbbef2762016-06-23 14:05:33 +020097 self.servers_client.stop_server(server['id'])
98 waiters.wait_for_server_status(self.servers_client, server['id'],
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +000099 'SHUTOFF')
Dan Smithc18d8c62012-07-02 08:09:26 -0700100
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200101 self.servers_client.start_server(server['id'])
102 waiters.wait_for_server_status(self.servers_client, server['id'],
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000103 'ACTIVE')
Dan Smithc18d8c62012-07-02 08:09:26 -0700104
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100105 if CONF.validation.run_validation:
106 linux_client = remote_client.RemoteClient(
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200107 self.get_server_ip(server),
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100108 self.image_ssh_user,
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200109 self.image_ssh_password,
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100110 self.validation_resources['keypair']['private_key'],
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200111 server=server,
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100112 servers_client=self.servers_client)
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000113
Evgeny Antyshev4894a912016-11-21 12:17:18 +0000114 disks = linux_client.get_disks()
115 device_name_to_match = '\n' + self.device + ' '
116 self.assertIn(device_name_to_match, disks)
Dan Smithc18d8c62012-07-02 08:09:26 -0700117
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300118 self._detach_volume(server['id'], attachment['volumeId'])
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200119 self.servers_client.stop_server(server['id'])
120 waiters.wait_for_server_status(self.servers_client, server['id'],
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000121 'SHUTOFF')
Dan Smithc18d8c62012-07-02 08:09:26 -0700122
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200123 self.servers_client.start_server(server['id'])
124 waiters.wait_for_server_status(self.servers_client, server['id'],
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000125 'ACTIVE')
Dan Smithc18d8c62012-07-02 08:09:26 -0700126
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100127 if CONF.validation.run_validation:
128 linux_client = remote_client.RemoteClient(
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200129 self.get_server_ip(server),
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100130 self.image_ssh_user,
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200131 self.image_ssh_password,
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100132 self.validation_resources['keypair']['private_key'],
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200133 server=server,
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100134 servers_client=self.servers_client)
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000135
Evgeny Antyshev4894a912016-11-21 12:17:18 +0000136 disks = linux_client.get_disks()
137 self.assertNotIn(device_name_to_match, disks)
Dan Smith1ced8422012-08-16 10:35:19 -0700138
Chris Hoge7579c1a2015-02-26 14:12:15 -0800139 @test.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
Ghanshyam5c2a5582014-04-14 17:16:57 +0900140 def test_list_get_volume_attachments(self):
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300141 # List volume attachment of the server
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200142 server = self._create_server()
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300143 volume = self.create_volume()
144 attachment = self._attach_volume(server['id'], volume['id'],
145 device=self.device)
David Kranz3ebc7212015-02-10 12:19:19 -0500146 body = self.servers_client.list_volume_attachments(
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200147 server['id'])['volumeAttachments']
Ghanshyam5c2a5582014-04-14 17:16:57 +0900148 self.assertEqual(1, len(body))
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300149 self.assertIn(attachment, body)
Ghanshyam5c2a5582014-04-14 17:16:57 +0900150
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300151 # Get volume attachment of the server
Ken'ichi Ohmichi277d1882015-11-20 00:44:06 +0000152 body = self.servers_client.show_volume_attachment(
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200153 server['id'],
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300154 attachment['id'])['volumeAttachment']
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200155 self.assertEqual(server['id'], body['serverId'])
Anna Babich506efe22016-09-08 18:14:22 +0300156 self.assertEqual(volume['id'], body['volumeId'])
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300157 self.assertEqual(attachment['id'], body['id'])
lanoux2746ba02016-03-16 17:41:01 +0900158
Ken'ichi Ohmichi09139282016-12-01 14:36:22 -0800159 @test.idempotent_id('757d488b-a951-4bc7-b3cd-f417028da08a')
160 def test_list_get_two_volume_attachments(self):
161 # NOTE: This test is using the volume device auto-assignment
162 # without specifying the device ("/dev/sdb", etc). The feature
163 # is supported since Nova Liberty release or later. So this should
164 # be skipped on older clouds.
165 server = self._create_server()
166 volume_1st = self.create_volume()
167 volume_2nd = self.create_volume()
168 attachment_1st = self._attach_volume(server['id'], volume_1st['id'])
169 attachment_2nd = self._attach_volume(server['id'], volume_2nd['id'])
170
171 body = self.servers_client.list_volume_attachments(
172 server['id'])['volumeAttachments']
173 self.assertEqual(2, len(body))
174
175 body = self.servers_client.show_volume_attachment(
176 server['id'],
177 attachment_1st['id'])['volumeAttachment']
178 self.assertEqual(server['id'], body['serverId'])
179 self.assertEqual(attachment_1st['volumeId'], body['volumeId'])
180 self.assertEqual(attachment_1st['id'], body['id'])
181
182 body = self.servers_client.show_volume_attachment(
183 server['id'],
184 attachment_2nd['id'])['volumeAttachment']
185 self.assertEqual(server['id'], body['serverId'])
186 self.assertEqual(attachment_2nd['volumeId'], body['volumeId'])
187 self.assertEqual(attachment_2nd['id'], body['id'])
188
lanoux2746ba02016-03-16 17:41:01 +0900189
190class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
191 """Testing volume with shelved instance.
192
193 This test checks the attaching and detaching volumes from
Tianbiao Qi0d1d24e2016-09-28 14:17:12 +0800194 a shelved or shelved offload instance.
lanoux2746ba02016-03-16 17:41:01 +0900195 """
196
197 min_microversion = '2.20'
198 max_microversion = 'latest'
199
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200200 def _count_volumes(self, server):
201 # Count number of volumes on an instance
202 volumes = 0
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100203 if CONF.validation.run_validation:
204 linux_client = remote_client.RemoteClient(
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200205 self.get_server_ip(server),
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100206 self.image_ssh_user,
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200207 self.image_ssh_password,
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100208 self.validation_resources['keypair']['private_key'],
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200209 server=server,
Andrea Frittoli (andreaf)3f5aa982016-07-08 12:10:36 +0100210 servers_client=self.servers_client)
lanoux2746ba02016-03-16 17:41:01 +0900211
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200212 command = 'grep -c -E [vs]d.$ /proc/partitions'
213 volumes = int(linux_client.exec_command(command).strip())
214 return volumes
215
216 def _shelve_server(self, server):
217 # NOTE(andreaf) If we are going to shelve a server, we should
218 # check first whether the server is ssh-able. Otherwise we
219 # won't be able to distinguish failures introduced by shelve
220 # from pre-existing ones. Also it's good to wait for cloud-init
221 # to be done and sshd server to be running before shelving to
222 # avoid breaking the VM
223 if CONF.validation.run_validation:
224 linux_client = remote_client.RemoteClient(
225 self.get_server_ip(server),
226 self.image_ssh_user,
227 self.image_ssh_password,
228 self.validation_resources['keypair']['private_key'],
229 server=server,
230 servers_client=self.servers_client)
231 linux_client.validate_authentication()
232
233 # If validation went ok, or it was skipped, shelve the server
234 compute.shelve_server(self.servers_client, server['id'])
235
236 def _unshelve_server_and_check_volumes(self, server, number_of_volumes):
237 # Unshelve the instance and check that there are expected volumes
238 self.servers_client.unshelve_server(server['id'])
239 waiters.wait_for_server_status(self.servers_client,
240 server['id'],
241 'ACTIVE')
242 if CONF.validation.run_validation:
243 counted_volumes = self._count_volumes(server)
244 self.assertEqual(number_of_volumes, counted_volumes)
lanoux2746ba02016-03-16 17:41:01 +0900245
246 @test.idempotent_id('13a940b6-3474-4c3c-b03f-29b89112bfee')
247 @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
248 'Shelve is not available.')
lanoux2746ba02016-03-16 17:41:01 +0900249 def test_attach_volume_shelved_or_offload_server(self):
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200250 # Create server, count number of volumes on it, shelve
251 # server and attach pre-created volume to shelved server
252 server = self._create_server()
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300253 volume = self.create_volume()
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200254 num_vol = self._count_volumes(server)
255 self._shelve_server(server)
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300256 attachment = self._attach_volume(server['id'], volume['id'],
257 device=self.device)
lanoux2746ba02016-03-16 17:41:01 +0900258
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200259 # Unshelve the instance and check that attached volume exists
260 self._unshelve_server_and_check_volumes(server, num_vol + 1)
lanoux2746ba02016-03-16 17:41:01 +0900261
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300262 # Get volume attachment of the server
lanoux2746ba02016-03-16 17:41:01 +0900263 volume_attachment = self.servers_client.show_volume_attachment(
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200264 server['id'],
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300265 attachment['id'])['volumeAttachment']
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200266 self.assertEqual(server['id'], volume_attachment['serverId'])
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300267 self.assertEqual(attachment['id'], volume_attachment['id'])
lanoux2746ba02016-03-16 17:41:01 +0900268 # Check the mountpoint is not None after unshelve server even in
269 # case of shelved_offloaded.
270 self.assertIsNotNone(volume_attachment['device'])
271
272 @test.idempotent_id('b54e86dd-a070-49c4-9c07-59ae6dae15aa')
273 @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
274 'Shelve is not available.')
lanoux2746ba02016-03-16 17:41:01 +0900275 def test_detach_volume_shelved_or_offload_server(self):
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300276 # Count number of volumes on instance, shelve
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200277 # server and attach pre-created volume to shelved server
278 server = self._create_server()
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300279 volume = self.create_volume()
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200280 num_vol = self._count_volumes(server)
281 self._shelve_server(server)
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300282 self._attach_volume(server['id'], volume['id'], device=self.device)
lanoux2746ba02016-03-16 17:41:01 +0900283 # Detach the volume
Benny Kopilov5c5f7d82016-09-13 14:19:53 +0300284 self._detach_volume(server['id'], volume['id'])
lanoux2746ba02016-03-16 17:41:01 +0900285
Fabian Zimmermannbbef2762016-06-23 14:05:33 +0200286 # Unshelve the instance and check that we have the expected number of
287 # volume(s)
288 self._unshelve_server_and_check_volumes(server, num_vol)