Fix output from cluster/node delete

As requested by some users, we are supposed to output the action IDs
spawned at server side when deleting cluster or node.

Change-Id: Id339affb413f81aa12cf00d86122d00e2302e471
Closes-Bug: #1564711
This commit is contained in:
tengqm 2016-08-30 21:47:33 -04:00
parent 04a28f59d5
commit 6e41ab2265
7 changed files with 59 additions and 78 deletions

View File

@ -187,6 +187,14 @@ def print_dict(d, formatters=None):
print(encodeutils.safe_encode(content))
def print_action_result(rid, res):
if res[0] == "OK":
output = _("accepted by action %s") % res[1]
else:
output = _("failed due to '%s'") % res[1]
print(_(" %(cid)s: %(output)s") % {"cid": rid, "output": output})
def format_parameters(params, parse_semicolon=True):
"""Reformat parameters into dict of format expected by the API."""
if not params:

View File

@ -330,7 +330,8 @@ class TestClusterDelete(TestCluster):
def setUp(self):
super(TestClusterDelete, self).setUp()
self.cmd = osc_cluster.DeleteCluster(self.app, None)
self.mock_client.delete_cluster = mock.Mock()
mock_cluster = mock.Mock(location='abc/fake_action_id')
self.mock_client.delete_cluster = mock.Mock(return_value=mock_cluster)
def test_cluster_delete(self):
arglist = ['cluster1', 'cluster2', 'cluster3']
@ -354,10 +355,12 @@ class TestClusterDelete(TestCluster):
arglist = ['my_cluster']
self.mock_client.delete_cluster.side_effect = sdk_exc.ResourceNotFound
parsed_args = self.check_parser(self.cmd, arglist, [])
error = self.assertRaises(exc.CommandError, self.cmd.take_action,
parsed_args)
self.assertIn('Failed to delete 1 of the 1 specified cluster(s).',
str(error))
self.cmd.take_action(parsed_args)
self.mock_client.delete_cluster.assert_has_calls(
[mock.call('my_cluster', False)]
)
def test_cluster_delete_one_found_one_not_found(self):
arglist = ['cluster1', 'cluster2']
@ -365,13 +368,12 @@ class TestClusterDelete(TestCluster):
[None, sdk_exc.ResourceNotFound]
)
parsed_args = self.check_parser(self.cmd, arglist, [])
error = self.assertRaises(exc.CommandError,
self.cmd.take_action, parsed_args)
self.cmd.take_action(parsed_args)
self.mock_client.delete_cluster.assert_has_calls(
[mock.call('cluster1', False), mock.call('cluster2', False)]
)
self.assertEqual('Failed to delete 1 of the 2 specified cluster(s).',
str(error))
@mock.patch('sys.stdin', spec=six.StringIO)
def test_cluster_delete_prompt_yes(self, mock_stdin):

View File

@ -335,7 +335,8 @@ class TestNodeDelete(TestNode):
def setUp(self):
super(TestNodeDelete, self).setUp()
self.cmd = osc_node.DeleteNode(self.app, None)
self.mock_client.delete_node = mock.Mock()
mock_node = mock.Mock(location='loc/fake_action_id')
self.mock_client.delete_node = mock.Mock(return_value=mock_node)
def test_node_delete(self):
arglist = ['node1', 'node2', 'node3']
@ -359,10 +360,12 @@ class TestNodeDelete(TestNode):
arglist = ['my_node']
self.mock_client.delete_node.side_effect = sdk_exc.ResourceNotFound
parsed_args = self.check_parser(self.cmd, arglist, [])
error = self.assertRaises(exc.CommandError, self.cmd.take_action,
parsed_args)
self.assertIn('Failed to delete 1 of the 1 specified node(s).',
str(error))
self.cmd.take_action(parsed_args)
self.mock_client.delete_node.assert_has_calls(
[mock.call('my_node', False)]
)
def test_node_delete_one_found_one_not_found(self):
arglist = ['node1', 'node2']
@ -370,13 +373,12 @@ class TestNodeDelete(TestNode):
[None, sdk_exc.ResourceNotFound]
)
parsed_args = self.check_parser(self.cmd, arglist, [])
error = self.assertRaises(exc.CommandError,
self.cmd.take_action, parsed_args)
self.cmd.take_action(parsed_args)
self.mock_client.delete_node.assert_has_calls(
[mock.call('node1', False), mock.call('node2', False)]
)
self.assertEqual('Failed to delete 1 of the 2 specified node(s).',
str(error))
@mock.patch('sys.stdin', spec=six.StringIO)
def test_node_delete_prompt_yes(self, mock_stdin):

View File

