blob: d715a422544653c9a6dceeac24bb2ddbda23cc27 [file] [log] [blame]
Matt Riedemann342b37c2016-09-21 15:38:12 -04001# 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
jeremy.zhangc9d58002017-03-22 11:03:54 +080013import time
14
Matt Riedemann342b37c2016-09-21 15:38:12 -040015from tempest.api.compute import base
Andrea Frittolicd368412017-08-14 21:37:56 +010016from tempest.common import utils
Matt Riedemann342b37c2016-09-21 15:38:12 -040017from tempest.common import waiters
18from tempest import config
Ken'ichi Ohmichiebbfd1c2017-01-27 16:37:00 -080019from tempest.lib import decorators
jeremy.zhangc9d58002017-03-22 11:03:54 +080020from tempest.lib import exceptions as lib_exc
Matt Riedemann342b37c2016-09-21 15:38:12 -040021
22CONF = config.CONF
23
24
25class TestVolumeSwap(base.BaseV2ComputeAdminTest):
26 """The test suite for swapping of volume with admin user.
27
28 The following is the scenario outline:
29 1. Create a volume "volume1" with non-admin.
30 2. Create a volume "volume2" with non-admin.
31 3. Boot an instance "instance1" with non-admin.
32 4. Attach "volume1" to "instance1" with non-admin.
33 5. Swap volume from "volume1" to "volume2" as admin.
34 6. Check the swap volume is successful and "volume2"
35 is attached to "instance1" and "volume1" is in available state.
Lee Yarwood89a6cfc2017-02-01 16:01:14 +000036 7. Swap volume from "volume2" to "volume1" as admin.
37 8. Check the swap volume is successful and "volume1"
38 is attached to "instance1" and "volume2" is in available state.
Matt Riedemann342b37c2016-09-21 15:38:12 -040039 """
40
41 @classmethod
42 def skip_checks(cls):
43 super(TestVolumeSwap, cls).skip_checks()
44 if not CONF.compute_feature_enabled.swap_volume:
45 raise cls.skipException("Swapping volumes is not supported.")
46
jeremy.zhangc9d58002017-03-22 11:03:54 +080047 def _wait_for_server_volume_swap(self, server_id, old_volume_id,
48 new_volume_id):
49 """Waits for a server to swap the old volume to a new one."""
50 volume_attachments = self.servers_client.list_volume_attachments(
51 server_id)['volumeAttachments']
52 attached_volume_ids = [attachment['volumeId']
53 for attachment in volume_attachments]
54 start = int(time.time())
55
56 while (old_volume_id in attached_volume_ids) \
57 or (new_volume_id not in attached_volume_ids):
58 time.sleep(self.servers_client.build_interval)
59 volume_attachments = self.servers_client.list_volume_attachments(
60 server_id)['volumeAttachments']
61 attached_volume_ids = [attachment['volumeId']
62 for attachment in volume_attachments]
63
64 if int(time.time()) - start >= self.servers_client.build_timeout:
65 old_vol_bdm_status = 'in BDM' \
66 if old_volume_id in attached_volume_ids else 'not in BDM'
67 new_vol_bdm_status = 'in BDM' \
68 if new_volume_id in attached_volume_ids else 'not in BDM'
69 message = ('Failed to swap old volume %(old_volume_id)s '
70 '(current %(old_vol_bdm_status)s) to new volume '
71 '%(new_volume_id)s (current %(new_vol_bdm_status)s)'
72 ' on server %(server_id)s within the required time '
73 '(%(timeout)s s)' %
74 {'old_volume_id': old_volume_id,
75 'old_vol_bdm_status': old_vol_bdm_status,
76 'new_volume_id': new_volume_id,
77 'new_vol_bdm_status': new_vol_bdm_status,
78 'server_id': server_id,
79 'timeout': self.servers_client.build_timeout})
80 raise lib_exc.TimeoutException(message)
81
Ken'ichi Ohmichiebbfd1c2017-01-27 16:37:00 -080082 @decorators.idempotent_id('1769f00d-a693-4d67-a631-6a3496773813')
Andrea Frittolicd368412017-08-14 21:37:56 +010083 @utils.services('volume')
Matt Riedemann342b37c2016-09-21 15:38:12 -040084 def test_volume_swap(self):
85 # Create two volumes.
86 # NOTE(gmann): Volumes are created before server creation so that
87 # volumes cleanup can happen successfully irrespective of which volume
88 # is attached to server.
89 volume1 = self.create_volume()
90 volume2 = self.create_volume()
91 # Boot server
92 server = self.create_test_server(wait_until='ACTIVE')
93 # Attach "volume1" to server
94 self.attach_volume(server, volume1)
95 # Swap volume from "volume1" to "volume2"
zhufle5b62a62017-02-15 16:04:21 +080096 self.admin_servers_client.update_attached_volume(
Matt Riedemann342b37c2016-09-21 15:38:12 -040097 server['id'], volume1['id'], volumeId=volume2['id'])
lkuchlan52d7b0d2016-11-07 20:53:19 +020098 waiters.wait_for_volume_resource_status(self.volumes_client,
99 volume1['id'], 'available')
100 waiters.wait_for_volume_resource_status(self.volumes_client,
101 volume2['id'], 'in-use')
jeremy.zhangc9d58002017-03-22 11:03:54 +0800102 self._wait_for_server_volume_swap(server['id'], volume1['id'],
103 volume2['id'])
Matt Riedemann342b37c2016-09-21 15:38:12 -0400104 # Verify "volume2" is attached to the server
105 vol_attachments = self.servers_client.list_volume_attachments(
106 server['id'])['volumeAttachments']
107 self.assertEqual(1, len(vol_attachments))
108 self.assertIn(volume2['id'], vol_attachments[0]['volumeId'])
109
Lee Yarwood89a6cfc2017-02-01 16:01:14 +0000110 # Swap volume from "volume2" to "volume1"
111 self.admin_servers_client.update_attached_volume(
112 server['id'], volume2['id'], volumeId=volume1['id'])
113 waiters.wait_for_volume_resource_status(self.volumes_client,
114 volume2['id'], 'available')
115 waiters.wait_for_volume_resource_status(self.volumes_client,
116 volume1['id'], 'in-use')
jeremy.zhangc9d58002017-03-22 11:03:54 +0800117 self._wait_for_server_volume_swap(server['id'], volume2['id'],
118 volume1['id'])
Lee Yarwood89a6cfc2017-02-01 16:01:14 +0000119 # Verify "volume1" is attached to the server
120 vol_attachments = self.servers_client.list_volume_attachments(
121 server['id'])['volumeAttachments']
122 self.assertEqual(1, len(vol_attachments))
123 self.assertIn(volume1['id'], vol_attachments[0]['volumeId'])