Matthew Treinish | 7b01582 | 2014-01-21 18:15:39 +0000 | [diff] [blame] | 1 | # 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 | |
| 15 | import time |
Sean McGinnis | eed8074 | 2020-04-18 12:01:03 -0500 | [diff] [blame] | 16 | from unittest import mock |
Matthew Treinish | 7b01582 | 2014-01-21 18:15:39 +0000 | [diff] [blame] | 17 | |
Lee Yarwood | c1b2a4a | 2020-01-08 17:02:49 +0000 | [diff] [blame] | 18 | from oslo_utils.fixture import uuidsentinel as uuids |
Matthew Treinish | 7b01582 | 2014-01-21 18:15:39 +0000 | [diff] [blame] | 19 | |
| 20 | from tempest.common import waiters |
| 21 | from tempest import exceptions |
guo yunxian | ebb15f2 | 2016-11-01 21:03:35 +0800 | [diff] [blame] | 22 | from tempest.lib import exceptions as lib_exc |
Balazs Gibizer | 2e515fe | 2020-12-07 15:10:11 +0100 | [diff] [blame] | 23 | from tempest.lib.services.compute import servers_client |
lkuchlan | f53947e | 2016-09-15 10:37:57 +0300 | [diff] [blame] | 24 | from tempest.lib.services.volume.v2 import volumes_client |
Matthew Treinish | ffad78a | 2016-04-16 14:39:52 -0400 | [diff] [blame] | 25 | from tempest.tests import base |
Jordan Pittier | 0e53b61 | 2016-03-03 14:23:17 +0100 | [diff] [blame] | 26 | import tempest.tests.utils as utils |
Matthew Treinish | 7b01582 | 2014-01-21 18:15:39 +0000 | [diff] [blame] | 27 | |
| 28 | |
| 29 | class TestImageWaiters(base.TestCase): |
| 30 | def setUp(self): |
| 31 | super(TestImageWaiters, self).setUp() |
| 32 | self.client = mock.MagicMock() |
| 33 | self.client.build_timeout = 1 |
| 34 | self.client.build_interval = 1 |
| 35 | |
| 36 | def test_wait_for_image_status(self): |
Ken'ichi Ohmichi | 5d41076 | 2015-05-22 01:10:03 +0000 | [diff] [blame] | 37 | self.client.show_image.return_value = ({'status': 'active'}) |
Matthew Treinish | 7b01582 | 2014-01-21 18:15:39 +0000 | [diff] [blame] | 38 | start_time = int(time.time()) |
| 39 | waiters.wait_for_image_status(self.client, 'fake_image_id', 'active') |
| 40 | end_time = int(time.time()) |
| 41 | # Ensure waiter returns before build_timeout |
Béla Vancsics | 64862f7 | 2016-11-08 09:12:31 +0100 | [diff] [blame] | 42 | self.assertLess((end_time - start_time), 10) |
Matthew Treinish | 7b01582 | 2014-01-21 18:15:39 +0000 | [diff] [blame] | 43 | |
Yaroslav Lobankov | 2fea405 | 2016-04-19 15:05:57 +0300 | [diff] [blame] | 44 | def test_wait_for_image_status_timeout(self): |
Jordan Pittier | 0e53b61 | 2016-03-03 14:23:17 +0100 | [diff] [blame] | 45 | time_mock = self.patch('time.time') |
| 46 | time_mock.side_effect = utils.generate_timeout_series(1) |
| 47 | |
Ken'ichi Ohmichi | 5d41076 | 2015-05-22 01:10:03 +0000 | [diff] [blame] | 48 | self.client.show_image.return_value = ({'status': 'saving'}) |
guo yunxian | ebb15f2 | 2016-11-01 21:03:35 +0800 | [diff] [blame] | 49 | self.assertRaises(lib_exc.TimeoutException, |
Matthew Treinish | 7b01582 | 2014-01-21 18:15:39 +0000 | [diff] [blame] | 50 | waiters.wait_for_image_status, |
| 51 | self.client, 'fake_image_id', 'active') |
| 52 | |
Yaroslav Lobankov | 2fea405 | 2016-04-19 15:05:57 +0300 | [diff] [blame] | 53 | def test_wait_for_image_status_error_on_image_create(self): |
Ken'ichi Ohmichi | 5d41076 | 2015-05-22 01:10:03 +0000 | [diff] [blame] | 54 | self.client.show_image.return_value = ({'status': 'ERROR'}) |
Matthew Treinish | 7b01582 | 2014-01-21 18:15:39 +0000 | [diff] [blame] | 55 | self.assertRaises(exceptions.AddImageException, |
| 56 | waiters.wait_for_image_status, |
| 57 | self.client, 'fake_image_id', 'active') |
Matt Riedemann | f77e7dc | 2015-08-10 16:39:39 -0700 | [diff] [blame] | 58 | |
zhufl | 414ffba | 2020-11-19 16:57:06 +0800 | [diff] [blame] | 59 | def test_wait_for_image_imported_to_stores(self): |
| 60 | self.client.show_image.return_value = ({'status': 'active', |
| 61 | 'stores': 'fake_store'}) |
| 62 | start_time = int(time.time()) |
| 63 | waiters.wait_for_image_imported_to_stores( |
| 64 | self.client, 'fake_image_id', 'fake_store') |
| 65 | end_time = int(time.time()) |
| 66 | # Ensure waiter returns before build_timeout |
| 67 | self.assertLess((end_time - start_time), 10) |
| 68 | |
Dan Smith | ef8e054 | 2021-02-05 13:05:45 -0800 | [diff] [blame] | 69 | def test_wait_for_image_imported_to_stores_failure(self): |
zhufl | 414ffba | 2020-11-19 16:57:06 +0800 | [diff] [blame] | 70 | time_mock = self.patch('time.time') |
| 71 | client = mock.MagicMock() |
| 72 | client.build_timeout = 2 |
| 73 | self.patch('time.time', side_effect=[0., 1., 2.]) |
| 74 | time_mock.side_effect = utils.generate_timeout_series(1) |
| 75 | |
| 76 | client.show_image.return_value = ({ |
| 77 | 'status': 'saving', |
| 78 | 'stores': 'fake_store', |
| 79 | 'os_glance_failed_import': 'fake_os_glance_failed_import'}) |
Dan Smith | ef8e054 | 2021-02-05 13:05:45 -0800 | [diff] [blame] | 80 | self.assertRaises(lib_exc.OtherRestClientException, |
| 81 | waiters.wait_for_image_imported_to_stores, |
| 82 | client, 'fake_image_id', 'fake_store') |
| 83 | |
| 84 | def test_wait_for_image_imported_to_stores_timeout(self): |
| 85 | time_mock = self.patch('time.time') |
| 86 | client = mock.MagicMock() |
| 87 | client.build_timeout = 2 |
| 88 | self.patch('time.time', side_effect=[0., 1., 2.]) |
| 89 | time_mock.side_effect = utils.generate_timeout_series(1) |
| 90 | |
| 91 | client.show_image.return_value = ({ |
| 92 | 'status': 'saving', |
| 93 | 'stores': 'fake_store'}) |
zhufl | 414ffba | 2020-11-19 16:57:06 +0800 | [diff] [blame] | 94 | self.assertRaises(lib_exc.TimeoutException, |
| 95 | waiters.wait_for_image_imported_to_stores, |
| 96 | client, 'fake_image_id', 'fake_store') |
| 97 | |
| 98 | def test_wait_for_image_copied_to_stores(self): |
| 99 | self.client.show_image.return_value = ({ |
| 100 | 'status': 'active', |
| 101 | 'os_glance_importing_to_stores': '', |
| 102 | 'os_glance_failed_import': 'fake_os_glance_failed_import'}) |
| 103 | start_time = int(time.time()) |
| 104 | waiters.wait_for_image_copied_to_stores( |
| 105 | self.client, 'fake_image_id') |
| 106 | end_time = int(time.time()) |
| 107 | # Ensure waiter returns before build_timeout |
| 108 | self.assertLess((end_time - start_time), 10) |
| 109 | |
| 110 | def test_wait_for_image_copied_to_stores_timeout(self): |
| 111 | time_mock = self.patch('time.time') |
| 112 | self.patch('time.time', side_effect=[0., 1.]) |
| 113 | time_mock.side_effect = utils.generate_timeout_series(1) |
| 114 | |
| 115 | self.client.show_image.return_value = ({ |
| 116 | 'status': 'active', |
| 117 | 'os_glance_importing_to_stores': 'processing', |
| 118 | 'os_glance_failed_import': 'fake_os_glance_failed_import'}) |
| 119 | self.assertRaises(lib_exc.TimeoutException, |
| 120 | waiters.wait_for_image_copied_to_stores, |
| 121 | self.client, 'fake_image_id') |
| 122 | |
Ghanshyam Mann | b15b58e | 2021-04-29 19:45:29 -0500 | [diff] [blame] | 123 | def test_wait_for_image_tasks_status(self): |
| 124 | self.client.show_image_tasks.return_value = ({ |
| 125 | 'tasks': [{'status': 'success'}]}) |
| 126 | start_time = int(time.time()) |
| 127 | waiters.wait_for_image_tasks_status( |
| 128 | self.client, 'fake_image_id', 'success') |
| 129 | end_time = int(time.time()) |
| 130 | # Ensure waiter returns before build_timeout |
| 131 | self.assertLess((end_time - start_time), 10) |
| 132 | |
| 133 | def test_wait_for_image_tasks_status_timeout(self): |
| 134 | time_mock = self.patch('time.time') |
| 135 | self.patch('time.time', side_effect=[0., 1.]) |
| 136 | time_mock.side_effect = utils.generate_timeout_series(1) |
| 137 | |
| 138 | self.client.show_image_tasks.return_value = ({ |
| 139 | 'tasks': [ |
| 140 | {'status': 'success'}, |
| 141 | {'status': 'processing'}]}) |
| 142 | self.assertRaises(lib_exc.TimeoutException, |
| 143 | waiters.wait_for_image_tasks_status, |
| 144 | self.client, 'fake_image_id', 'success') |
| 145 | |
Artom Lifshitz | df0d6d7 | 2018-05-11 11:31:11 -0400 | [diff] [blame] | 146 | |
| 147 | class TestInterfaceWaiters(base.TestCase): |
Artom Lifshitz | df0d6d7 | 2018-05-11 11:31:11 -0400 | [diff] [blame] | 148 | |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 149 | build_timeout = 1. |
| 150 | build_interval = 1 |
| 151 | port_down = {'interfaceAttachment': {'port_state': 'DOWN'}} |
| 152 | port_active = {'interfaceAttachment': {'port_state': 'ACTIVE'}} |
Artom Lifshitz | df0d6d7 | 2018-05-11 11:31:11 -0400 | [diff] [blame] | 153 | |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 154 | def mock_client(self, **kwargs): |
| 155 | return mock.MagicMock( |
| 156 | build_timeout=self.build_timeout, |
| 157 | build_interval=self.build_interval, |
| 158 | **kwargs) |
Artom Lifshitz | df0d6d7 | 2018-05-11 11:31:11 -0400 | [diff] [blame] | 159 | |
| 160 | def test_wait_for_interface_status(self): |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 161 | show_interface = mock.Mock( |
| 162 | side_effect=[self.port_down, self.port_active]) |
| 163 | client = self.mock_client(show_interface=show_interface) |
| 164 | self.patch('time.time', return_value=0.) |
| 165 | sleep = self.patch('time.sleep') |
| 166 | |
| 167 | result = waiters.wait_for_interface_status( |
| 168 | client, 'server_id', 'port_id', 'ACTIVE') |
| 169 | |
| 170 | self.assertIs(self.port_active['interfaceAttachment'], result) |
| 171 | show_interface.assert_has_calls([mock.call('server_id', 'port_id'), |
| 172 | mock.call('server_id', 'port_id')]) |
| 173 | sleep.assert_called_once_with(client.build_interval) |
Artom Lifshitz | df0d6d7 | 2018-05-11 11:31:11 -0400 | [diff] [blame] | 174 | |
| 175 | def test_wait_for_interface_status_timeout(self): |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 176 | show_interface = mock.MagicMock(return_value=self.port_down) |
| 177 | client = self.mock_client(show_interface=show_interface) |
| 178 | self.patch('time.time', side_effect=[0., client.build_timeout + 1.]) |
| 179 | sleep = self.patch('time.sleep') |
Artom Lifshitz | df0d6d7 | 2018-05-11 11:31:11 -0400 | [diff] [blame] | 180 | |
Artom Lifshitz | df0d6d7 | 2018-05-11 11:31:11 -0400 | [diff] [blame] | 181 | self.assertRaises(lib_exc.TimeoutException, |
| 182 | waiters.wait_for_interface_status, |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 183 | client, 'server_id', 'port_id', 'ACTIVE') |
Artom Lifshitz | 3306d42 | 2018-03-22 12:20:54 -0400 | [diff] [blame] | 184 | |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 185 | show_interface.assert_has_calls([mock.call('server_id', 'port_id'), |
| 186 | mock.call('server_id', 'port_id')]) |
| 187 | sleep.assert_called_once_with(client.build_interval) |
Artom Lifshitz | 3306d42 | 2018-03-22 12:20:54 -0400 | [diff] [blame] | 188 | |
Artom Lifshitz | 3306d42 | 2018-03-22 12:20:54 -0400 | [diff] [blame] | 189 | def test_wait_for_interface_detach(self): |
Balazs Gibizer | 5541458 | 2021-10-05 11:22:30 +0200 | [diff] [blame] | 190 | no_event = { |
| 191 | 'instanceAction': { |
| 192 | 'events': [] |
| 193 | } |
| 194 | } |
| 195 | one_event_without_result = { |
| 196 | 'instanceAction': { |
| 197 | 'events': [ |
| 198 | { |
| 199 | 'event': 'compute_detach_interface', |
| 200 | 'result': None |
| 201 | } |
| 202 | |
| 203 | ] |
| 204 | } |
| 205 | } |
| 206 | one_event_successful = { |
| 207 | 'instanceAction': { |
| 208 | 'events': [ |
| 209 | { |
| 210 | 'event': 'compute_detach_interface', |
| 211 | 'result': 'Success' |
| 212 | } |
| 213 | ] |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | show_instance_action = mock.MagicMock( |
| 218 | # there is an extra call to return the result from the waiter |
| 219 | side_effect=[ |
| 220 | no_event, |
| 221 | one_event_without_result, |
| 222 | one_event_successful, |
| 223 | one_event_successful, |
| 224 | ] |
| 225 | ) |
| 226 | client = self.mock_client(show_instance_action=show_instance_action) |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 227 | self.patch('time.time', return_value=0.) |
| 228 | sleep = self.patch('time.sleep') |
| 229 | |
| 230 | result = waiters.wait_for_interface_detach( |
Balazs Gibizer | 5541458 | 2021-10-05 11:22:30 +0200 | [diff] [blame] | 231 | client, mock.sentinel.server_id, mock.sentinel.port_id, |
| 232 | mock.sentinel.detach_request_id |
| 233 | ) |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 234 | |
Balazs Gibizer | 5541458 | 2021-10-05 11:22:30 +0200 | [diff] [blame] | 235 | self.assertIs(one_event_successful['instanceAction'], result) |
| 236 | show_instance_action.assert_has_calls( |
| 237 | # there is an extra call to return the result from the waiter |
| 238 | [ |
| 239 | mock.call( |
| 240 | mock.sentinel.server_id, mock.sentinel.detach_request_id) |
| 241 | ] * 4 |
| 242 | ) |
| 243 | sleep.assert_has_calls([mock.call(client.build_interval)] * 2) |
Artom Lifshitz | 3306d42 | 2018-03-22 12:20:54 -0400 | [diff] [blame] | 244 | |
| 245 | def test_wait_for_interface_detach_timeout(self): |
Balazs Gibizer | 5541458 | 2021-10-05 11:22:30 +0200 | [diff] [blame] | 246 | one_event_without_result = { |
| 247 | 'instanceAction': { |
| 248 | 'events': [ |
| 249 | { |
| 250 | 'event': 'compute_detach_interface', |
| 251 | 'result': None |
| 252 | } |
| 253 | |
| 254 | ] |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | show_instance_action = mock.MagicMock( |
| 259 | return_value=one_event_without_result) |
| 260 | client = self.mock_client(show_instance_action=show_instance_action) |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 261 | self.patch('time.time', side_effect=[0., client.build_timeout + 1.]) |
| 262 | sleep = self.patch('time.sleep') |
Artom Lifshitz | 3306d42 | 2018-03-22 12:20:54 -0400 | [diff] [blame] | 263 | |
Balazs Gibizer | 5541458 | 2021-10-05 11:22:30 +0200 | [diff] [blame] | 264 | self.assertRaises( |
| 265 | lib_exc.TimeoutException, |
| 266 | waiters.wait_for_interface_detach, |
| 267 | client, mock.sentinel.server_id, mock.sentinel.port_id, |
| 268 | mock.sentinel.detach_request_id |
| 269 | ) |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 270 | |
Balazs Gibizer | 5541458 | 2021-10-05 11:22:30 +0200 | [diff] [blame] | 271 | show_instance_action.assert_has_calls( |
| 272 | [ |
| 273 | mock.call( |
| 274 | mock.sentinel.server_id, mock.sentinel.detach_request_id) |
| 275 | ] * 2 |
| 276 | ) |
Federico Ressi | 8827d38 | 2018-06-12 23:27:00 +0200 | [diff] [blame] | 277 | sleep.assert_called_once_with(client.build_interval) |
Lee Yarwood | e559740 | 2019-02-15 20:17:00 +0000 | [diff] [blame] | 278 | |
Slawek Kaplonski | e3405ba | 2020-11-09 17:24:13 +0100 | [diff] [blame] | 279 | def test_wait_for_guest_os_boot(self): |
| 280 | get_console_output = mock.Mock( |
| 281 | side_effect=[ |
| 282 | {'output': 'os not ready yet\n'}, |
| 283 | {'output': 'login:\n'} |
| 284 | ]) |
| 285 | client = self.mock_client(get_console_output=get_console_output) |
| 286 | self.patch('time.time', return_value=0.) |
| 287 | sleep = self.patch('time.sleep') |
| 288 | |
| 289 | with mock.patch.object(waiters.LOG, "info") as log_info: |
| 290 | waiters.wait_for_guest_os_boot(client, 'server_id') |
| 291 | |
| 292 | get_console_output.assert_has_calls([ |
| 293 | mock.call('server_id'), mock.call('server_id')]) |
| 294 | sleep.assert_called_once_with(client.build_interval) |
| 295 | log_info.assert_not_called() |
| 296 | |
| 297 | def test_wait_for_guest_os_boot_timeout(self): |
| 298 | get_console_output = mock.Mock( |
| 299 | return_value={'output': 'os not ready yet\n'}) |
| 300 | client = self.mock_client(get_console_output=get_console_output) |
| 301 | self.patch('time.time', side_effect=[0., client.build_timeout + 1.]) |
| 302 | self.patch('time.sleep') |
| 303 | |
| 304 | with mock.patch.object(waiters.LOG, "info") as log_info: |
| 305 | waiters.wait_for_guest_os_boot(client, 'server_id') |
| 306 | |
| 307 | log_info.assert_called_once() |
| 308 | |
Lee Yarwood | e559740 | 2019-02-15 20:17:00 +0000 | [diff] [blame] | 309 | |
| 310 | class TestVolumeWaiters(base.TestCase): |
| 311 | vol_migrating_src_host = { |
| 312 | 'volume': {'migration_status': 'migrating', |
| 313 | 'os-vol-host-attr:host': 'src_host@backend#type'}} |
| 314 | vol_migrating_dst_host = { |
| 315 | 'volume': {'migration_status': 'migrating', |
| 316 | 'os-vol-host-attr:host': 'dst_host@backend#type'}} |
| 317 | vol_migration_success = { |
| 318 | 'volume': {'migration_status': 'success', |
| 319 | 'os-vol-host-attr:host': 'dst_host@backend#type'}} |
| 320 | vol_migration_error = { |
| 321 | 'volume': {'migration_status': 'error', |
| 322 | 'os-vol-host-attr:host': 'src_host@backend#type'}} |
| 323 | |
| 324 | def test_wait_for_volume_migration_timeout(self): |
| 325 | show_volume = mock.MagicMock(return_value=self.vol_migrating_src_host) |
| 326 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 327 | resource_type="volume", |
| 328 | build_interval=1, |
| 329 | build_timeout=1, |
| 330 | show_volume=show_volume) |
| 331 | self.patch('time.time', side_effect=[0., client.build_timeout + 1.]) |
| 332 | self.patch('time.sleep') |
| 333 | self.assertRaises(lib_exc.TimeoutException, |
| 334 | waiters.wait_for_volume_migration, |
| 335 | client, mock.sentinel.volume_id, 'dst_host') |
| 336 | |
| 337 | def test_wait_for_volume_migration_error(self): |
| 338 | show_volume = mock.MagicMock(side_effect=[ |
| 339 | self.vol_migrating_src_host, |
| 340 | self.vol_migrating_src_host, |
| 341 | self.vol_migration_error]) |
| 342 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 343 | resource_type="volume", |
| 344 | build_interval=1, |
| 345 | build_timeout=1, |
| 346 | show_volume=show_volume) |
| 347 | self.patch('time.time', return_value=0.) |
| 348 | self.patch('time.sleep') |
| 349 | self.assertRaises(lib_exc.TempestException, |
| 350 | waiters.wait_for_volume_migration, |
| 351 | client, mock.sentinel.volume_id, 'dst_host') |
| 352 | |
| 353 | def test_wait_for_volume_migration_success_and_dst(self): |
| 354 | show_volume = mock.MagicMock(side_effect=[ |
| 355 | self.vol_migrating_src_host, |
| 356 | self.vol_migrating_dst_host, |
| 357 | self.vol_migration_success]) |
| 358 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 359 | resource_type="volume", |
| 360 | build_interval=1, |
| 361 | build_timeout=1, |
| 362 | show_volume=show_volume) |
| 363 | self.patch('time.time', return_value=0.) |
| 364 | self.patch('time.sleep') |
| 365 | waiters.wait_for_volume_migration( |
| 366 | client, mock.sentinel.volume_id, 'dst_host') |
| 367 | |
| 368 | # Assert that we wait until migration_status is success and dst_host is |
| 369 | # part of the returned os-vol-host-attr:host. |
| 370 | show_volume.assert_has_calls([mock.call(mock.sentinel.volume_id), |
| 371 | mock.call(mock.sentinel.volume_id), |
| 372 | mock.call(mock.sentinel.volume_id)]) |
Lee Yarwood | 9e202d8 | 2020-01-08 16:41:32 +0000 | [diff] [blame] | 373 | |
| 374 | @mock.patch.object(time, 'sleep') |
| 375 | def test_wait_for_volume_status_error_restoring(self, mock_sleep): |
| 376 | # Tests that the wait method raises VolumeRestoreErrorException if |
| 377 | # the volume status is 'error_restoring'. |
| 378 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 379 | resource_type="volume", |
| 380 | build_interval=1) |
| 381 | volume1 = {'volume': {'status': 'restoring-backup'}} |
| 382 | volume2 = {'volume': {'status': 'error_restoring'}} |
| 383 | mock_show = mock.Mock(side_effect=(volume1, volume2)) |
| 384 | client.show_volume = mock_show |
| 385 | volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa' |
| 386 | self.assertRaises(exceptions.VolumeRestoreErrorException, |
| 387 | waiters.wait_for_volume_resource_status, |
| 388 | client, volume_id, 'available') |
| 389 | mock_show.assert_has_calls([mock.call(volume_id), |
| 390 | mock.call(volume_id)]) |
| 391 | mock_sleep.assert_called_once_with(1) |
| 392 | |
| 393 | @mock.patch.object(time, 'sleep') |
| 394 | def test_wait_for_volume_status_error_extending(self, mock_sleep): |
| 395 | # Tests that the wait method raises VolumeExtendErrorException if |
| 396 | # the volume status is 'error_extending'. |
| 397 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 398 | resource_type="volume", |
| 399 | build_interval=1) |
| 400 | volume1 = {'volume': {'status': 'extending'}} |
| 401 | volume2 = {'volume': {'status': 'error_extending'}} |
| 402 | mock_show = mock.Mock(side_effect=(volume1, volume2)) |
| 403 | client.show_volume = mock_show |
| 404 | volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa' |
| 405 | self.assertRaises(exceptions.VolumeExtendErrorException, |
| 406 | waiters.wait_for_volume_resource_status, |
| 407 | client, volume_id, 'available') |
| 408 | mock_show.assert_has_calls([mock.call(volume_id), |
| 409 | mock.call(volume_id)]) |
| 410 | mock_sleep.assert_called_once_with(1) |
Lee Yarwood | c1b2a4a | 2020-01-08 17:02:49 +0000 | [diff] [blame] | 411 | |
Peter Penchev | 5c243a9 | 2020-09-06 02:26:03 +0300 | [diff] [blame] | 412 | def test_wait_for_volume_attachment_create(self): |
| 413 | vol_detached = {'volume': {'attachments': []}} |
| 414 | vol_attached = {'volume': {'attachments': [ |
| 415 | {'id': uuids.volume_id, |
| 416 | 'attachment_id': uuids.attachment_id, |
| 417 | 'server_id': uuids.server_id, |
| 418 | 'volume_id': uuids.volume_id}]}} |
| 419 | show_volume = mock.MagicMock(side_effect=[ |
| 420 | vol_detached, vol_detached, vol_attached]) |
| 421 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 422 | build_interval=1, |
| 423 | build_timeout=5, |
| 424 | show_volume=show_volume) |
| 425 | self.patch('time.time') |
| 426 | self.patch('time.sleep') |
| 427 | att = waiters.wait_for_volume_attachment_create( |
| 428 | client, uuids.volume_id, uuids.server_id) |
| 429 | assert att == vol_attached['volume']['attachments'][0] |
| 430 | # Assert that show volume is called until the attachment is removed. |
| 431 | show_volume.assert_has_calls([mock.call(uuids.volume_id), |
| 432 | mock.call(uuids.volume_id), |
| 433 | mock.call(uuids.volume_id)]) |
| 434 | |
Lee Yarwood | c1b2a4a | 2020-01-08 17:02:49 +0000 | [diff] [blame] | 435 | def test_wait_for_volume_attachment(self): |
| 436 | vol_detached = {'volume': {'attachments': []}} |
| 437 | vol_attached = {'volume': {'attachments': [ |
| 438 | {'attachment_id': uuids.attachment_id}]}} |
| 439 | show_volume = mock.MagicMock(side_effect=[ |
| 440 | vol_attached, vol_attached, vol_detached]) |
| 441 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 442 | build_interval=1, |
| 443 | build_timeout=5, |
| 444 | show_volume=show_volume) |
| 445 | self.patch('time.time') |
| 446 | self.patch('time.sleep') |
| 447 | waiters.wait_for_volume_attachment_remove(client, uuids.volume_id, |
| 448 | uuids.attachment_id) |
| 449 | # Assert that show volume is called until the attachment is removed. |
Peter Penchev | dc4ceae | 2020-09-09 00:47:50 +0300 | [diff] [blame] | 450 | show_volume.assert_has_calls([mock.call(uuids.volume_id), |
| 451 | mock.call(uuids.volume_id), |
| 452 | mock.call(uuids.volume_id)]) |
Lee Yarwood | c1b2a4a | 2020-01-08 17:02:49 +0000 | [diff] [blame] | 453 | |
| 454 | def test_wait_for_volume_attachment_timeout(self): |
| 455 | show_volume = mock.MagicMock(return_value={ |
| 456 | 'volume': {'attachments': [ |
| 457 | {'attachment_id': uuids.attachment_id}]}}) |
| 458 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 459 | build_interval=1, |
| 460 | build_timeout=1, |
| 461 | show_volume=show_volume) |
| 462 | self.patch('time.time', side_effect=[0., client.build_timeout + 1.]) |
| 463 | self.patch('time.sleep') |
| 464 | # Assert that a timeout is raised if the attachment remains. |
| 465 | self.assertRaises(lib_exc.TimeoutException, |
| 466 | waiters.wait_for_volume_attachment_remove, |
| 467 | client, uuids.volume_id, uuids.attachment_id) |
| 468 | |
| 469 | def test_wait_for_volume_attachment_not_present(self): |
| 470 | show_volume = mock.MagicMock(return_value={ |
| 471 | 'volume': {'attachments': []}}) |
| 472 | client = mock.Mock(spec=volumes_client.VolumesClient, |
| 473 | build_interval=1, |
| 474 | build_timeout=1, |
| 475 | show_volume=show_volume) |
| 476 | self.patch('time.time', side_effect=[0., client.build_timeout + 1.]) |
| 477 | self.patch('time.sleep') |
| 478 | waiters.wait_for_volume_attachment_remove(client, uuids.volume_id, |
| 479 | uuids.attachment_id) |
| 480 | # Assert that show volume is only called once before we return |
| 481 | show_volume.assert_called_once_with(uuids.volume_id) |
Balazs Gibizer | 2e515fe | 2020-12-07 15:10:11 +0100 | [diff] [blame] | 482 | |
| 483 | def test_wait_for_volume_attachment_remove_from_server(self): |
| 484 | volume_attached = { |
| 485 | "volumeAttachments": [{"volumeId": uuids.volume_id}]} |
| 486 | volume_not_attached = {"volumeAttachments": []} |
| 487 | mock_list_volume_attachments = mock.Mock( |
| 488 | side_effect=[volume_attached, volume_not_attached]) |
| 489 | mock_client = mock.Mock( |
| 490 | spec=servers_client.ServersClient, |
| 491 | build_interval=1, |
| 492 | build_timeout=1, |
| 493 | list_volume_attachments=mock_list_volume_attachments) |
| 494 | self.patch( |
| 495 | 'time.time', |
| 496 | side_effect=[0., 0.5, mock_client.build_timeout + 1.]) |
| 497 | self.patch('time.sleep') |
| 498 | |
| 499 | waiters.wait_for_volume_attachment_remove_from_server( |
| 500 | mock_client, uuids.server_id, uuids.volume_id) |
| 501 | |
| 502 | # Assert that list_volume_attachments is called until the attachment is |
| 503 | # removed. |
| 504 | mock_list_volume_attachments.assert_has_calls([ |
| 505 | mock.call(uuids.server_id), |
| 506 | mock.call(uuids.server_id)]) |
| 507 | |
| 508 | def test_wait_for_volume_attachment_remove_from_server_timeout(self): |
| 509 | volume_attached = { |
| 510 | "volumeAttachments": [{"volumeId": uuids.volume_id}]} |
| 511 | mock_list_volume_attachments = mock.Mock( |
| 512 | side_effect=[volume_attached, volume_attached]) |
Lee Yarwood | 1bd6059 | 2021-06-04 10:18:35 +0100 | [diff] [blame] | 513 | mock_get_console_output = mock.Mock( |
| 514 | return_value={'output': 'output'}) |
Balazs Gibizer | 2e515fe | 2020-12-07 15:10:11 +0100 | [diff] [blame] | 515 | mock_client = mock.Mock( |
| 516 | spec=servers_client.ServersClient, |
| 517 | build_interval=1, |
| 518 | build_timeout=1, |
Lee Yarwood | 1bd6059 | 2021-06-04 10:18:35 +0100 | [diff] [blame] | 519 | list_volume_attachments=mock_list_volume_attachments, |
| 520 | get_console_output=mock_get_console_output) |
Balazs Gibizer | 2e515fe | 2020-12-07 15:10:11 +0100 | [diff] [blame] | 521 | self.patch( |
| 522 | 'time.time', |
| 523 | side_effect=[0., 0.5, mock_client.build_timeout + 1.]) |
| 524 | self.patch('time.sleep') |
| 525 | |
| 526 | self.assertRaises( |
| 527 | lib_exc.TimeoutException, |
| 528 | waiters.wait_for_volume_attachment_remove_from_server, |
| 529 | mock_client, uuids.server_id, uuids.volume_id) |
| 530 | |
| 531 | # Assert that list_volume_attachments is called until the attachment is |
| 532 | # removed. |
| 533 | mock_list_volume_attachments.assert_has_calls([ |
| 534 | mock.call(uuids.server_id), |
| 535 | mock.call(uuids.server_id)]) |
Lee Yarwood | 1bd6059 | 2021-06-04 10:18:35 +0100 | [diff] [blame] | 536 | |
| 537 | # Assert that we fetch console output |
| 538 | mock_get_console_output.assert_called_once_with(uuids.server_id) |
| 539 | |
| 540 | def test_wait_for_volume_attachment_remove_from_server_not_found(self): |
| 541 | mock_list_volume_attachments = mock.Mock( |
| 542 | side_effect=lib_exc.NotFound) |
| 543 | mock_client = mock.Mock( |
| 544 | spec=servers_client.ServersClient, |
| 545 | list_volume_attachments=mock_list_volume_attachments) |
| 546 | |
| 547 | # Assert that nothing is raised when lib_exc_NotFound is raised |
| 548 | # by the client call to list_volume_attachments |
| 549 | waiters.wait_for_volume_attachment_remove_from_server( |
| 550 | mock_client, mock.sentinel.server_id, mock.sentinel.volume_id) |
| 551 | |
| 552 | # Assert that list_volume_attachments was actually called |
| 553 | mock_list_volume_attachments.assert_called_once_with( |
| 554 | mock.sentinel.server_id) |
Artom Lifshitz | 8a959ea | 2021-09-27 12:09:12 -0400 | [diff] [blame] | 555 | |
| 556 | |
| 557 | class TestServerFloatingIPWaiters(base.TestCase): |
| 558 | |
| 559 | def test_wait_for_server_floating_ip_associate_timeout(self): |
| 560 | mock_server = {'server': {'id': 'fake_uuid', 'addresses': {}}} |
| 561 | mock_client = mock.Mock( |
| 562 | spec=servers_client.ServersClient, |
| 563 | build_timeout=1, build_interval=1, |
| 564 | show_server=lambda id: mock_server) |
| 565 | |
| 566 | fake_server = {'id': 'fake-uuid'} |
| 567 | fake_fip = {'floating_ip_address': 'fake_address'} |
| 568 | self.assertRaises( |
| 569 | lib_exc.TimeoutException, |
| 570 | waiters.wait_for_server_floating_ip, mock_client, fake_server, |
| 571 | fake_fip) |
| 572 | |
| 573 | def test_wait_for_server_floating_ip_disassociate_timeout(self): |
| 574 | mock_addresses = {'shared': [{'OS-EXT-IPS:type': 'floating', |
| 575 | 'addr': 'fake_address'}]} |
| 576 | mock_server = {'server': {'id': 'fake_uuid', |
| 577 | 'addresses': mock_addresses}} |
| 578 | mock_client = mock.Mock( |
| 579 | spec=servers_client.ServersClient, |
| 580 | build_timeout=1, build_interval=1, |
| 581 | show_server=lambda id: mock_server) |
| 582 | |
| 583 | fake_server = {'id': 'fake-uuid'} |
| 584 | fake_fip = {'floating_ip_address': 'fake_address'} |
| 585 | self.assertRaises( |
| 586 | lib_exc.TimeoutException, |
| 587 | waiters.wait_for_server_floating_ip, mock_client, fake_server, |
| 588 | fake_fip, wait_for_disassociate=True) |