@ -780,17 +780,6 @@ class ShellTest(testtools.TestCase):
sh.do_cluster_delete(service, args)
service.delete_cluster.assert_called_once_with('CID', False)
def test_do_cluster_delete_not_found(self):
service = mock.Mock()
args = {'id': ['cluster_id']}
args = self._make_args(args)
service.delete_cluster.side_effect = oexc.ResourceNotFound
ex = self.assertRaises(exc.CommandError,
sh.do_cluster_delete, service, args)
msg = _('Failed to delete some of the specified clusters.')
self.assertEqual(msg, six.text_type(ex))
@mock.patch('subprocess.Popen')
def test__run_script(self, mock_proc):
x_proc = mock.Mock(returncode=0)
@ -1485,17 +1474,6 @@ class ShellTest(testtools.TestCase):
service.delete_node.assert_called_once_with('node1', False)
def test_do_node_delete_not_found(self):
service = mock.Mock()
ex = oexc.ResourceNotFound
service.delete_node.side_effect = ex
args = self._make_args({'id': ['node1']})
ex = self.assertRaises(exc.CommandError,
sh.do_node_delete, service, args)
msg = _('Failed to delete some of the specified nodes.')
self.assertEqual(msg, six.text_type(ex))
def test_do_node_check(self):
service = mock.Mock()
args = self._make_args({'id': ['node1']})

View File

@ -311,20 +311,16 @@ class DeleteCluster(command.Command):
self.log.info(_LI('Ctrl-d detected'))
return
failure_count = 0
result = {}
for cid in parsed_args.cluster:
try:
senlin_client.delete_cluster(cid, False)
cluster = senlin_client.delete_cluster(cid, False)
result[cid] = ('OK', cluster.location.split('/')[-1])
except Exception as ex:
failure_count += 1
print(ex)
if failure_count:
raise exc.CommandError(_('Failed to delete %(count)s of the '
'%(total)s specified cluster(s).') %
{'count': failure_count,
'total': len(parsed_args.cluster)})
print('Request accepted')
result[cid] = ('ERROR', six.text_type(ex))
for rid, res in result.items():
senlin_utils.print_action_result(rid, res)
class ResizeCluster(command.Command):

View File

@ -19,6 +19,7 @@ from openstack import exceptions as sdk_exc
from osc_lib.command import command
from osc_lib import exceptions as exc
from osc_lib import utils
import six
from senlinclient.common.i18n import _
from senlinclient.common.i18n import _LI
@ -314,20 +315,16 @@ class DeleteNode(command.Command):
self.log.info(_LI('Ctrl-d detected'))
return
failure_count = 0
result = {}
for nid in parsed_args.node:
try:
senlin_client.delete_node(nid, False)
node = senlin_client.delete_node(nid, False)
result[nid] = ('OK', node.location.split('/')[-1])
except Exception as ex:
failure_count += 1
print(ex)
if failure_count:
raise exc.CommandError(_('Failed to delete %(count)s of the '
'%(total)s specified node(s).') %
{'count': failure_count,
'total': len(parsed_args.node)})
print('Request accepted')
result[nid] = ('ERROR', six.text_type(ex))
for rid, res in result.items():
senlin_utils.print_action_result(rid, res)
class CheckNode(command.Command):

View File

@ -582,18 +582,17 @@ def do_cluster_collect(service, args):
def do_cluster_delete(service, args):
"""Delete the cluster(s)."""
show_deprecated('senlin cluster-delete', 'openstack cluster delete')
failure_count = 0
result = {}
for cid in args.id:
try:
service.delete_cluster(cid, False)
cluster = service.delete_cluster(cid, False)
result[cid] = ('OK', cluster.location.split('/')[-1])
except Exception as ex:
failure_count += 1
print(ex)
if failure_count > 0:
msg = _('Failed to delete some of the specified clusters.')
raise exc.CommandError(msg)
print('Request accepted')
result[cid] = ('ERROR', six.text_type(ex))
for rid, res in result.items():
utils.print_action_result(rid, res)
def _run_script(node_id, addr, net, addr_type, port, user, ipv6, identity_file,
@ -1208,18 +1207,17 @@ def do_node_show(service, args):
def do_node_delete(service, args):
"""Delete the node(s)."""
show_deprecated('senlin node-delete', 'openstack cluster node delete')
failure_count = 0
result = {}
for nid in args.id:
try:
service.delete_node(nid, False)
node = service.delete_node(nid, False)
result[nid] = ('OK', node.location.split('/')[-1])
except Exception as ex:
failure_count += 1
print(ex)
if failure_count > 0:
msg = _('Failed to delete some of the specified nodes.')
raise exc.CommandError(msg)
print('Request accepted')
result[nid] = ('ERROR', six.text_type(ex))
for rid, res in result.items():
utils.print_action_result(rid, res)
@utils.arg('-n', '--name', metavar='<NAME>',