blob: 02e1c9943795640841bc55277ff9d9ea37b80a20 [file] [log] [blame]
Matthew Treinish7b015822014-01-21 18:15:39 +00001# Copyright 2014 IBM Corp.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import time
16
17import mock
18
19from tempest.common import waiters
20from tempest import exceptions
guo yunxianebb15f22016-11-01 21:03:35 +080021from tempest.lib import exceptions as lib_exc
lkuchlanf53947e2016-09-15 10:37:57 +030022from tempest.lib.services.volume.v2 import volumes_client
Matthew Treinishffad78a2016-04-16 14:39:52 -040023from tempest.tests import base
Jordan Pittier0e53b612016-03-03 14:23:17 +010024import tempest.tests.utils as utils
Matthew Treinish7b015822014-01-21 18:15:39 +000025
26
27class TestImageWaiters(base.TestCase):
28 def setUp(self):
29 super(TestImageWaiters, self).setUp()
30 self.client = mock.MagicMock()
31 self.client.build_timeout = 1
32 self.client.build_interval = 1
33
34 def test_wait_for_image_status(self):
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +000035 self.client.show_image.return_value = ({'status': 'active'})
Matthew Treinish7b015822014-01-21 18:15:39 +000036 start_time = int(time.time())
37 waiters.wait_for_image_status(self.client, 'fake_image_id', 'active')
38 end_time = int(time.time())
39 # Ensure waiter returns before build_timeout
Béla Vancsics64862f72016-11-08 09:12:31 +010040 self.assertLess((end_time - start_time), 10)
Matthew Treinish7b015822014-01-21 18:15:39 +000041
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +030042 def test_wait_for_image_status_timeout(self):
Jordan Pittier0e53b612016-03-03 14:23:17 +010043 time_mock = self.patch('time.time')
44 time_mock.side_effect = utils.generate_timeout_series(1)
45
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +000046 self.client.show_image.return_value = ({'status': 'saving'})
guo yunxianebb15f22016-11-01 21:03:35 +080047 self.assertRaises(lib_exc.TimeoutException,
Matthew Treinish7b015822014-01-21 18:15:39 +000048 waiters.wait_for_image_status,
49 self.client, 'fake_image_id', 'active')
50
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +030051 def test_wait_for_image_status_error_on_image_create(self):
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +000052 self.client.show_image.return_value = ({'status': 'ERROR'})
Matthew Treinish7b015822014-01-21 18:15:39 +000053 self.assertRaises(exceptions.AddImageException,
54 waiters.wait_for_image_status,
55 self.client, 'fake_image_id', 'active')
Matt Riedemannf77e7dc2015-08-10 16:39:39 -070056
57 @mock.patch.object(time, 'sleep')
58 def test_wait_for_volume_status_error_restoring(self, mock_sleep):
59 # Tests that the wait method raises VolumeRestoreErrorException if
60 # the volume status is 'error_restoring'.
lkuchlanf53947e2016-09-15 10:37:57 +030061 client = mock.Mock(spec=volumes_client.VolumesClient,
xing-yang41ed7152017-05-03 06:52:56 -040062 resource_type="volume",
Matt Riedemannf77e7dc2015-08-10 16:39:39 -070063 build_interval=1)
John Warren6177c9e2015-08-19 20:00:17 +000064 volume1 = {'volume': {'status': 'restoring-backup'}}
65 volume2 = {'volume': {'status': 'error_restoring'}}
Matt Riedemannf77e7dc2015-08-10 16:39:39 -070066 mock_show = mock.Mock(side_effect=(volume1, volume2))
67 client.show_volume = mock_show
68 volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
69 self.assertRaises(exceptions.VolumeRestoreErrorException,
lkuchlan52d7b0d2016-11-07 20:53:19 +020070 waiters.wait_for_volume_resource_status,
Matt Riedemannf77e7dc2015-08-10 16:39:39 -070071 client, volume_id, 'available')
72 mock_show.assert_has_calls([mock.call(volume_id),
73 mock.call(volume_id)])
74 mock_sleep.assert_called_once_with(1)
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -040075
zhufl0ea2c012019-06-03 15:37:13 +080076 @mock.patch.object(time, 'sleep')
77 def test_wait_for_volume_status_error_extending(self, mock_sleep):
78 # Tests that the wait method raises VolumeExtendErrorException if
79 # the volume status is 'error_extending'.
80 client = mock.Mock(spec=volumes_client.VolumesClient,
81 resource_type="volume",
82 build_interval=1)
83 volume1 = {'volume': {'status': 'extending'}}
84 volume2 = {'volume': {'status': 'error_extending'}}
85 mock_show = mock.Mock(side_effect=(volume1, volume2))
86 client.show_volume = mock_show
87 volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
88 self.assertRaises(exceptions.VolumeExtendErrorException,
89 waiters.wait_for_volume_resource_status,
90 client, volume_id, 'available')
91 mock_show.assert_has_calls([mock.call(volume_id),
92 mock.call(volume_id)])
93 mock_sleep.assert_called_once_with(1)
94
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -040095
96class TestInterfaceWaiters(base.TestCase):
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -040097
Federico Ressi8827d382018-06-12 23:27:00 +020098 build_timeout = 1.
99 build_interval = 1
100 port_down = {'interfaceAttachment': {'port_state': 'DOWN'}}
101 port_active = {'interfaceAttachment': {'port_state': 'ACTIVE'}}
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400102
Federico Ressi8827d382018-06-12 23:27:00 +0200103 def mock_client(self, **kwargs):
104 return mock.MagicMock(
105 build_timeout=self.build_timeout,
106 build_interval=self.build_interval,
107 **kwargs)
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400108
109 def test_wait_for_interface_status(self):
Federico Ressi8827d382018-06-12 23:27:00 +0200110 show_interface = mock.Mock(
111 side_effect=[self.port_down, self.port_active])
112 client = self.mock_client(show_interface=show_interface)
113 self.patch('time.time', return_value=0.)
114 sleep = self.patch('time.sleep')
115
116 result = waiters.wait_for_interface_status(
117 client, 'server_id', 'port_id', 'ACTIVE')
118
119 self.assertIs(self.port_active['interfaceAttachment'], result)
120 show_interface.assert_has_calls([mock.call('server_id', 'port_id'),
121 mock.call('server_id', 'port_id')])
122 sleep.assert_called_once_with(client.build_interval)
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400123
124 def test_wait_for_interface_status_timeout(self):
Federico Ressi8827d382018-06-12 23:27:00 +0200125 show_interface = mock.MagicMock(return_value=self.port_down)
126 client = self.mock_client(show_interface=show_interface)
127 self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
128 sleep = self.patch('time.sleep')
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400129
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400130 self.assertRaises(lib_exc.TimeoutException,
131 waiters.wait_for_interface_status,
Federico Ressi8827d382018-06-12 23:27:00 +0200132 client, 'server_id', 'port_id', 'ACTIVE')
Artom Lifshitz3306d422018-03-22 12:20:54 -0400133
Federico Ressi8827d382018-06-12 23:27:00 +0200134 show_interface.assert_has_calls([mock.call('server_id', 'port_id'),
135 mock.call('server_id', 'port_id')])
136 sleep.assert_called_once_with(client.build_interval)
Artom Lifshitz3306d422018-03-22 12:20:54 -0400137
Federico Ressi8827d382018-06-12 23:27:00 +0200138 one_interface = {'interfaceAttachments': [{'port_id': 'port_one'}]}
139 two_interfaces = {'interfaceAttachments': [{'port_id': 'port_one'},
140 {'port_id': 'port_two'}]}
Artom Lifshitz3306d422018-03-22 12:20:54 -0400141
142 def test_wait_for_interface_detach(self):
Federico Ressi8827d382018-06-12 23:27:00 +0200143 list_interfaces = mock.MagicMock(
144 side_effect=[self.two_interfaces, self.one_interface])
145 client = self.mock_client(list_interfaces=list_interfaces)
146 self.patch('time.time', return_value=0.)
147 sleep = self.patch('time.sleep')
148
149 result = waiters.wait_for_interface_detach(
150 client, 'server_id', 'port_two')
151
152 self.assertIs(self.one_interface['interfaceAttachments'], result)
153 list_interfaces.assert_has_calls([mock.call('server_id'),
154 mock.call('server_id')])
155 sleep.assert_called_once_with(client.build_interval)
Artom Lifshitz3306d422018-03-22 12:20:54 -0400156
157 def test_wait_for_interface_detach_timeout(self):
Federico Ressi8827d382018-06-12 23:27:00 +0200158 list_interfaces = mock.MagicMock(return_value=self.one_interface)
159 client = self.mock_client(list_interfaces=list_interfaces)
160 self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
161 sleep = self.patch('time.sleep')
Artom Lifshitz3306d422018-03-22 12:20:54 -0400162
Artom Lifshitz3306d422018-03-22 12:20:54 -0400163 self.assertRaises(lib_exc.TimeoutException,
164 waiters.wait_for_interface_detach,
Federico Ressi8827d382018-06-12 23:27:00 +0200165 client, 'server_id', 'port_one')
166
167 list_interfaces.assert_has_calls([mock.call('server_id'),
168 mock.call('server_id')])
169 sleep.assert_called_once_with(client.build_interval)
Lee Yarwoode5597402019-02-15 20:17:00 +0000170
171
172class TestVolumeWaiters(base.TestCase):
173 vol_migrating_src_host = {
174 'volume': {'migration_status': 'migrating',
175 'os-vol-host-attr:host': 'src_host@backend#type'}}
176 vol_migrating_dst_host = {
177 'volume': {'migration_status': 'migrating',
178 'os-vol-host-attr:host': 'dst_host@backend#type'}}
179 vol_migration_success = {
180 'volume': {'migration_status': 'success',
181 'os-vol-host-attr:host': 'dst_host@backend#type'}}
182 vol_migration_error = {
183 'volume': {'migration_status': 'error',
184 'os-vol-host-attr:host': 'src_host@backend#type'}}
185
186 def test_wait_for_volume_migration_timeout(self):
187 show_volume = mock.MagicMock(return_value=self.vol_migrating_src_host)
188 client = mock.Mock(spec=volumes_client.VolumesClient,
189 resource_type="volume",
190 build_interval=1,
191 build_timeout=1,
192 show_volume=show_volume)
193 self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
194 self.patch('time.sleep')
195 self.assertRaises(lib_exc.TimeoutException,
196 waiters.wait_for_volume_migration,
197 client, mock.sentinel.volume_id, 'dst_host')
198
199 def test_wait_for_volume_migration_error(self):
200 show_volume = mock.MagicMock(side_effect=[
201 self.vol_migrating_src_host,
202 self.vol_migrating_src_host,
203 self.vol_migration_error])
204 client = mock.Mock(spec=volumes_client.VolumesClient,
205 resource_type="volume",
206 build_interval=1,
207 build_timeout=1,
208 show_volume=show_volume)
209 self.patch('time.time', return_value=0.)
210 self.patch('time.sleep')
211 self.assertRaises(lib_exc.TempestException,
212 waiters.wait_for_volume_migration,
213 client, mock.sentinel.volume_id, 'dst_host')
214
215 def test_wait_for_volume_migration_success_and_dst(self):
216 show_volume = mock.MagicMock(side_effect=[
217 self.vol_migrating_src_host,
218 self.vol_migrating_dst_host,
219 self.vol_migration_success])
220 client = mock.Mock(spec=volumes_client.VolumesClient,
221 resource_type="volume",
222 build_interval=1,
223 build_timeout=1,
224 show_volume=show_volume)
225 self.patch('time.time', return_value=0.)
226 self.patch('time.sleep')
227 waiters.wait_for_volume_migration(
228 client, mock.sentinel.volume_id, 'dst_host')
229
230 # Assert that we wait until migration_status is success and dst_host is
231 # part of the returned os-vol-host-attr:host.
232 show_volume.assert_has_calls([mock.call(mock.sentinel.volume_id),
233 mock.call(mock.sentinel.volume_id),
234 mock.call(mock.sentinel.volume_id)])