Skip to content

Commit 2b073c2

Browse files
committed
Add 'server unshelve --wait' option
This was recently added to the 'server shelve' command. Add it now for the 'unshelve' command. Change-Id: I633dd85b60cf70b4f8610f414d82669dd6a53111 Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
1 parent 64c2a1a commit 2b073c2

3 files changed

Lines changed: 98 additions & 45 deletions

File tree

openstackclient/compute/v2/server.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4131,25 +4131,54 @@ def get_parser(self, prog_name):
41314131
'SHELVED_OFFLOADED server (supported by '
41324132
'--os-compute-api-version 2.77 or above)'),
41334133
)
4134+
parser.add_argument(
4135+
'--wait',
4136+
action='store_true',
4137+
default=False,
4138+
help=_('Wait for unshelve operation to complete'),
4139+
)
41344140
return parser
41354141

41364142
def take_action(self, parsed_args):
4143+
4144+
def _show_progress(progress):
4145+
if progress:
4146+
self.app.stdout.write('\rProgress: %s' % progress)
4147+
self.app.stdout.flush()
4148+
41374149
compute_client = self.app.client_manager.compute
4138-
support_az = compute_client.api_version >= api_versions.APIVersion(
4139-
'2.77')
4140-
if not support_az and parsed_args.availability_zone:
4141-
msg = _("--os-compute-api-version 2.77 or greater is required "
4142-
"to support the '--availability-zone' option.")
4143-
raise exceptions.CommandError(msg)
4150+
kwargs = {}
4151+
4152+
if parsed_args.availability_zone:
4153+
if compute_client.api_version < api_versions.APIVersion('2.77'):
4154+
msg = _(
4155+
'--os-compute-api-version 2.77 or greater is required '
4156+
'to support the --availability-zone option'
4157+
)
4158+
raise exceptions.CommandError(msg)
4159+
4160+
kwargs['availability_zone'] = parsed_args.availability_zone
41444161

41454162
for server in parsed_args.server:
4146-
if support_az:
4147-
utils.find_resource(
4148-
compute_client.servers,
4149-
server
4150-
).unshelve(availability_zone=parsed_args.availability_zone)
4151-
else:
4152-
utils.find_resource(
4153-
compute_client.servers,
4154-
server,
4155-
).unshelve()
4163+
server_obj = utils.find_resource(
4164+
compute_client.servers,
4165+
server,
4166+
)
4167+
4168+
if server_obj.status.lower() not in (
4169+
'shelved', 'shelved_offloaded',
4170+
):
4171+
continue
4172+
4173+
server_obj.unshelve(**kwargs)
4174+
4175+
if parsed_args.wait:
4176+
if not utils.wait_for_status(
4177+
compute_client.servers.get, server_obj.id,
4178+
success_status=('active', 'shutoff'),
4179+
callback=_show_progress,
4180+
):
4181+
LOG.error(_('Error unshelving server %s'), server_obj.id)
4182+
self.app.stdout.write(
4183+
_('Error unshelving server: %s\n') % server_obj.id)
4184+
raise SystemExit

openstackclient/tests/unit/compute/v2/test_server.py

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6969,62 +6969,84 @@ def setUp(self):
69696969
self.methods = {
69706970
'unshelve': None,
69716971
}
6972+
self.attrs = {
6973+
'status': 'SHELVED',
6974+
}
69726975

69736976
def test_unshelve_one_server(self):
69746977
self.run_method_with_servers('unshelve', 1)
69756978

69766979
def test_unshelve_multi_servers(self):
69776980
self.run_method_with_servers('unshelve', 3)
69786981

