Add a --wait flag to share manage/unmanage
This option enables "manage" and "unmanage" commands to wait until the action has completed. Partially-implements: bp add-wait-to-async-commands Closes-Bug: #1898309 Change-Id: I03b87f2f27b045e0a83c3a25cc482901bacffa15
This commit is contained in:
parent
f9aee522ef
commit
36aee019cd
@ -691,7 +691,8 @@ class ShellTest(test_utils.TestCase):
|
|||||||
'share_type': None,
|
'share_type': None,
|
||||||
'share_server_id': None,
|
'share_server_id': None,
|
||||||
}},
|
}},
|
||||||
{'cmd_args': '--public',
|
{'cmd_args': '--public'
|
||||||
|
' --wait',
|
||||||
'valid_params': {
|
'valid_params': {
|
||||||
'driver_options': {},
|
'driver_options': {},
|
||||||
'share_type': None,
|
'share_type': None,
|
||||||
@ -710,7 +711,8 @@ class ShellTest(test_utils.TestCase):
|
|||||||
'version': '--os-share-api-version 2.8',
|
'version': '--os-share-api-version 2.8',
|
||||||
},
|
},
|
||||||
{'cmd_args': '--driver_options opt1=opt1 opt2=opt2'
|
{'cmd_args': '--driver_options opt1=opt1 opt2=opt2'
|
||||||
' --share_type fake_share_type',
|
' --share_type fake_share_type'
|
||||||
|
' --wait',
|
||||||
'valid_params': {
|
'valid_params': {
|
||||||
'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'},
|
'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'},
|
||||||
'share_type': 'fake_share_type',
|
'share_type': 'fake_share_type',
|
||||||
@ -730,7 +732,8 @@ class ShellTest(test_utils.TestCase):
|
|||||||
},
|
},
|
||||||
{'cmd_args': '--driver_options opt1=opt1 opt2=opt2'
|
{'cmd_args': '--driver_options opt1=opt1 opt2=opt2'
|
||||||
' --share_type fake_share_type'
|
' --share_type fake_share_type'
|
||||||
' --share_server_id fake_server',
|
' --share_server_id fake_server'
|
||||||
|
' --wait',
|
||||||
'valid_params': {
|
'valid_params': {
|
||||||
'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'},
|
'driver_options': {'opt1': 'opt1', 'opt2': 'opt2'},
|
||||||
'share_type': 'fake_share_type',
|
'share_type': 'fake_share_type',
|
||||||
@ -740,6 +743,16 @@ class ShellTest(test_utils.TestCase):
|
|||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_manage(self, cmd_args, valid_params, is_public=False,
|
def test_manage(self, cmd_args, valid_params, is_public=False,
|
||||||
version=None):
|
version=None):
|
||||||
|
share_to_be_managed = shares.Share(
|
||||||
|
'fake_share', {
|
||||||
|
'id': 'fake'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.mock_object(
|
||||||
|
shell_v2, '_wait_for_resource_status',
|
||||||
|
mock.Mock(return_value=share_to_be_managed)
|
||||||
|
)
|
||||||
|
|
||||||
if version is not None:
|
if version is not None:
|
||||||
self.run_command(version
|
self.run_command(version
|
||||||
+ ' manage fake_service fake_protocol '
|
+ ' manage fake_service fake_protocol '
|
||||||
@ -761,8 +774,16 @@ class ShellTest(test_utils.TestCase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expected['share'].update(valid_params)
|
expected['share'].update(valid_params)
|
||||||
|
|
||||||
self.assert_called('POST', '/shares/manage', body=expected)
|
self.assert_called('POST', '/shares/manage', body=expected)
|
||||||
|
|
||||||
|
if '--wait' in cmd_args:
|
||||||
|
shell_v2._wait_for_resource_status.assert_called_once_with(
|
||||||
|
self.shell.cs, share_to_be_managed, resource_type='share',
|
||||||
|
expected_status='available')
|
||||||
|
else:
|
||||||
|
shell_v2._wait_for_resource_status.assert_not_called()
|
||||||
|
|
||||||
def test_manage_invalid_param_share_server_id(self):
|
def test_manage_invalid_param_share_server_id(self):
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exceptions.CommandError,
|
exceptions.CommandError,
|
||||||
@ -903,9 +924,40 @@ class ShellTest(test_utils.TestCase):
|
|||||||
expected = {'reset_status': {'status': status}}
|
expected = {'reset_status': {'status': status}}
|
||||||
self.assert_called('POST', '/share-servers/1234/action', body=expected)
|
self.assert_called('POST', '/share-servers/1234/action', body=expected)
|
||||||
|
|
||||||
def test_unmanage(self):
|
@ddt.data('--wait', '')
|
||||||
self.run_command('unmanage 1234')
|
def test_unmanage(self, wait_option):
|
||||||
self.assert_called('POST', '/shares/1234/action')
|
version = api_versions.APIVersion('2.46')
|
||||||
|
api = mock.Mock(api_version=version)
|
||||||
|
manager = shares.ShareManager(api=api)
|
||||||
|
fake_share = shares.Share(
|
||||||
|
manager, {
|
||||||
|
'id': 'xyzzyspoon',
|
||||||
|
'api_version': version,
|
||||||
|
'status': 'available',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
share_not_found_error = ("ERROR: No share with "
|
||||||
|
"a name or ID of '%s' exists.")
|
||||||
|
share_not_found_error = exceptions.CommandError(
|
||||||
|
share_not_found_error % (fake_share.id)
|
||||||
|
)
|
||||||
|
self.mock_object(
|
||||||
|
shell_v2, '_find_share',
|
||||||
|
mock.Mock(side_effect=([fake_share, fake_share, fake_share,
|
||||||
|
share_not_found_error])))
|
||||||
|
self.mock_object(
|
||||||
|
shares.ShareManager, 'get',
|
||||||
|
mock.Mock(return_value=fake_share))
|
||||||
|
|
||||||
|
self.run_command('unmanage %s xyzzyspoon' % wait_option)
|
||||||
|
|
||||||
|
expected_get_share_calls = 4 if wait_option else 1
|
||||||
|
shell_v2._find_share.assert_has_calls(
|
||||||
|
[mock.call(self.shell.cs, fake_share.id)] *
|
||||||
|
expected_get_share_calls
|
||||||
|
)
|
||||||
|
uri = '/shares/%s/action' % fake_share.id
|
||||||
|
api.client.post.assert_called_once_with(uri, body={'unmanage': None})
|
||||||
|
|
||||||
def test_share_server_unmanage(self):
|
def test_share_server_unmanage(self):
|
||||||
self.run_command('share-server-unmanage 1234')
|
self.run_command('share-server-unmanage 1234')
|
||||||
|
@ -79,6 +79,8 @@ def _wait_for_resource_status(cs,
|
|||||||
"state.")
|
"state.")
|
||||||
deleted_message = ("%(resource_type)s %(resource)s has been successfully "
|
deleted_message = ("%(resource_type)s %(resource)s has been successfully "
|
||||||
"deleted.")
|
"deleted.")
|
||||||
|
unmanaged_message = ("%(resource_type)s %(resource)s has been "
|
||||||
|
"successfully unmanaged.")
|
||||||
message_payload = {
|
message_payload = {
|
||||||
'resource_type': resource_type.capitalize(),
|
'resource_type': resource_type.capitalize(),
|
||||||
'resource': resource.id,
|
'resource': resource.id,
|
||||||
@ -94,10 +96,13 @@ def _wait_for_resource_status(cs,
|
|||||||
try:
|
try:
|
||||||
resource = find_resource[resource_type](cs, resource.id)
|
resource = find_resource[resource_type](cs, resource.id)
|
||||||
except exceptions.CommandError as e:
|
except exceptions.CommandError as e:
|
||||||
if (re.search(not_found_regex, str(e), flags=re.IGNORECASE)
|
if (re.search(not_found_regex, str(e), flags=re.IGNORECASE)):
|
||||||
and 'deleted' in expected_status):
|
if 'deleted' in expected_status:
|
||||||
print(deleted_message % message_payload)
|
print(deleted_message % message_payload)
|
||||||
break
|
break
|
||||||
|
if 'unmanaged' in expected_status:
|
||||||
|
print(unmanaged_message % message_payload)
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
@ -1523,6 +1528,10 @@ def do_share_export_location_show(cs, args):
|
|||||||
help="Share server associated with share when using a share type with "
|
help="Share server associated with share when using a share type with "
|
||||||
"'driver_handles_share_servers' extra_spec set to True. Available "
|
"'driver_handles_share_servers' extra_spec set to True. Available "
|
||||||
"only for microversion >= 2.49. (Default=None)")
|
"only for microversion >= 2.49. (Default=None)")
|
||||||
|
@cliutils.arg(
|
||||||
|
'--wait',
|
||||||
|
action='store_true',
|
||||||
|
help='Wait for share management')
|
||||||
def do_manage(cs, args):
|
def do_manage(cs, args):
|
||||||
"""Manage share not handled by Manila (Admin only)."""
|
"""Manage share not handled by Manila (Admin only)."""
|
||||||
driver_options = _extract_key_value_options(args, 'driver_options')
|
driver_options = _extract_key_value_options(args, 'driver_options')
|
||||||
@ -1545,6 +1554,11 @@ def do_manage(cs, args):
|
|||||||
name=args.name, description=args.description,
|
name=args.name, description=args.description,
|
||||||
is_public=args.public)
|
is_public=args.public)
|
||||||
|
|
||||||
|
if args.wait:
|
||||||
|
share = _wait_for_resource_status(
|
||||||
|
cs, share, resource_type='share',
|
||||||
|
expected_status='available'
|
||||||
|
)
|
||||||
_print_share(cs, share)
|
_print_share(cs, share)
|
||||||
|
|
||||||
|
|
||||||
@ -1682,10 +1696,16 @@ def do_snapshot_manage(cs, args):
|
|||||||
'share',
|
'share',
|
||||||
metavar='<share>',
|
metavar='<share>',
|
||||||
help='Name or ID of the share(s).')
|
help='Name or ID of the share(s).')
|
||||||
|
@cliutils.arg(
|
||||||
|
'--wait',
|
||||||
|
action='store_true',
|
||||||
|
help='Wait for share unmanagement')
|
||||||
def do_unmanage(cs, args):
|
def do_unmanage(cs, args):
|
||||||
"""Unmanage share (Admin only)."""
|
"""Unmanage share (Admin only)."""
|
||||||
share_ref = _find_share(cs, args.share)
|
share_ref = _find_share(cs, args.share)
|
||||||
share_ref.unmanage()
|
share_ref.unmanage()
|
||||||
|
if args.wait:
|
||||||
|
_wait_for_share_status(cs, share_ref, expected_status='unmanaged')
|
||||||
|
|
||||||
|
|
||||||
@api_versions.wraps("2.49")
|
@api_versions.wraps("2.49")
|
||||||
@ -1775,7 +1795,6 @@ def do_delete(cs, args):
|
|||||||
"""Remove one or more shares."""
|
"""Remove one or more shares."""
|
||||||
failure_count = 0
|
failure_count = 0
|
||||||
shares_to_delete = []
|
shares_to_delete = []
|
||||||
|
|
||||||
for share in args.share:
|
for share in args.share:
|
||||||
try:
|
try:
|
||||||
share_ref = _find_share(cs, share)
|
share_ref = _find_share(cs, share)
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The commands "manila manage" and "manila unmanage"
|
||||||
|
now accept an optional "--wait" flag that allows
|
||||||
|
users to let the client poll for the completion
|
||||||
|
of the operation.
|
Loading…
x
Reference in New Issue
Block a user