evacuate: respect original SHUTOFF state in --wait completion

When running `openstack server evacuate --wait`, the command would hang
indefinitely if the instance was originally in SHUTOFF state, because
only “ACTIVE” was treated as a successful completion. We now capture
the server’s status before evacuation and dynamically include
“SHUTOFF” in the `success_status` list if the instance was already
shut off. This ensures that a shutoff instance is accepted as a valid
completion without requiring manual intervention.

Unit tests have been added and updated to cover both:
- pre-evacuation ACTIVE → success_status=['active']
- pre-evacuation SHUTOFF → success_status=['active','shutoff']

Closes-Bug: #2103426
Change-Id: I86ad1cd173a144b16fde1dbac87819fab2d7a50a
This commit is contained in:
waf
2025-05-21 16:52:24 +09:00
parent a49a290a2b
commit 3909e93301
2 changed files with 34 additions and 0 deletions

View File

@@ -3879,9 +3879,15 @@ host."""
compute_client.evacuate_server(server, **kwargs)
if parsed_args.wait:
orig_status = server.status
success = ['ACTIVE']
if orig_status == 'SHUTOFF':
success.append('SHUTOFF')
if utils.wait_for_status(
compute_client.get_server,
server.id,
success_status=success,
callback=_show_progress,
):
self.app.stdout.write(_('Complete\n'))

View File

@@ -7000,6 +7000,7 @@ class TestServerEvacuate(TestServer):
'image': self.image,
'networks': {},
'adminPass': 'passw0rd',
'status': 'ACTIVE',
}
self.server = compute_fakes.create_one_server(attrs=attrs)
attrs['id'] = self.server.id
@@ -7137,6 +7138,33 @@ class TestServerEvacuate(TestServer):
mock_wait_for_status.assert_called_once_with(
self.compute_client.get_server,
self.server.id,
success_status=['ACTIVE'],
callback=mock.ANY,
)
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
def test_evacuate_with_wait_ok_shutoff(self, mock_wait_for_status):
self.server.status = 'SHUTOFF'
self.compute_client.get_server.return_value = self.server
args = [
self.server.id,
'--wait',
]
verify_args = [
('server', self.server.id),
('wait', True),
]
evac_args = {
'host': None,
'on_shared_storage': False,
'admin_pass': None,
}
self._test_evacuate(args, verify_args, evac_args)
mock_wait_for_status.assert_called_once_with(
self.compute_client.get_server,
self.server.id,
success_status=['ACTIVE', 'SHUTOFF'],
callback=mock.ANY,
)