blob: 93c949e64d1d7221f7495a52abb35bd7095f054a [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
Sean McGinniseed80742020-04-18 12:01:03 -050016from unittest import mock
Matthew Treinish7b015822014-01-21 18:15:39 +000017
Lee Yarwoodc1b2a4a2020-01-08 17:02:49 +000018from oslo_utils.fixture import uuidsentinel as uuids
Matthew Treinish7b015822014-01-21 18:15:39 +000019
20from tempest.common import waiters
21from tempest import exceptions
guo yunxianebb15f22016-11-01 21:03:35 +080022from tempest.lib import exceptions as lib_exc
Balazs Gibizer2e515fe2020-12-07 15:10:11 +010023from tempest.lib.services.compute import servers_client
Eliad Cohenbec2d4d2022-09-14 17:52:59 +000024from tempest.lib.services.network import ports_client
lkuchlanf53947e2016-09-15 10:37:57 +030025from tempest.lib.services.volume.v2 import volumes_client
Matthew Treinishffad78a2016-04-16 14:39:52 -040026from tempest.tests import base
Jordan Pittier0e53b612016-03-03 14:23:17 +010027import tempest.tests.utils as utils
Matthew Treinish7b015822014-01-21 18:15:39 +000028
29
30class TestImageWaiters(base.TestCase):
31 def setUp(self):
32 super(TestImageWaiters, self).setUp()
33 self.client = mock.MagicMock()
34 self.client.build_timeout = 1
35 self.client.build_interval = 1
36
37 def test_wait_for_image_status(self):
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +000038 self.client.show_image.return_value = ({'status': 'active'})
Matthew Treinish7b015822014-01-21 18:15:39 +000039 start_time = int(time.time())
40 waiters.wait_for_image_status(self.client, 'fake_image_id', 'active')
41 end_time = int(time.time())
42 # Ensure waiter returns before build_timeout
Béla Vancsics64862f72016-11-08 09:12:31 +010043 self.assertLess((end_time - start_time), 10)
Matthew Treinish7b015822014-01-21 18:15:39 +000044
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +030045 def test_wait_for_image_status_timeout(self):
Jordan Pittier0e53b612016-03-03 14:23:17 +010046 time_mock = self.patch('time.time')
47 time_mock.side_effect = utils.generate_timeout_series(1)
48
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +000049 self.client.show_image.return_value = ({'status': 'saving'})
guo yunxianebb15f22016-11-01 21:03:35 +080050 self.assertRaises(lib_exc.TimeoutException,
Matthew Treinish7b015822014-01-21 18:15:39 +000051 waiters.wait_for_image_status,
52 self.client, 'fake_image_id', 'active')
53
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +030054 def test_wait_for_image_status_error_on_image_create(self):
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +000055 self.client.show_image.return_value = ({'status': 'ERROR'})
Matthew Treinish7b015822014-01-21 18:15:39 +000056 self.assertRaises(exceptions.AddImageException,
57 waiters.wait_for_image_status,
58 self.client, 'fake_image_id', 'active')
Matt Riedemannf77e7dc2015-08-10 16:39:39 -070059
zhufl414ffba2020-11-19 16:57:06 +080060 def test_wait_for_image_imported_to_stores(self):
61 self.client.show_image.return_value = ({'status': 'active',
62 'stores': 'fake_store'})
Dan Smith466f7062022-10-10 15:25:39 -070063 self.client.info_stores.return_value = {
64 'stores': [{'id': 'fake_store',
65 'description': 'A writable store'},
66 {'id': 'another_fake_store',
67 'description': 'A read-only store',
68 'read-only': 'true'}]
69 }
zhufl414ffba2020-11-19 16:57:06 +080070 start_time = int(time.time())
71 waiters.wait_for_image_imported_to_stores(
Dan Smith466f7062022-10-10 15:25:39 -070072 self.client, 'fake_image_id', 'fake_store,another_fake_store')
zhufl414ffba2020-11-19 16:57:06 +080073 end_time = int(time.time())
Dan Smith466f7062022-10-10 15:25:39 -070074 # Ensure waiter returns before build_timeout, and did not wait
75 # for the read-only store
zhufl414ffba2020-11-19 16:57:06 +080076 self.assertLess((end_time - start_time), 10)
77
Dan Smithef8e0542021-02-05 13:05:45 -080078 def test_wait_for_image_imported_to_stores_failure(self):
zhufl414ffba2020-11-19 16:57:06 +080079 time_mock = self.patch('time.time')
80 client = mock.MagicMock()
81 client.build_timeout = 2
82 self.patch('time.time', side_effect=[0., 1., 2.])
83 time_mock.side_effect = utils.generate_timeout_series(1)
84
85 client.show_image.return_value = ({
86 'status': 'saving',
87 'stores': 'fake_store',
88 'os_glance_failed_import': 'fake_os_glance_failed_import'})
Dan Smithef8e0542021-02-05 13:05:45 -080089 self.assertRaises(lib_exc.OtherRestClientException,
90 waiters.wait_for_image_imported_to_stores,
91 client, 'fake_image_id', 'fake_store')
92
93 def test_wait_for_image_imported_to_stores_timeout(self):
94 time_mock = self.patch('time.time')
95 client = mock.MagicMock()
96 client.build_timeout = 2
97 self.patch('time.time', side_effect=[0., 1., 2.])
98 time_mock.side_effect = utils.generate_timeout_series(1)
99
100 client.show_image.return_value = ({
101 'status': 'saving',
102 'stores': 'fake_store'})
zhufl414ffba2020-11-19 16:57:06 +0800103 self.assertRaises(lib_exc.TimeoutException,
104 waiters.wait_for_image_imported_to_stores,
105 client, 'fake_image_id', 'fake_store')
106
Dan Smith466f7062022-10-10 15:25:39 -0700107 def test_wait_for_image_imported_to_stores_no_stores(self):
108 client = mock.MagicMock()
109 client.show_image.return_value = ({'status': 'active'})
110 client.info_stores.side_effect = lib_exc.NotFound
111 client.build_timeout = 2
112 start_time = time.time()
113 waiters.wait_for_image_imported_to_stores(
114 client, 'fake_image_id', None)
115 end_time = time.time()
116 self.assertLess(end_time - start_time, 10)
117
118 exc = self.assertRaises(lib_exc.TimeoutException,
119 waiters.wait_for_image_imported_to_stores,
120 client, 'fake_image_id', 'foo,bar')
121 self.assertIn('cowardly', str(exc))
122
zhufl414ffba2020-11-19 16:57:06 +0800123 def test_wait_for_image_copied_to_stores(self):
124 self.client.show_image.return_value = ({
125 'status': 'active',
126 'os_glance_importing_to_stores': '',
127 'os_glance_failed_import': 'fake_os_glance_failed_import'})
128 start_time = int(time.time())
129 waiters.wait_for_image_copied_to_stores(
130 self.client, 'fake_image_id')
131 end_time = int(time.time())
132 # Ensure waiter returns before build_timeout
133 self.assertLess((end_time - start_time), 10)
134
135 def test_wait_for_image_copied_to_stores_timeout(self):
136 time_mock = self.patch('time.time')
137 self.patch('time.time', side_effect=[0., 1.])
138 time_mock.side_effect = utils.generate_timeout_series(1)
139
140 self.client.show_image.return_value = ({
141 'status': 'active',
142 'os_glance_importing_to_stores': 'processing',
143 'os_glance_failed_import': 'fake_os_glance_failed_import'})
144 self.assertRaises(lib_exc.TimeoutException,
145 waiters.wait_for_image_copied_to_stores,
146 self.client, 'fake_image_id')
147
Ghanshyam Mannb15b58e2021-04-29 19:45:29 -0500148 def test_wait_for_image_tasks_status(self):
149 self.client.show_image_tasks.return_value = ({
150 'tasks': [{'status': 'success'}]})
151 start_time = int(time.time())
152 waiters.wait_for_image_tasks_status(
153 self.client, 'fake_image_id', 'success')
154 end_time = int(time.time())
155 # Ensure waiter returns before build_timeout
156 self.assertLess((end_time - start_time), 10)
157
158 def test_wait_for_image_tasks_status_timeout(self):
159 time_mock = self.patch('time.time')
160 self.patch('time.time', side_effect=[0., 1.])
161 time_mock.side_effect = utils.generate_timeout_series(1)
162
163 self.client.show_image_tasks.return_value = ({
164 'tasks': [
165 {'status': 'success'},
166 {'status': 'processing'}]})
167 self.assertRaises(lib_exc.TimeoutException,
168 waiters.wait_for_image_tasks_status,
169 self.client, 'fake_image_id', 'success')
170
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400171
172class TestInterfaceWaiters(base.TestCase):
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400173
Federico Ressi8827d382018-06-12 23:27:00 +0200174 build_timeout = 1.
175 build_interval = 1
176 port_down = {'interfaceAttachment': {'port_state': 'DOWN'}}
177 port_active = {'interfaceAttachment': {'port_state': 'ACTIVE'}}
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400178
Federico Ressi8827d382018-06-12 23:27:00 +0200179 def mock_client(self, **kwargs):
180 return mock.MagicMock(
181 build_timeout=self.build_timeout,
182 build_interval=self.build_interval,
183 **kwargs)
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400184
185 def test_wait_for_interface_status(self):
Federico Ressi8827d382018-06-12 23:27:00 +0200186 show_interface = mock.Mock(
187 side_effect=[self.port_down, self.port_active])
188 client = self.mock_client(show_interface=show_interface)
189 self.patch('time.time', return_value=0.)
190 sleep = self.patch('time.sleep')
191
192 result = waiters.wait_for_interface_status(
193 client, 'server_id', 'port_id', 'ACTIVE')
194
195 self.assertIs(self.port_active['interfaceAttachment'], result)
196 show_interface.assert_has_calls([mock.call('server_id', 'port_id'),
197 mock.call('server_id', 'port_id')])
198 sleep.assert_called_once_with(client.build_interval)
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400199
200 def test_wait_for_interface_status_timeout(self):
Federico Ressi8827d382018-06-12 23:27:00 +0200201 show_interface = mock.MagicMock(return_value=self.port_down)
202 client = self.mock_client(show_interface=show_interface)
203 self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
204 sleep = self.patch('time.sleep')
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400205
Artom Lifshitzdf0d6d72018-05-11 11:31:11 -0400206 self.assertRaises(lib_exc.TimeoutException,
207 waiters.wait_for_interface_status,
Federico Ressi8827d382018-06-12 23:27:00 +0200208 client, 'server_id', 'port_id', 'ACTIVE')
Artom Lifshitz3306d422018-03-22 12:20:54 -0400209
Federico Ressi8827d382018-06-12 23:27:00 +0200210 show_interface.assert_has_calls([mock.call('server_id', 'port_id'),
211 mock.call('server_id', 'port_id')])
212 sleep.assert_called_once_with(client.build_interval)
Artom Lifshitz3306d422018-03-22 12:20:54 -0400213
Artom Lifshitz3306d422018-03-22 12:20:54 -0400214 def test_wait_for_interface_detach(self):
Balazs Gibizer55414582021-10-05 11:22:30 +0200215 no_event = {
216 'instanceAction': {
217 'events': []
218 }
219 }
220 one_event_without_result = {
221 'instanceAction': {
222 'events': [
223 {
224 'event': 'compute_detach_interface',
225 'result': None
226 }
227
228 ]
229 }
230 }
231 one_event_successful = {
232 'instanceAction': {
233 'events': [
234 {
235 'event': 'compute_detach_interface',
236 'result': 'Success'
237 }
238 ]
239 }
240 }
241
242 show_instance_action = mock.MagicMock(
243 # there is an extra call to return the result from the waiter
244 side_effect=[
245 no_event,
246 one_event_without_result,
247 one_event_successful,
248 one_event_successful,
249 ]
250 )
251 client = self.mock_client(show_instance_action=show_instance_action)
Federico Ressi8827d382018-06-12 23:27:00 +0200252 self.patch('time.time', return_value=0.)
253 sleep = self.patch('time.sleep')
254
255 result = waiters.wait_for_interface_detach(
Balazs Gibizer55414582021-10-05 11:22:30 +0200256 client, mock.sentinel.server_id, mock.sentinel.port_id,
257 mock.sentinel.detach_request_id
258 )
Federico Ressi8827d382018-06-12 23:27:00 +0200259
Balazs Gibizer55414582021-10-05 11:22:30 +0200260 self.assertIs(one_event_successful['instanceAction'], result)
261 show_instance_action.assert_has_calls(
262 # there is an extra call to return the result from the waiter
263 [
264 mock.call(
265 mock.sentinel.server_id, mock.sentinel.detach_request_id)
266 ] * 4
267 )
268 sleep.assert_has_calls([mock.call(client.build_interval)] * 2)
Artom Lifshitz3306d422018-03-22 12:20:54 -0400269
270 def test_wait_for_interface_detach_timeout(self):
Balazs Gibizer55414582021-10-05 11:22:30 +0200271 one_event_without_result = {
272 'instanceAction': {
273 'events': [
274 {
275 'event': 'compute_detach_interface',
276 'result': None
277 }
278
279 ]
280 }
281 }
282
283 show_instance_action = mock.MagicMock(
284 return_value=one_event_without_result)
285 client = self.mock_client(show_instance_action=show_instance_action)
Federico Ressi8827d382018-06-12 23:27:00 +0200286 self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
287 sleep = self.patch('time.sleep')
Artom Lifshitz3306d422018-03-22 12:20:54 -0400288
Balazs Gibizer55414582021-10-05 11:22:30 +0200289 self.assertRaises(
290 lib_exc.TimeoutException,
291 waiters.wait_for_interface_detach,
292 client, mock.sentinel.server_id, mock.sentinel.port_id,
293 mock.sentinel.detach_request_id
294 )
Federico Ressi8827d382018-06-12 23:27:00 +0200295
Balazs Gibizer55414582021-10-05 11:22:30 +0200296 show_instance_action.assert_has_calls(
297 [
298 mock.call(
299 mock.sentinel.server_id, mock.sentinel.detach_request_id)
300 ] * 2
301 )
Federico Ressi8827d382018-06-12 23:27:00 +0200302 sleep.assert_called_once_with(client.build_interval)
Lee Yarwoode5597402019-02-15 20:17:00 +0000303
304
305class TestVolumeWaiters(base.TestCase):
306 vol_migrating_src_host = {
307 'volume': {'migration_status': 'migrating',
308 'os-vol-host-attr:host': 'src_host@backend#type'}}
309 vol_migrating_dst_host = {
310 'volume': {'migration_status': 'migrating',
311 'os-vol-host-attr:host': 'dst_host@backend#type'}}
312 vol_migration_success = {
313 'volume': {'migration_status': 'success',
314 'os-vol-host-attr:host': 'dst_host@backend#type'}}
315 vol_migration_error = {
316 'volume': {'migration_status': 'error',
317 'os-vol-host-attr:host': 'src_host@backend#type'}}
318
319 def test_wait_for_volume_migration_timeout(self):
320 show_volume = mock.MagicMock(return_value=self.vol_migrating_src_host)
321 client = mock.Mock(spec=volumes_client.VolumesClient,
322 resource_type="volume",
323 build_interval=1,
324 build_timeout=1,
325 show_volume=show_volume)
326 self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
327 self.patch('time.sleep')
328 self.assertRaises(lib_exc.TimeoutException,
329 waiters.wait_for_volume_migration,
330 client, mock.sentinel.volume_id, 'dst_host')
331
332 def test_wait_for_volume_migration_error(self):
333 show_volume = mock.MagicMock(side_effect=[
334 self.vol_migrating_src_host,
335 self.vol_migrating_src_host,
336 self.vol_migration_error])
337 client = mock.Mock(spec=volumes_client.VolumesClient,
338 resource_type="volume",
339 build_interval=1,
340 build_timeout=1,
341 show_volume=show_volume)
342 self.patch('time.time', return_value=0.)
343 self.patch('time.sleep')
344 self.assertRaises(lib_exc.TempestException,
345 waiters.wait_for_volume_migration,
346 client, mock.sentinel.volume_id, 'dst_host')
347
348 def test_wait_for_volume_migration_success_and_dst(self):
349 show_volume = mock.MagicMock(side_effect=[
350 self.vol_migrating_src_host,
351 self.vol_migrating_dst_host,
352 self.vol_migration_success])
353 client = mock.Mock(spec=volumes_client.VolumesClient,
354 resource_type="volume",
355 build_interval=1,
356 build_timeout=1,
357 show_volume=show_volume)
358 self.patch('time.time', return_value=0.)
359 self.patch('time.sleep')
360 waiters.wait_for_volume_migration(
361 client, mock.sentinel.volume_id, 'dst_host')
362
363 # Assert that we wait until migration_status is success and dst_host is
364 # part of the returned os-vol-host-attr:host.
365 show_volume.assert_has_calls([mock.call(mock.sentinel.volume_id),
366 mock.call(mock.sentinel.volume_id),
367 mock.call(mock.sentinel.volume_id)])
Lee Yarwood9e202d82020-01-08 16:41:32 +0000368
369 @mock.patch.object(time, 'sleep')
370 def test_wait_for_volume_status_error_restoring(self, mock_sleep):
371 # Tests that the wait method raises VolumeRestoreErrorException if
372 # the volume status is 'error_restoring'.
373 client = mock.Mock(spec=volumes_client.VolumesClient,
374 resource_type="volume",
375 build_interval=1)
376 volume1 = {'volume': {'status': 'restoring-backup'}}
377 volume2 = {'volume': {'status': 'error_restoring'}}
378 mock_show = mock.Mock(side_effect=(volume1, volume2))
379 client.show_volume = mock_show
380 volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
381 self.assertRaises(exceptions.VolumeRestoreErrorException,
382 waiters.wait_for_volume_resource_status,
383 client, volume_id, 'available')
384 mock_show.assert_has_calls([mock.call(volume_id),
385 mock.call(volume_id)])
386 mock_sleep.assert_called_once_with(1)
387
388 @mock.patch.object(time, 'sleep')
Dan Smithaeacd8c2023-02-21 13:34:20 -0800389 def test_wait_for_volume_status_timeout_console(self, mock_sleep):
390 # Tests that the wait method gets the server console log if the
391 # timeout is hit.
392 client = mock.Mock(spec=volumes_client.VolumesClient,
393 resource_type="volume",
394 build_interval=1,
395 build_timeout=1)
396 servers_client = mock.Mock()
397 servers_client.get_console_output.return_value = {
398 'output': 'console log'}
399 volume = {'volume': {'status': 'detaching'}}
400 mock_show = mock.Mock(return_value=volume)
401 client.show_volume = mock_show
402 volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
403 self.assertRaises(lib_exc.TimeoutException,
404 waiters.wait_for_volume_resource_status,
405 client, volume_id, 'available',
406 server_id='someserver',
407 servers_client=servers_client)
408 servers_client.get_console_output.assert_called_once_with(
409 'someserver')
410
411 @mock.patch.object(time, 'sleep')
Lee Yarwood9e202d82020-01-08 16:41:32 +0000412 def test_wait_for_volume_status_error_extending(self, mock_sleep):
413 # Tests that the wait method raises VolumeExtendErrorException if
414 # the volume status is 'error_extending'.
415 client = mock.Mock(spec=volumes_client.VolumesClient,
416 resource_type="volume",
417 build_interval=1)
418 volume1 = {'volume': {'status': 'extending'}}
419 volume2 = {'volume': {'status': 'error_extending'}}
420 mock_show = mock.Mock(side_effect=(volume1, volume2))
421 client.show_volume = mock_show
422 volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
423 self.assertRaises(exceptions.VolumeExtendErrorException,
424 waiters.wait_for_volume_resource_status,
425 client, volume_id, 'available')
426 mock_show.assert_has_calls([mock.call(volume_id),
427 mock.call(volume_id)])
428 mock_sleep.assert_called_once_with(1)
Lee Yarwoodc1b2a4a2020-01-08 17:02:49 +0000429
Peter Penchev5c243a92020-09-06 02:26:03 +0300430 def test_wait_for_volume_attachment_create(self):
431 vol_detached = {'volume': {'attachments': []}}
432 vol_attached = {'volume': {'attachments': [
433 {'id': uuids.volume_id,
434 'attachment_id': uuids.attachment_id,
435 'server_id': uuids.server_id,
436 'volume_id': uuids.volume_id}]}}
437 show_volume = mock.MagicMock(side_effect=[
438 vol_detached, vol_detached, vol_attached])
439 client = mock.Mock(spec=volumes_client.VolumesClient,
440 build_interval=1,
441 build_timeout=5,
442 show_volume=show_volume)
443 self.patch('time.time')
444 self.patch('time.sleep')
445 att = waiters.wait_for_volume_attachment_create(
446 client, uuids.volume_id, uuids.server_id)
447 assert att == vol_attached['volume']['attachments'][0]
448 # Assert that show volume is called until the attachment is removed.
449 show_volume.assert_has_calls([mock.call(uuids.volume_id),
450 mock.call(uuids.volume_id),
451 mock.call(uuids.volume_id)])
452
Lee Yarwoodc1b2a4a2020-01-08 17:02:49 +0000453 def test_wait_for_volume_attachment(self):
454 vol_detached = {'volume': {'attachments': []}}
455 vol_attached = {'volume': {'attachments': [
456 {'attachment_id': uuids.attachment_id}]}}
457 show_volume = mock.MagicMock(side_effect=[
458 vol_attached, vol_attached, vol_detached])
459 client = mock.Mock(spec=volumes_client.VolumesClient,
460 build_interval=1,
461 build_timeout=5,
462 show_volume=show_volume)
463 self.patch('time.time')
464 self.patch('time.sleep')
465 waiters.wait_for_volume_attachment_remove(client, uuids.volume_id,
466 uuids.attachment_id)
467 # Assert that show volume is called until the attachment is removed.
Peter Penchevdc4ceae2020-09-09 00:47:50 +0300468 show_volume.assert_has_calls([mock.call(uuids.volume_id),
469 mock.call(uuids.volume_id),
470 mock.call(uuids.volume_id)])
Lee Yarwoodc1b2a4a2020-01-08 17:02:49 +0000471
472 def test_wait_for_volume_attachment_timeout(self):
473 show_volume = mock.MagicMock(return_value={
474 'volume': {'attachments': [
475 {'attachment_id': uuids.attachment_id}]}})
476 client = mock.Mock(spec=volumes_client.VolumesClient,
477 build_interval=1,
478 build_timeout=1,
479 show_volume=show_volume)
480 self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
481 self.patch('time.sleep')
482 # Assert that a timeout is raised if the attachment remains.
483 self.assertRaises(lib_exc.TimeoutException,
484 waiters.wait_for_volume_attachment_remove,
485 client, uuids.volume_id, uuids.attachment_id)
486
487 def test_wait_for_volume_attachment_not_present(self):
488 show_volume = mock.MagicMock(return_value={
489 'volume': {'attachments': []}})
490 client = mock.Mock(spec=volumes_client.VolumesClient,
491 build_interval=1,
492 build_timeout=1,
493 show_volume=show_volume)
494 self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
495 self.patch('time.sleep')
496 waiters.wait_for_volume_attachment_remove(client, uuids.volume_id,
497 uuids.attachment_id)
498 # Assert that show volume is only called once before we return
499 show_volume.assert_called_once_with(uuids.volume_id)
Balazs Gibizer2e515fe2020-12-07 15:10:11 +0100500
501 def test_wait_for_volume_attachment_remove_from_server(self):
502 volume_attached = {
503 "volumeAttachments": [{"volumeId": uuids.volume_id}]}
504 volume_not_attached = {"volumeAttachments": []}
505 mock_list_volume_attachments = mock.Mock(
506 side_effect=[volume_attached, volume_not_attached])
507 mock_client = mock.Mock(
508 spec=servers_client.ServersClient,
509 build_interval=1,
510 build_timeout=1,
511 list_volume_attachments=mock_list_volume_attachments)
512 self.patch(
513 'time.time',
514 side_effect=[0., 0.5, mock_client.build_timeout + 1.])
515 self.patch('time.sleep')
516
517 waiters.wait_for_volume_attachment_remove_from_server(
518 mock_client, uuids.server_id, uuids.volume_id)
519
520 # Assert that list_volume_attachments is called until the attachment is
521 # removed.
522 mock_list_volume_attachments.assert_has_calls([
523 mock.call(uuids.server_id),
524 mock.call(uuids.server_id)])
525
526 def test_wait_for_volume_attachment_remove_from_server_timeout(self):
527 volume_attached = {
528 "volumeAttachments": [{"volumeId": uuids.volume_id}]}
529 mock_list_volume_attachments = mock.Mock(
530 side_effect=[volume_attached, volume_attached])
Lee Yarwood1bd60592021-06-04 10:18:35 +0100531 mock_get_console_output = mock.Mock(
532 return_value={'output': 'output'})
Balazs Gibizer2e515fe2020-12-07 15:10:11 +0100533 mock_client = mock.Mock(
534 spec=servers_client.ServersClient,
535 build_interval=1,
536 build_timeout=1,
Lee Yarwood1bd60592021-06-04 10:18:35 +0100537 list_volume_attachments=mock_list_volume_attachments,
538 get_console_output=mock_get_console_output)
Balazs Gibizer2e515fe2020-12-07 15:10:11 +0100539 self.patch(
540 'time.time',
541 side_effect=[0., 0.5, mock_client.build_timeout + 1.])
542 self.patch('time.sleep')
543
544 self.assertRaises(
545 lib_exc.TimeoutException,
546 waiters.wait_for_volume_attachment_remove_from_server,
547 mock_client, uuids.server_id, uuids.volume_id)
548
549 # Assert that list_volume_attachments is called until the attachment is
550 # removed.
551 mock_list_volume_attachments.assert_has_calls([
552 mock.call(uuids.server_id),
553 mock.call(uuids.server_id)])
Lee Yarwood1bd60592021-06-04 10:18:35 +0100554
555 # Assert that we fetch console output
556 mock_get_console_output.assert_called_once_with(uuids.server_id)
557
558 def test_wait_for_volume_attachment_remove_from_server_not_found(self):
559 mock_list_volume_attachments = mock.Mock(
560 side_effect=lib_exc.NotFound)
561 mock_client = mock.Mock(
562 spec=servers_client.ServersClient,
563 list_volume_attachments=mock_list_volume_attachments)
564
565 # Assert that nothing is raised when lib_exc_NotFound is raised
566 # by the client call to list_volume_attachments
567 waiters.wait_for_volume_attachment_remove_from_server(
568 mock_client, mock.sentinel.server_id, mock.sentinel.volume_id)
569
570 # Assert that list_volume_attachments was actually called
571 mock_list_volume_attachments.assert_called_once_with(
572 mock.sentinel.server_id)
Artom Lifshitz8a959ea2021-09-27 12:09:12 -0400573
Lee Yarwood0b4bc3d2021-11-11 17:45:25 +0000574 @mock.patch('os.system')
575 def test_wait_for_ping_host_alive(self, mock_ping):
576 mock_ping.return_value = 0
577 # Assert that nothing is raised as the host is alive
578 waiters.wait_for_ping('127.0.0.1', 10, 1)
579
580 @mock.patch('os.system')
581 def test_wait_for_ping_host_eventually_alive(self, mock_ping):
582 mock_ping.side_effect = [1, 1, 0]
583 # Assert that nothing is raised when the host is eventually alive
584 waiters.wait_for_ping('127.0.0.1', 10, 1)
585
586 @mock.patch('os.system')
587 def test_wait_for_ping_timeout(self, mock_ping):
588 mock_ping.return_value = 1
589 # Assert that TimeoutException is raised when the host is dead
590 self.assertRaises(
591 lib_exc.TimeoutException,
592 waiters.wait_for_ping,
593 '127.0.0.1',
594 .1,
595 .1
596 )
597
598 def test_wait_for_ssh(self):
599 mock_ssh_client = mock.Mock()
600 mock_ssh_client.validate_authentication.return_value = True
601 # Assert that nothing is raised when validate_authentication returns
602 waiters.wait_for_ssh(mock_ssh_client, .1)
603 mock_ssh_client.validate_authentication.assert_called_once()
604
605 def test_wait_for_ssh_eventually_up(self):
606 mock_ssh_client = mock.Mock()
607 timeout = lib_exc.SSHTimeout(
608 host='foo',
609 username='bar',
610 password='fizz'
611 )
612 mock_ssh_client.validate_authentication.side_effect = [
613 timeout,
614 timeout,
615 True
616 ]
617 # Assert that nothing is raised if validate_authentication passes
618 # before the timeout
619 waiters.wait_for_ssh(mock_ssh_client, 10)
620
621 def test_wait_for_ssh_timeout(self):
622 mock_ssh_client = mock.Mock()
623 timeout = lib_exc.SSHTimeout(
624 host='foo',
625 username='bar',
626 password='fizz'
627 )
628 mock_ssh_client.validate_authentication.side_effect = timeout
629 # Assert that TimeoutException is raised when validate_authentication
630 # doesn't pass in time.
631 self.assertRaises(
632 lib_exc.TimeoutException,
633 waiters.wait_for_ssh,
634 mock_ssh_client,
635 .1
636 )
637
Artom Lifshitz8a959ea2021-09-27 12:09:12 -0400638
Eliad Cohenbec2d4d2022-09-14 17:52:59 +0000639class TestPortCreationWaiter(base.TestCase):
640 def test_wait_for_port_status(self):
641 """Test that the waiter replies with the port before the timeout"""
642
643 def client_response(self):
644 """Mock client response, replies with the final status after
645 2 calls
646 """
647 if mock_client.call_count >= 2:
648 return mock_port
649 else:
650 mock_client.call_count += 1
651 return mock_port_build
652
653 mock_port = {'port': {'id': '1234', 'status': "DOWN"}}
654 mock_port_build = {'port': {'id': '1234', 'status': "BUILD"}}
655 mock_client = mock.Mock(
656 spec=ports_client.PortsClient,
657 build_timeout=30, build_interval=1,
658 show_port=client_response)
659 fake_port_id = "1234"
660 fake_status = "DOWN"
661 self.assertEqual(mock_port, waiters.wait_for_port_status(
662 mock_client, fake_port_id, fake_status))
663
664 def test_wait_for_port_status_timeout(self):
665 """Negative test - checking that a timeout
666 presented by a small 'fake_timeout' and a static status of
667 'BUILD' in the mock will raise a timeout exception
668 """
669 mock_port = {'port': {'id': '1234', 'status': "BUILD"}}
670 mock_client = mock.Mock(
671 spec=ports_client.PortsClient,
672 build_timeout=2, build_interval=1,
673 show_port=lambda id: mock_port)
674 fake_port_id = "1234"
675 fake_status = "ACTIVE"
676 self.assertRaises(lib_exc.TimeoutException,
677 waiters.wait_for_port_status, mock_client,
678 fake_port_id, fake_status)
679
680
Artom Lifshitz8a959ea2021-09-27 12:09:12 -0400681class TestServerFloatingIPWaiters(base.TestCase):
682
683 def test_wait_for_server_floating_ip_associate_timeout(self):
684 mock_server = {'server': {'id': 'fake_uuid', 'addresses': {}}}
685 mock_client = mock.Mock(
686 spec=servers_client.ServersClient,
687 build_timeout=1, build_interval=1,
688 show_server=lambda id: mock_server)
689
690 fake_server = {'id': 'fake-uuid'}
691 fake_fip = {'floating_ip_address': 'fake_address'}
692 self.assertRaises(
693 lib_exc.TimeoutException,
694 waiters.wait_for_server_floating_ip, mock_client, fake_server,
695 fake_fip)
696
697 def test_wait_for_server_floating_ip_disassociate_timeout(self):
698 mock_addresses = {'shared': [{'OS-EXT-IPS:type': 'floating',
699 'addr': 'fake_address'}]}
700 mock_server = {'server': {'id': 'fake_uuid',
701 'addresses': mock_addresses}}
702 mock_client = mock.Mock(
703 spec=servers_client.ServersClient,
704 build_timeout=1, build_interval=1,
705 show_server=lambda id: mock_server)
706
707 fake_server = {'id': 'fake-uuid'}
708 fake_fip = {'floating_ip_address': 'fake_address'}
709 self.assertRaises(
710 lib_exc.TimeoutException,
711 waiters.wait_for_server_floating_ip, mock_client, fake_server,
712 fake_fip, wait_for_disassociate=True)