Merge "Add json and yaml formatting to manila-manage"
This commit is contained in:
commit
c8a893eb64
@ -55,9 +55,11 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import yaml
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
from manila.common import config # Need to register global_opts # noqa
|
from manila.common import config # Need to register global_opts # noqa
|
||||||
from manila import context
|
from manila import context
|
||||||
@ -69,6 +71,7 @@ from manila import version
|
|||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
ALLOWED_OUTPUT_FORMATS = ['table', 'json', 'yaml']
|
||||||
HOST_UPDATE_HELP_MSG = ("A fully qualified host string is of the format "
|
HOST_UPDATE_HELP_MSG = ("A fully qualified host string is of the format "
|
||||||
"'HostA@BackendB#PoolC'. Provide only the host name "
|
"'HostA@BackendB#PoolC'. Provide only the host name "
|
||||||
"(ex: 'HostA') to update the hostname part of "
|
"(ex: 'HostA') to update the hostname part of "
|
||||||
@ -78,6 +81,8 @@ HOST_UPDATE_HELP_MSG = ("A fully qualified host string is of the format "
|
|||||||
HOST_UPDATE_CURRENT_HOST_HELP = ("Current share host name. %s" %
|
HOST_UPDATE_CURRENT_HOST_HELP = ("Current share host name. %s" %
|
||||||
HOST_UPDATE_HELP_MSG)
|
HOST_UPDATE_HELP_MSG)
|
||||||
HOST_UPDATE_NEW_HOST_HELP = "New share host name. %s" % HOST_UPDATE_HELP_MSG
|
HOST_UPDATE_NEW_HOST_HELP = "New share host name. %s" % HOST_UPDATE_HELP_MSG
|
||||||
|
LIST_OUTPUT_FORMAT_HELP = ("Format to be used to print the output (table, "
|
||||||
|
"json, yaml). Defaults to 'table'")
|
||||||
SHARE_SERVERS_UPDATE_HELP = ("List of share servers to be updated, separated "
|
SHARE_SERVERS_UPDATE_HELP = ("List of share servers to be updated, separated "
|
||||||
"by commas.")
|
"by commas.")
|
||||||
SHARE_SERVERS_UPDATE_CAPABILITIES_HELP = (
|
SHARE_SERVERS_UPDATE_CAPABILITIES_HELP = (
|
||||||
@ -93,6 +98,37 @@ def args(*args, **kwargs):
|
|||||||
return _decorator
|
return _decorator
|
||||||
|
|
||||||
|
|
||||||
|
class ListCommand(object):
|
||||||
|
|
||||||
|
def list_json(self, resource_name, resource_list):
|
||||||
|
resource_list = {resource_name: resource_list}
|
||||||
|
object_list = jsonutils.dumps(resource_list, indent=4)
|
||||||
|
print(object_list)
|
||||||
|
|
||||||
|
def list_yaml(self, resource_name, resource_list):
|
||||||
|
resource_list = {resource_name: resource_list}
|
||||||
|
data_yaml = yaml.dump(resource_list)
|
||||||
|
print(data_yaml)
|
||||||
|
|
||||||
|
def list_table(self, resource_name, resource_list):
|
||||||
|
print_format = "{0:<16} {1:<36} {2:<16} {3:<10} {4:<5} {5:<10}"
|
||||||
|
print(print_format.format(
|
||||||
|
*[k.capitalize().replace(
|
||||||
|
'_', ' ') for k in resource_list[0].keys()]))
|
||||||
|
for resource in resource_list:
|
||||||
|
# Print is not transforming into a string, so let's ensure it
|
||||||
|
# happens
|
||||||
|
resource['updated_at'] = str(resource['updated_at'])
|
||||||
|
print(print_format.format(*resource.values()))
|
||||||
|
|
||||||
|
def _check_format_output(self, format_output):
|
||||||
|
if format_output not in ALLOWED_OUTPUT_FORMATS:
|
||||||
|
print('Invalid output format specified. Defaulting to table.')
|
||||||
|
return 'table'
|
||||||
|
else:
|
||||||
|
return format_output
|
||||||
|
|
||||||
|
|
||||||
class ShellCommands(object):
|
class ShellCommands(object):
|
||||||
def bpython(self):
|
def bpython(self):
|
||||||
"""Runs a bpython shell.
|
"""Runs a bpython shell.
|
||||||
@ -319,35 +355,35 @@ class GetLogCommands(object):
|
|||||||
print("No manila entries in syslog!")
|
print("No manila entries in syslog!")
|
||||||
|
|
||||||
|
|
||||||
class ServiceCommands(object):
|
class ServiceCommands(ListCommand):
|
||||||
"""Methods for managing services."""
|
"""Methods for managing services."""
|
||||||
def list(self):
|
|
||||||
|
@args('--format_output', required=False, default='table',
|
||||||
|
help=LIST_OUTPUT_FORMAT_HELP)
|
||||||
|
def list(self, format_output):
|
||||||
"""Show a list of all manila services."""
|
"""Show a list of all manila services."""
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
services = db.service_get_all(ctxt)
|
services = db.service_get_all(ctxt)
|
||||||
print_format = "%-16s %-36s %-16s %-10s %-5s %-10s"
|
format_output = self._check_format_output(format_output)
|
||||||
print(print_format % (
|
|
||||||
_('Binary'),
|
services_list = []
|
||||||
_('Host'),
|
for service in services:
|
||||||
_('Zone'),
|
alive = utils.service_is_up(service)
|
||||||
_('Status'),
|
state = ":-)" if alive else "XXX"
|
||||||
_('State'),
|
|
||||||
_('Updated At'))
|
|
||||||
)
|
|
||||||
for svc in services:
|
|
||||||
alive = utils.service_is_up(svc)
|
|
||||||
art = ":-)" if alive else "XXX"
|
|
||||||
status = 'enabled'
|
status = 'enabled'
|
||||||
if svc['disabled']:
|
if service['disabled']:
|
||||||
status = 'disabled'
|
status = 'disabled'
|
||||||
print(print_format % (
|
services_list.append({
|
||||||
svc['binary'],
|
'binary': service['binary'],
|
||||||
svc['host'].partition('.')[0],
|
'host': service['host'].partition('.')[0],
|
||||||
svc['availability_zone']['name'],
|
'zone': service['availability_zone']['name'],
|
||||||
status,
|
'status': status,
|
||||||
art,
|
'state': state,
|
||||||
svc['updated_at'],
|
'updated_at': str(service['updated_at']),
|
||||||
))
|
})
|
||||||
|
|
||||||
|
method_list_name = f'list_{format_output}'
|
||||||
|
getattr(self, method_list_name)('services', services_list)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
"""Remove manila services reporting as 'down'."""
|
"""Remove manila services reporting as 'down'."""
|
||||||
|
@ -18,9 +18,11 @@ import io
|
|||||||
import readline
|
import readline
|
||||||
import sys
|
import sys
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
import yaml
|
||||||
|
|
||||||
import ddt
|
import ddt
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
from manila.cmd import manage as manila_manage
|
from manila.cmd import manage as manila_manage
|
||||||
from manila import context
|
from manila import context
|
||||||
@ -48,6 +50,7 @@ class ManilaCmdManageTestCase(test.TestCase):
|
|||||||
self.service_cmds = manila_manage.ServiceCommands()
|
self.service_cmds = manila_manage.ServiceCommands()
|
||||||
self.share_cmds = manila_manage.ShareCommands()
|
self.share_cmds = manila_manage.ShareCommands()
|
||||||
self.server_cmds = manila_manage.ShareServerCommands()
|
self.server_cmds = manila_manage.ShareServerCommands()
|
||||||
|
self.list_commands = manila_manage.ListCommand()
|
||||||
|
|
||||||
@mock.patch.object(manila_manage.ShellCommands, 'run', mock.Mock())
|
@mock.patch.object(manila_manage.ShellCommands, 'run', mock.Mock())
|
||||||
def test_shell_commands_bpython(self):
|
def test_shell_commands_bpython(self):
|
||||||
@ -291,7 +294,7 @@ class ManilaCmdManageTestCase(test.TestCase):
|
|||||||
'Zone',
|
'Zone',
|
||||||
'Status',
|
'Status',
|
||||||
'State',
|
'State',
|
||||||
'Updated At')
|
'Updated at')
|
||||||
service_format = format % (service['binary'],
|
service_format = format % (service['binary'],
|
||||||
service['host'].partition('.')[0],
|
service['host'].partition('.')[0],
|
||||||
service['availability_zone']['name'],
|
service['availability_zone']['name'],
|
||||||
@ -299,12 +302,47 @@ class ManilaCmdManageTestCase(test.TestCase):
|
|||||||
':-)',
|
':-)',
|
||||||
service['updated_at'])
|
service['updated_at'])
|
||||||
expected_out = print_format + '\n' + service_format + '\n'
|
expected_out = print_format + '\n' + service_format + '\n'
|
||||||
self.service_cmds.list()
|
self.service_cmds.list(format_output='table')
|
||||||
self.assertEqual(expected_out, fake_out.getvalue())
|
self.assertEqual(expected_out, fake_out.getvalue())
|
||||||
get_admin_context.assert_called_with()
|
get_admin_context.assert_called_with()
|
||||||
service_get_all.assert_called_with(ctxt)
|
service_get_all.assert_called_with(ctxt)
|
||||||
service_is_up.assert_called_with(service)
|
service_is_up.assert_called_with(service)
|
||||||
|
|
||||||
|
@ddt.data('json', 'yaml')
|
||||||
|
def test_service_commands_list_format(self, format_output):
|
||||||
|
ctxt = context.RequestContext('fake-user', 'fake-project')
|
||||||
|
format_method_name = f'list_{format_output}'
|
||||||
|
mock_list_method = self.mock_object(
|
||||||
|
self.service_cmds, format_method_name)
|
||||||
|
get_admin_context = self.mock_object(context, 'get_admin_context')
|
||||||
|
service_get_all = self.mock_object(db, 'service_get_all')
|
||||||
|
service_is_up = self.mock_object(utils, 'service_is_up')
|
||||||
|
get_admin_context.return_value = ctxt
|
||||||
|
service = {'binary': 'manila-binary',
|
||||||
|
'host': 'fake-host.fake-domain',
|
||||||
|
'availability_zone': {'name': 'fake-zone'},
|
||||||
|
'updated_at': '2014-06-30 11:22:33',
|
||||||
|
'disabled': False}
|
||||||
|
services = [service]
|
||||||
|
service_get_all.return_value = services
|
||||||
|
service_is_up.return_value = True
|
||||||
|
|
||||||
|
with mock.patch('sys.stdout', new=io.StringIO()):
|
||||||
|
self.service_cmds.list(format_output=format_output)
|
||||||
|
get_admin_context.assert_called_with()
|
||||||
|
service_get_all.assert_called_with(ctxt)
|
||||||
|
service_is_up.assert_called_with(service)
|
||||||
|
service_format = {
|
||||||
|
'binary': service['binary'],
|
||||||
|
'host': service['host'].partition('.')[0],
|
||||||
|
'zone': service['availability_zone']['name'],
|
||||||
|
'status': 'enabled',
|
||||||
|
'state': ':-)',
|
||||||
|
'updated_at': service['updated_at'],
|
||||||
|
}
|
||||||
|
mock_list_method.assert_called_once_with(
|
||||||
|
'services', [service_format])
|
||||||
|
|
||||||
@ddt.data(True, False)
|
@ddt.data(True, False)
|
||||||
def test_service_commands_cleanup(self, service_is_up):
|
def test_service_commands_cleanup(self, service_is_up):
|
||||||
ctxt = context.RequestContext('fake-user', 'fake-project')
|
ctxt = context.RequestContext('fake-user', 'fake-project')
|
||||||
@ -508,3 +546,47 @@ class ManilaCmdManageTestCase(test.TestCase):
|
|||||||
True)
|
True)
|
||||||
|
|
||||||
self.assertEqual(1, exit.code)
|
self.assertEqual(1, exit.code)
|
||||||
|
|
||||||
|
@mock.patch('builtins.print')
|
||||||
|
def test_list_commands_json(self, mock_print):
|
||||||
|
resource_name = 'service'
|
||||||
|
service_format = [{
|
||||||
|
'binary': 'manila-binary',
|
||||||
|
'host': 'fake-host',
|
||||||
|
'availability_zone': 'fakeaz',
|
||||||
|
'status': 'enabled',
|
||||||
|
'state': ':-)',
|
||||||
|
'updated_at': '13 04:57:49 PM -03 2023'
|
||||||
|
}]
|
||||||
|
|
||||||
|
mock_json_dumps = self.mock_object(
|
||||||
|
jsonutils, 'dumps', mock.Mock(return_value=service_format[0]))
|
||||||
|
services = {resource_name: service_format}
|
||||||
|
|
||||||
|
self.list_commands.list_json('service', service_format)
|
||||||
|
|
||||||
|
mock_json_dumps.assert_called_once_with(
|
||||||
|
services, indent=4)
|
||||||
|
mock_print.assert_called_once_with(service_format[0])
|
||||||
|
|
||||||
|
@mock.patch('builtins.print')
|
||||||
|
def test_list_commands_yaml(self, mock_print):
|
||||||
|
resource_name = 'service'
|
||||||
|
service_format = [{
|
||||||
|
'binary': 'manila-binary',
|
||||||
|
'host': 'fake-host',
|
||||||
|
'availability_zone': 'fakeaz',
|
||||||
|
'status': 'enabled',
|
||||||
|
'state': ':-)',
|
||||||
|
'updated_at': '13 04:57:49 PM -03 2023'
|
||||||
|
}]
|
||||||
|
|
||||||
|
mock_yaml_dump = self.mock_object(
|
||||||
|
yaml, 'dump', mock.Mock(return_value=service_format[0]))
|
||||||
|
services = {resource_name: service_format}
|
||||||
|
|
||||||
|
self.list_commands.list_yaml('service', service_format)
|
||||||
|
|
||||||
|
mock_yaml_dump.assert_called_once_with(
|
||||||
|
services)
|
||||||
|
mock_print.assert_called_once_with(service_format[0])
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The possibility to specify the desired output format while issuing the
|
||||||
|
`manila-manage service list` command was added. It is now possible to
|
||||||
|
display the output also in yaml and json formats.
|
Loading…
Reference in New Issue
Block a user