Add waiters to OSC share create/delete/resize

This patch adds a '--wait' argument to the following commands:
openstack share create
openstack share delete
openstack share resize

When passing that flag, the command will return
only after the action has been performed. For share create and
share reszise, the command will return after the share reaches
'available' state. For deleting a share, the command will return
only after the share has been deleted.

Change-Id: I8d6ddb1eeba97313fd58f1f6d205906b7611af3a
Partially-implements: bp add-waiters
This commit is contained in:
Maari Tamm 2020-10-04 20:05:32 +00:00
parent f98d4fa7d3
commit 78981e768c
2 changed files with 211 additions and 2 deletions

View File

@ -172,6 +172,12 @@ class CreateShare(command.ShowOne):
help=_('Optional share group name or ID in which to create '
'the share. (Default=None).')
)
parser.add_argument(
'--wait',
action='store_true',
default=False,
help=_('Wait for share creation')
)
return parser
def take_action(self, parsed_args):
@ -218,6 +224,17 @@ class CreateShare(command.ShowOne):
share = share_client.shares.create(**body)
if parsed_args.wait:
if not oscutils.wait_for_status(
status_f=share_client.shares.get,
res_id=share.id,
success_status=['available']
):
LOG.error(_("ERROR: Share is in error state."))
share = apiutils.find_resource(share_client.shares,
share.id)
printable_share = share._info
printable_share.pop('links', None)
printable_share.pop('shares_type', None)
@ -251,6 +268,12 @@ class DeleteShare(command.Command):
help=_("Attempt forced removal of share(s), regardless of state "
"(defaults to False)")
)
parser.add_argument(
"--wait",
action='store_true',
default=False,
help=_("Wait for share deletion")
)
return parser
def take_action(self, parsed_args):
@ -269,6 +292,12 @@ class DeleteShare(command.Command):
else:
share_client.shares.delete(share_obj,
share_group_id)
if parsed_args.wait:
if not oscutils.wait_for_delete(
manager=share_client.shares,
res_id=share_obj.id):
result += 1
except Exception as exc:
result += 1
LOG.error(_("Failed to delete share with "
@ -706,6 +735,12 @@ class ResizeShare(command.Command):
type=int,
help=_('New size of share, in GiBs')
)
parser.add_argument(
'--wait',
action='store_true',
default=False,
help=_('Wait for share resize')
)
return parser
def take_action(self, parsed_args):
@ -733,3 +768,11 @@ class ResizeShare(command.Command):
raise exceptions.CommandError(_(
"Share size is already at %s GiBs" % new_size
))
if parsed_args.wait:
if not oscutils.wait_for_status(
status_f=share_client.shares.get,
res_id=share.id,
success_status=['available']
):
raise exceptions.CommandError(_(
"Share not available after resize attempt."))

View File

@ -55,9 +55,13 @@ class TestShareCreate(TestShare):
def setUp(self):
super(TestShareCreate, self).setUp()
self.new_share = manila_fakes.FakeShare.create_one_share()
self.new_share = manila_fakes.FakeShare.create_one_share(
attrs={'status': 'available'}
)
self.shares_mock.create.return_value = self.new_share
self.shares_mock.get.return_value = self.new_share
# Get the command object to test
self.cmd = osc_shares.CreateShare(self.app, None)
@ -146,6 +150,81 @@ class TestShareCreate(TestShare):
# we implement snapshot support in OSC
# def test_share_create_with_snapshot(self):
def test_share_create_wait(self):
arglist = [
self.new_share.share_proto,
str(self.new_share.size),
'--wait'
]
verifylist = [
('share_proto', self.new_share.share_proto),
('size', self.new_share.size),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.shares_mock.create.assert_called_with(
availability_zone=None,
description=None,
is_public=False,
metadata={},
name=None,
share_group_id=None,
share_network=None,
share_proto=self.new_share.share_proto,
share_type=None,
size=self.new_share.size,
snapshot_id=None
)
self.shares_mock.get.assert_called_with(self.new_share.id)
self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.datalist, data)
@mock.patch('manilaclient.osc.v2.share.LOG')
def test_share_create_wait_error(self, mock_logger):
arglist = [
self.new_share.share_proto,
str(self.new_share.size),
'--wait'
]
verifylist = [
('share_proto', self.new_share.share_proto),
('size', self.new_share.size),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('osc_lib.utils.wait_for_status', return_value=False):
columns, data = self.cmd.take_action(parsed_args)
self.shares_mock.create.assert_called_with(
availability_zone=None,
description=None,
is_public=False,
metadata={},
name=None,
share_group_id=None,
share_network=None,
share_proto=self.new_share.share_proto,
share_type=None,
size=self.new_share.size,
snapshot_id=None
)
mock_logger.error.assert_called_with(
"ERROR: Share is in error state.")
self.shares_mock.get.assert_called_with(self.new_share.id)
self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.datalist, data)
class TestShareDelete(TestShare):
@ -246,6 +325,51 @@ class TestShareDelete(TestShare):
self.assertRaises(osc_utils.ParserException,
self.check_parser, self.cmd, arglist, verifylist)
def test_share_delete_wait(self):
shares = self.setup_shares_mock(count=1)
arglist = [
shares[0].name,
'--wait'
]
verifylist = [
("force", False),
("share_group", None),
('shares', [shares[0].name]),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('osc_lib.utils.wait_for_delete', return_value=True):
result = self.cmd.take_action(parsed_args)
self.shares_mock.delete.assert_called_with(shares[0], None)
self.shares_mock.get.assert_called_with(shares[0].name)
self.assertIsNone(result)
def test_share_delete_wait_error(self):
shares = self.setup_shares_mock(count=1)
arglist = [
shares[0].name,
'--wait'
]
verifylist = [
("force", False),
("share_group", None),
('shares', [shares[0].name]),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('osc_lib.utils.wait_for_delete', return_value=False):
self.assertRaises(
osc_exceptions.CommandError,
self.cmd.take_action,
parsed_args
)
class TestShareList(TestShare):
@ -1103,7 +1227,8 @@ class TestResizeShare(TestShare):
super(TestResizeShare, self).setUp()
self._share = manila_fakes.FakeShare.create_one_share(
attrs={'size': 2})
attrs={'size': 2,
'status': 'available'})
self.shares_mock.get.return_value = self._share
# Get the command objects to test
@ -1205,3 +1330,44 @@ class TestResizeShare(TestShare):
self.assertRaises(osc_utils.ParserException,
self.check_parser, self.cmd, arglist, verifylist)
def test_share_resize_wait(self):
arglist = [
self._share.id,
'3',
'--wait'
]
verifylist = [
('share', self._share.id),
('new_size', 3),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.shares_mock.extend.assert_called_with(
self._share,
3
)
self.shares_mock.get.assert_called_with(self._share.id)
def test_share_resize_wait_error(self):
arglist = [
self._share.id,
'3',
'--wait'
]
verifylist = [
('share', self._share.id),
('new_size', 3),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('osc_lib.utils.wait_for_status', return_value=False):
self.assertRaises(
osc_exceptions.CommandError,
self.cmd.take_action,
parsed_args
)