6979-
def test_unshelve_server_with_specified_az(self):
6980-
server = compute_fakes.FakeServer.create_one_server()
6982+
def test_unshelve_with_specified_az(self):
6983+
self.app.client_manager.compute.api_version = \
6984+
api_versions.APIVersion('2.77')
6985+
6986+
server = compute_fakes.FakeServer.create_one_server(
6987+
attrs=self.attrs, methods=self.methods)
6988+
self.servers_mock.get.return_value = server
69816989
arglist = [
6982-
server.id,
69836990
'--availability-zone', "foo-az",
6991+
server.id,
69846992
]
69856993
verifylist = [
69866994
('availability_zone', "foo-az"),
69876995
('server', [server.id])
69886996
]
69896997
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
6990-
ex = self.assertRaises(exceptions.CommandError,
6991-
self.cmd.take_action,
6992-
parsed_args)
6993-
self.assertIn(
6994-
'--os-compute-api-version 2.77 or greater is required', str(ex))
6995-
69966998

6997-
class TestServerUnshelveV277(TestServerUnshelve):
6998-
6999-
def setUp(self):
7000-
super(TestServerUnshelveV277, self).setUp()
7001-
7002-
self.server = compute_fakes.FakeServer.create_one_server(
7003-
methods=self.methods)
7004-
7005-
# This is the return value for utils.find_resource()
7006-
self.servers_mock.get.return_value = self.server
6999+
self.cmd.take_action(parsed_args)
70077000

7008-
# Get the command object to test
7009-
self.cmd = server.UnshelveServer(self.app, None)
7001+
self.servers_mock.get.assert_called_with(server.id)
7002+
server.unshelve.assert_called_with(availability_zone="foo-az")
70107003

7011-
def test_specified_az_to_unshelve_with_v277(self):
7012-
self.app.client_manager.compute.api_version = api_versions.APIVersion(
7013-
'2.77')
7004+
def test_unshelve_with_specified_az_pre_v277(self):
7005+
self.app.client_manager.compute.api_version = \
7006+
api_versions.APIVersion('2.76')
70147007

7008+
server = compute_fakes.FakeServer.create_one_server(
7009+
attrs=self.attrs, methods=self.methods)
70157010
arglist = [
7011+
server.id,
70167012
'--availability-zone', "foo-az",
7017-
self.server.id,
70187013
]
70197014
verifylist = [
70207015
('availability_zone', "foo-az"),
7021-
('server', [self.server.id])
7016+
('server', [server.id])
70227017
]
70237018
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
7019+
ex = self.assertRaises(
7020+
exceptions.CommandError,
7021+
self.cmd.take_action,
7022+
parsed_args)
7023+
self.assertIn(
7024+
'--os-compute-api-version 2.77 or greater is required', str(ex))
70247025

7025-
self.cmd.take_action(parsed_args)
7026-
self.servers_mock.get.assert_called_with(self.server.id)
7027-
self.server.unshelve.assert_called_with(availability_zone="foo-az")
7026+
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
7027+
def test_unshelve_with_wait(self, mock_wait_for_status):
7028+
server = compute_fakes.FakeServer.create_one_server(
7029+
attrs=self.attrs, methods=self.methods)
7030+
self.servers_mock.get.return_value = server
7031+
7032+
arglist = ['--wait', server.name]
7033+
verifylist = [
7034+
('server', [server.name]),
7035+
('wait', True),
7036+
]
7037+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
7038+
7039+
result = self.cmd.take_action(parsed_args)
7040+
self.assertIsNone(result)
7041+
7042+
self.servers_mock.get.assert_called_once_with(server.name)
7043+
server.unshelve.assert_called_once_with()
7044+
mock_wait_for_status.assert_called_once_with(
7045+
self.servers_mock.get,
7046+
server.id,
7047+
callback=mock.ANY,
7048+
success_status=('active', 'shutoff'),
7049+
)
70287050

70297051

70307052
class TestServerGeneral(TestServer):

releasenotes/notes/add-shelve-offload-wait-d0a5c8ba92586f72.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ features:
66
server in environments where automatic offloading is not configured, while
77
``--wait`` allows users to wait for the shelve and/or shelve offload
88
operations to complete.
9+
- |
10+
Add support ``--wait`` option for ``server shelve``.

0 commit comments

Comments
 (0)