ZhiQiang Fan | 39f9722 | 2013-09-20 04:49:44 +0800 | [diff] [blame] | 1 | # Copyright 2012 OpenStack Foundation |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 2 | # 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 | |
Zhi Kun Liu | bb363a2 | 2013-11-28 18:47:39 +0800 | [diff] [blame] | 16 | from tempest.api.volume import base |
Andrea Frittoli | cd36841 | 2017-08-14 21:37:56 +0100 | [diff] [blame] | 17 | from tempest.common import utils |
Ken'ichi Ohmichi | 0eb153c | 2015-07-13 02:18:25 +0000 | [diff] [blame] | 18 | from tempest.common import waiters |
Matthew Treinish | 4d352bc | 2014-01-29 18:29:18 +0000 | [diff] [blame] | 19 | from tempest import config |
Ken'ichi Ohmichi | ef1c1ce | 2017-03-10 11:07:10 -0800 | [diff] [blame] | 20 | from tempest.lib.common.utils import data_utils |
Jordan Pittier | 9e227c5 | 2016-02-09 14:35:18 +0100 | [diff] [blame] | 21 | from tempest.lib.common.utils import test_utils |
Ken'ichi Ohmichi | 6b279c7 | 2017-01-27 18:26:59 -0800 | [diff] [blame] | 22 | from tempest.lib import decorators |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 23 | |
Matthew Treinish | 4d352bc | 2014-01-29 18:29:18 +0000 | [diff] [blame] | 24 | CONF = config.CONF |
| 25 | |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 26 | |
Ken'ichi Ohmichi | e8afb8c | 2017-03-27 11:25:37 -0700 | [diff] [blame] | 27 | class VolumesActionsTest(base.BaseVolumeTest): |
zhufl | a568237 | 2020-08-14 14:56:57 +0800 | [diff] [blame] | 28 | """Test volume actions""" |
| 29 | |
Ghanshyam Mann | 7d91b69 | 2020-03-03 10:21:50 -0600 | [diff] [blame] | 30 | create_default_network = True |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 31 | |
| 32 | @classmethod |
Rohan Kanade | 0574915 | 2015-01-30 17:15:18 +0530 | [diff] [blame] | 33 | def resource_setup(cls): |
Ken'ichi Ohmichi | e8afb8c | 2017-03-27 11:25:37 -0700 | [diff] [blame] | 34 | super(VolumesActionsTest, cls).resource_setup() |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 35 | |
Ken'ichi Ohmichi | 5687d55 | 2013-12-26 19:00:12 +0900 | [diff] [blame] | 36 | # Create a test shared volume for attach/detach tests |
| 37 | cls.volume = cls.create_volume() |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 38 | |
Ken'ichi Ohmichi | 6b279c7 | 2017-01-27 18:26:59 -0800 | [diff] [blame] | 39 | @decorators.idempotent_id('fff42874-7db5-4487-a8e1-ddda5fb5288d') |
Jordan Pittier | 3b46d27 | 2017-04-12 16:17:28 +0200 | [diff] [blame] | 40 | @decorators.attr(type='smoke') |
Andrea Frittoli | cd36841 | 2017-08-14 21:37:56 +0100 | [diff] [blame] | 41 | @utils.services('compute') |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 42 | def test_attach_detach_volume_to_instance(self): |
zhufl | a568237 | 2020-08-14 14:56:57 +0800 | [diff] [blame] | 43 | """Test attaching and detaching volume to instance""" |
lkuchlan | 5fc6936 | 2016-09-05 08:42:34 +0300 | [diff] [blame] | 44 | # Create a server |
lkuchlan | d4ecd0e | 2017-06-11 12:01:27 +0300 | [diff] [blame] | 45 | server = self.create_server() |
Sean Dague | 72a0038 | 2013-01-03 17:53:38 -0500 | [diff] [blame] | 46 | # Volume is attached and detached successfully from an instance |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 47 | self.volumes_client.attach_volume(self.volume['id'], |
| 48 | instance_uuid=server['id'], |
| 49 | mountpoint='/dev/%s' % |
| 50 | CONF.compute.volume_device_name) |
| 51 | waiters.wait_for_volume_resource_status(self.volumes_client, |
lkuchlan | 52d7b0d | 2016-11-07 20:53:19 +0200 | [diff] [blame] | 52 | self.volume['id'], 'in-use') |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 53 | self.volumes_client.detach_volume(self.volume['id']) |
| 54 | waiters.wait_for_volume_resource_status(self.volumes_client, |
lkuchlan | 52d7b0d | 2016-11-07 20:53:19 +0200 | [diff] [blame] | 55 | self.volume['id'], 'available') |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 56 | |
Ken'ichi Ohmichi | 6b279c7 | 2017-01-27 18:26:59 -0800 | [diff] [blame] | 57 | @decorators.idempotent_id('63e21b4c-0a0c-41f6-bfc3-7c2816815599') |
bkopilov | 8a657ae | 2015-05-11 11:45:23 +0300 | [diff] [blame] | 58 | def test_volume_bootable(self): |
zhufl | a568237 | 2020-08-14 14:56:57 +0800 | [diff] [blame] | 59 | """Test setting and retrieving bootable flag of a volume""" |
bkopilov | 8a657ae | 2015-05-11 11:45:23 +0300 | [diff] [blame] | 60 | for bool_bootable in [True, False]: |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 61 | self.volumes_client.set_bootable_volume(self.volume['id'], |
| 62 | bootable=bool_bootable) |
| 63 | fetched_volume = self.volumes_client.show_volume( |
John Warren | 6177c9e | 2015-08-19 20:00:17 +0000 | [diff] [blame] | 64 | self.volume['id'])['volume'] |
bkopilov | 8a657ae | 2015-05-11 11:45:23 +0300 | [diff] [blame] | 65 | # Get Volume information |
Masayuki Igawa | 5062746 | 2016-11-29 15:53:14 +0900 | [diff] [blame] | 66 | # NOTE(masayukig): 'bootable' is "true" or "false" in the current |
| 67 | # cinder implementation. So we need to cast boolean values to str |
| 68 | # and make it lower to compare here. |
| 69 | self.assertEqual(str(bool_bootable).lower(), |
| 70 | fetched_volume['bootable']) |
bkopilov | 8a657ae | 2015-05-11 11:45:23 +0300 | [diff] [blame] | 71 | |
Ken'ichi Ohmichi | 6b279c7 | 2017-01-27 18:26:59 -0800 | [diff] [blame] | 72 | @decorators.idempotent_id('9516a2c8-9135-488c-8dd6-5677a7e5f371') |
Andrea Frittoli | cd36841 | 2017-08-14 21:37:56 +0100 | [diff] [blame] | 73 | @utils.services('compute') |
Rohit Karajgi | a42fe44 | 2012-09-21 03:08:33 -0700 | [diff] [blame] | 74 | def test_get_volume_attachment(self): |
zhufl | a568237 | 2020-08-14 14:56:57 +0800 | [diff] [blame] | 75 | """Test getting volume attachments |
| 76 | |
| 77 | Attach a volume to a server, and then retrieve volume's attachments |
| 78 | info. |
| 79 | """ |
lkuchlan | 5fc6936 | 2016-09-05 08:42:34 +0300 | [diff] [blame] | 80 | # Create a server |
lkuchlan | d4ecd0e | 2017-06-11 12:01:27 +0300 | [diff] [blame] | 81 | server = self.create_server() |
Sean Dague | 72a0038 | 2013-01-03 17:53:38 -0500 | [diff] [blame] | 82 | # Verify that a volume's attachment information is retrieved |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 83 | self.volumes_client.attach_volume(self.volume['id'], |
| 84 | instance_uuid=server['id'], |
| 85 | mountpoint='/dev/%s' % |
| 86 | CONF.compute.volume_device_name) |
| 87 | waiters.wait_for_volume_resource_status(self.volumes_client, |
| 88 | self.volume['id'], |
lkuchlan | 52d7b0d | 2016-11-07 20:53:19 +0200 | [diff] [blame] | 89 | 'in-use') |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 90 | self.addCleanup(waiters.wait_for_volume_resource_status, |
| 91 | self.volumes_client, |
lkuchlan | 52d7b0d | 2016-11-07 20:53:19 +0200 | [diff] [blame] | 92 | self.volume['id'], 'available') |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 93 | self.addCleanup(self.volumes_client.detach_volume, self.volume['id']) |
| 94 | volume = self.volumes_client.show_volume(self.volume['id'])['volume'] |
Ken'ichi Ohmichi | 84a5f96 | 2016-08-26 15:34:26 -0700 | [diff] [blame] | 95 | attachment = volume['attachments'][0] |
| 96 | |
bkopilov | bc830d0 | 2016-03-27 14:09:47 +0300 | [diff] [blame] | 97 | self.assertEqual('/dev/%s' % |
| 98 | CONF.compute.volume_device_name, |
| 99 | attachment['device']) |
lkuchlan | 5fc6936 | 2016-09-05 08:42:34 +0300 | [diff] [blame] | 100 | self.assertEqual(server['id'], attachment['server_id']) |
Giulio Fidente | 92f7719 | 2013-08-26 17:13:28 +0200 | [diff] [blame] | 101 | self.assertEqual(self.volume['id'], attachment['id']) |
| 102 | self.assertEqual(self.volume['id'], attachment['volume_id']) |
Giulio Fidente | 884e9da | 2013-06-21 17:25:42 +0200 | [diff] [blame] | 103 | |
Ken'ichi Ohmichi | 6b279c7 | 2017-01-27 18:26:59 -0800 | [diff] [blame] | 104 | @decorators.idempotent_id('d8f1ca95-3d5b-44a3-b8ca-909691c9532d') |
Andrea Frittoli | cd36841 | 2017-08-14 21:37:56 +0100 | [diff] [blame] | 105 | @utils.services('image') |
Giulio Fidente | 884e9da | 2013-06-21 17:25:42 +0200 | [diff] [blame] | 106 | def test_volume_upload(self): |
zhufl | a568237 | 2020-08-14 14:56:57 +0800 | [diff] [blame] | 107 | """Test uploading volume to create an image""" |
Giulio Fidente | 884e9da | 2013-06-21 17:25:42 +0200 | [diff] [blame] | 108 | # NOTE(gfidente): the volume uploaded in Glance comes from setUpClass, |
| 109 | # it is shared with the other tests. After it is uploaded in Glance, |
| 110 | # there is no way to delete it from Cinder, so we delete it from Glance |
lkuchlan | 153df15 | 2017-04-25 16:43:47 +0300 | [diff] [blame] | 111 | # using the Glance images_client and from Cinder via tearDownClass. |
zhufl | c6ce539 | 2016-08-17 14:34:37 +0800 | [diff] [blame] | 112 | image_name = data_utils.rand_name(self.__class__.__name__ + '-Image') |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 113 | body = self.volumes_client.upload_volume( |
Ghanshyam | 8fc0ed2 | 2015-12-18 10:25:14 +0900 | [diff] [blame] | 114 | self.volume['id'], image_name=image_name, |
| 115 | disk_format=CONF.volume.disk_format)['os-volume_upload_image'] |
Giulio Fidente | 884e9da | 2013-06-21 17:25:42 +0200 | [diff] [blame] | 116 | image_id = body["image_id"] |
Jordan Pittier | 9e227c5 | 2016-02-09 14:35:18 +0100 | [diff] [blame] | 117 | self.addCleanup(test_utils.call_and_ignore_notfound_exc, |
jeremy.zhang | cb0dd58 | 2017-04-25 08:48:38 +0800 | [diff] [blame] | 118 | self.images_client.delete_image, |
Jordan Pittier | 9e227c5 | 2016-02-09 14:35:18 +0100 | [diff] [blame] | 119 | image_id) |
jeremy.zhang | cb0dd58 | 2017-04-25 08:48:38 +0800 | [diff] [blame] | 120 | waiters.wait_for_image_status(self.images_client, image_id, 'active') |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 121 | waiters.wait_for_volume_resource_status(self.volumes_client, |
lkuchlan | 52d7b0d | 2016-11-07 20:53:19 +0200 | [diff] [blame] | 122 | self.volume['id'], 'available') |
anju tiwari | 789449a | 2013-08-29 16:56:17 +0530 | [diff] [blame] | 123 | |
lkuchlan | c1ebf65 | 2017-04-03 12:15:28 +0300 | [diff] [blame] | 124 | image_info = self.images_client.show_image(image_id) |
| 125 | self.assertEqual(image_name, image_info['name']) |
| 126 | self.assertEqual(CONF.volume.disk_format, image_info['disk_format']) |
| 127 | |
Ken'ichi Ohmichi | 6b279c7 | 2017-01-27 18:26:59 -0800 | [diff] [blame] | 128 | @decorators.idempotent_id('92c4ef64-51b2-40c0-9f7e-4749fbaaba33') |
zhangyanzi | 6b63243 | 2013-10-24 19:08:50 +0800 | [diff] [blame] | 129 | def test_reserve_unreserve_volume(self): |
zhufl | a568237 | 2020-08-14 14:56:57 +0800 | [diff] [blame] | 130 | """Test reserving and unreserving volume""" |
zhangyanzi | 6b63243 | 2013-10-24 19:08:50 +0800 | [diff] [blame] | 131 | # Mark volume as reserved. |
jeremy.zhang | e280f66 | 2017-06-30 17:38:58 +0800 | [diff] [blame] | 132 | self.volumes_client.reserve_volume(self.volume['id']) |
zhangyanzi | 6b63243 | 2013-10-24 19:08:50 +0800 | [diff] [blame] | 133 | # To get the volume info |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 134 | body = self.volumes_client.show_volume(self.volume['id'])['volume'] |
zhangyanzi | 6b63243 | 2013-10-24 19:08:50 +0800 | [diff] [blame] | 135 | self.assertIn('attaching', body['status']) |
| 136 | # Unmark volume as reserved. |
jeremy.zhang | e280f66 | 2017-06-30 17:38:58 +0800 | [diff] [blame] | 137 | self.volumes_client.unreserve_volume(self.volume['id']) |
zhangyanzi | 6b63243 | 2013-10-24 19:08:50 +0800 | [diff] [blame] | 138 | # To get the volume info |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 139 | body = self.volumes_client.show_volume(self.volume['id'])['volume'] |
zhangyanzi | 6b63243 | 2013-10-24 19:08:50 +0800 | [diff] [blame] | 140 | self.assertIn('available', body['status']) |
| 141 | |
Ken'ichi Ohmichi | 6b279c7 | 2017-01-27 18:26:59 -0800 | [diff] [blame] | 142 | @decorators.idempotent_id('fff74e1e-5bd3-4b33-9ea9-24c103bc3f59') |
zhangyanzi | aa18007 | 2013-11-21 12:31:26 +0800 | [diff] [blame] | 143 | def test_volume_readonly_update(self): |
zhufl | a568237 | 2020-08-14 14:56:57 +0800 | [diff] [blame] | 144 | """Test updating and retrieve volume's readonly flag""" |
zhufl | f9b4694 | 2016-10-09 11:23:46 +0800 | [diff] [blame] | 145 | for readonly in [True, False]: |
| 146 | # Update volume readonly |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 147 | self.volumes_client.update_volume_readonly(self.volume['id'], |
| 148 | readonly=readonly) |
zhufl | f9b4694 | 2016-10-09 11:23:46 +0800 | [diff] [blame] | 149 | # Get Volume information |
lkuchlan | 76d80b5 | 2017-04-03 12:29:57 +0300 | [diff] [blame] | 150 | fetched_volume = self.volumes_client.show_volume( |
zhufl | f9b4694 | 2016-10-09 11:23:46 +0800 | [diff] [blame] | 151 | self.volume['id'])['volume'] |
Masayuki Igawa | 5062746 | 2016-11-29 15:53:14 +0900 | [diff] [blame] | 152 | # NOTE(masayukig): 'readonly' is "True" or "False" in the current |
| 153 | # cinder implementation. So we need to cast boolean values to str |
| 154 | # to compare here. |
| 155 | self.assertEqual(str(readonly), |
| 156 | fetched_volume['metadata']['readonly']) |