Add operation log API cmd to karborclient
Change-Id: I097ec3424b47939ff00f417bedb186305de39a62 blueprint: operation-log-api
This commit is contained in:
111
karborclient/osc/v1/operation_logs.py
Normal file
111
karborclient/osc/v1/operation_logs.py
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""Data protection V1 operation_log action implementations"""
|
||||||
|
|
||||||
|
from osc_lib.command import command
|
||||||
|
from osc_lib import utils as osc_utils
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from karborclient.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
class ListOperationLogs(command.Lister):
|
||||||
|
_description = _("List operation_logs.")
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".ListOperationLogs")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ListOperationLogs, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'--all-projects',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help=_('Include all projects (admin only)'),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--status',
|
||||||
|
metavar='<status>',
|
||||||
|
help=_('Filter results by status'),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--marker',
|
||||||
|
metavar='<operation_log>',
|
||||||
|
help=_('The last operation_log ID of the previous page'),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--limit',
|
||||||
|
type=int,
|
||||||
|
metavar='<num-operation_logs>',
|
||||||
|
help=_('Maximum number of operation_logs to display'),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--sort',
|
||||||
|
metavar="<key>[:<direction>]",
|
||||||
|
default=None,
|
||||||
|
help=_("Sort output by selected keys and directions(asc or desc), "
|
||||||
|
"multiple keys and directions can be "
|
||||||
|
"specified separated by comma"),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--project',
|
||||||
|
metavar='<project>',
|
||||||
|
help=_('Filter results by a project(admin only)')
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)", parsed_args)
|
||||||
|
data_protection_client = self.app.client_manager.data_protection
|
||||||
|
all_projects = bool(parsed_args.project) or parsed_args.all_projects
|
||||||
|
|
||||||
|
search_opts = {
|
||||||
|
'all_tenants': all_projects,
|
||||||
|
'project_id': parsed_args.project,
|
||||||
|
'status': parsed_args.status,
|
||||||
|
}
|
||||||
|
|
||||||
|
data = data_protection_client.operation_logs.list(
|
||||||
|
search_opts=search_opts, marker=parsed_args.marker,
|
||||||
|
limit=parsed_args.limit, sort=parsed_args.sort)
|
||||||
|
|
||||||
|
column_headers = ['Id', 'Operation Type', 'Checkpoint id',
|
||||||
|
'Plan Id', 'Provider id', 'Restore Id',
|
||||||
|
'Scheduled Operation Id', 'Status',
|
||||||
|
'Started At', 'Ended At', 'Error Info',
|
||||||
|
'Extra Info']
|
||||||
|
|
||||||
|
return (column_headers,
|
||||||
|
(osc_utils.get_item_properties(
|
||||||
|
s, column_headers
|
||||||
|
) for s in data))
|
||||||
|
|
||||||
|
|
||||||
|
class ShowOperationLog(command.ShowOne):
|
||||||
|
_description = "Shows operation_log details"
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ShowOperationLog, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'operation_log',
|
||||||
|
metavar="<operation_log>",
|
||||||
|
help=_('The UUID of the operation_log.')
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
client = self.app.client_manager.data_protection
|
||||||
|
operation_log = osc_utils.find_resource(client.operation_logs,
|
||||||
|
parsed_args.operation_log)
|
||||||
|
|
||||||
|
operation_log._info.pop("links", None)
|
||||||
|
return zip(*sorted(operation_log._info.items()))
|
||||||
124
karborclient/tests/unit/osc/v1/test_operation_logs.py
Normal file
124
karborclient/tests/unit/osc/v1/test_operation_logs.py
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from karborclient.osc.v1 import operation_logs as osc_operation_logs
|
||||||
|
from karborclient.tests.unit.osc.v1 import fakes
|
||||||
|
from karborclient.v1 import operation_logs
|
||||||
|
|
||||||
|
|
||||||
|
OPERATIONLOG_INFO = {
|
||||||
|
"id": "22b82aa7-9179-4c71-bba2-caf5c0e68db7",
|
||||||
|
"project_id": "e486a2f49695423ca9c47e589b948108",
|
||||||
|
"operation_type": "protect",
|
||||||
|
"checkpoint_id": "dcb20606-ad71-40a3-80e4-ef0fafdad0c3",
|
||||||
|
"plan_id": "cf56bd3e-97a7-4078-b6d5-f36246333fd9",
|
||||||
|
"provider_id": "23902b02-5666-4ee6-8dfe-962ac09c3994",
|
||||||
|
"restore_id": None,
|
||||||
|
"scheduled_operation_id": "23902b02-5666-4ee6-8dfe-962ac09c3991",
|
||||||
|
"started_at": "2015-08-27T09:50:58-05:00",
|
||||||
|
"ended_at": "2015-08-27T10:50:58-05:00",
|
||||||
|
"status": "protecting",
|
||||||
|
"error_info": "Could not access bank",
|
||||||
|
"extra_info": None
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestOperationLogs(fakes.TestDataProtection):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestOperationLogs, self).setUp()
|
||||||
|
self.operation_logs_mock = (
|
||||||
|
self.app.client_manager.data_protection.operation_logs)
|
||||||
|
self.operation_logs_mock.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
|
class TestListOperationLogs(TestOperationLogs):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestListOperationLogs, self).setUp()
|
||||||
|
self.operation_logs_mock.list.return_value = [
|
||||||
|
operation_logs.OperationLog(None, OPERATIONLOG_INFO)]
|
||||||
|
|
||||||
|
# Command to test
|
||||||
|
self.cmd = osc_operation_logs.ListOperationLogs(self.app, None)
|
||||||
|
|
||||||
|
def test_operation_logs_list(self):
|
||||||
|
arglist = ['--status', 'success']
|
||||||
|
verifylist = [('status', 'success')]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Check that columns are correct
|
||||||
|
expected_columns = (
|
||||||
|
['Id', 'Operation Type', 'Checkpoint id', 'Plan Id',
|
||||||
|
'Provider id', 'Restore Id', 'Scheduled Operation Id',
|
||||||
|
'Status', 'Started At', 'Ended At', 'Error Info',
|
||||||
|
'Extra Info'])
|
||||||
|
self.assertEqual(expected_columns, columns)
|
||||||
|
|
||||||
|
# Check that data is correct
|
||||||
|
expected_data = [("22b82aa7-9179-4c71-bba2-caf5c0e68db7",
|
||||||
|
"protect",
|
||||||
|
"dcb20606-ad71-40a3-80e4-ef0fafdad0c3",
|
||||||
|
"cf56bd3e-97a7-4078-b6d5-f36246333fd9",
|
||||||
|
"23902b02-5666-4ee6-8dfe-962ac09c3994",
|
||||||
|
None,
|
||||||
|
"23902b02-5666-4ee6-8dfe-962ac09c3991",
|
||||||
|
"protecting",
|
||||||
|
"2015-08-27T09:50:58-05:00",
|
||||||
|
"2015-08-27T10:50:58-05:00",
|
||||||
|
"Could not access bank",
|
||||||
|
None)]
|
||||||
|
self.assertEqual(expected_data, list(data))
|
||||||
|
|
||||||
|
|
||||||
|
class TestShowOperationLog(TestOperationLogs):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestShowOperationLog, self).setUp()
|
||||||
|
self.operation_logs_mock.get.return_value = (
|
||||||
|
operation_logs.OperationLog(None, OPERATIONLOG_INFO))
|
||||||
|
|
||||||
|
# Command to test
|
||||||
|
self.cmd = osc_operation_logs.ShowOperationLog(self.app, None)
|
||||||
|
|
||||||
|
def test_operation_log_show(self):
|
||||||
|
arglist = ['22b82aa7-9179-4c71-bba2-caf5c0e68db7']
|
||||||
|
verifylist = [('operation_log',
|
||||||
|
'22b82aa7-9179-4c71-bba2-caf5c0e68db7')]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Check that columns are correct
|
||||||
|
expected_columns = (
|
||||||
|
'checkpoint_id', 'ended_at', 'error_info', 'extra_info',
|
||||||
|
'id', 'operation_type', 'plan_id', 'project_id',
|
||||||
|
'provider_id', 'restore_id', 'scheduled_operation_id',
|
||||||
|
'started_at', 'status')
|
||||||
|
self.assertEqual(expected_columns, columns)
|
||||||
|
|
||||||
|
# Check that data is correct
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['checkpoint_id'], data[0])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['ended_at'], data[1])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['error_info'], data[2])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['extra_info'], data[3])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['id'], data[4])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['operation_type'], data[5])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['plan_id'], data[6])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['project_id'], data[7])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['provider_id'], data[8])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['restore_id'], data[9])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['scheduled_operation_id'], data[10])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['started_at'], data[11])
|
||||||
|
self.assertEqual(OPERATIONLOG_INFO['status'], data[12])
|
||||||
63
karborclient/tests/unit/v1/test_operation_logs.py
Normal file
63
karborclient/tests/unit/v1/test_operation_logs.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from karborclient.tests.unit import base
|
||||||
|
from karborclient.tests.unit.v1 import fakes
|
||||||
|
|
||||||
|
cs = fakes.FakeClient()
|
||||||
|
mock_request_return = ({}, {'operation_log': {}})
|
||||||
|
|
||||||
|
|
||||||
|
class OperationLogsTest(base.TestCaseShell):
|
||||||
|
|
||||||
|
@mock.patch('karborclient.common.http.HTTPClient.json_request')
|
||||||
|
def test_list_operation_logs_with_marker_limit(self, mock_request):
|
||||||
|
mock_request.return_value = mock_request_return
|
||||||
|
cs.operation_logs.list(marker=1234, limit=2)
|
||||||
|
mock_request.assert_called_with(
|
||||||
|
'GET',
|
||||||
|
'/operation_logs?limit=2&marker=1234', headers={})
|
||||||
|
|
||||||
|
@mock.patch('karborclient.common.http.HTTPClient.json_request')
|
||||||
|
def test_list_operation_logs_with_sort_key_dir(self, mock_request):
|
||||||
|
mock_request.return_value = mock_request_return
|
||||||
|
cs.operation_logs.list(sort_key='id', sort_dir='asc')
|
||||||
|
mock_request.assert_called_with(
|
||||||
|
'GET',
|
||||||
|
'/operation_logs?'
|
||||||
|
'sort_dir=asc&sort_key=id', headers={})
|
||||||
|
|
||||||
|
@mock.patch('karborclient.common.http.HTTPClient.json_request')
|
||||||
|
def test_list_operation_logs_with_invalid_sort_key(self, mock_request):
|
||||||
|
self.assertRaises(ValueError,
|
||||||
|
cs.operation_logs.list,
|
||||||
|
sort_key='invalid', sort_dir='asc')
|
||||||
|
|
||||||
|
@mock.patch('karborclient.common.http.HTTPClient.json_request')
|
||||||
|
def test_show_operation_log(self, mock_request):
|
||||||
|
mock_request.return_value = mock_request_return
|
||||||
|
cs.operation_logs.get('1')
|
||||||
|
mock_request.assert_called_with(
|
||||||
|
'GET',
|
||||||
|
'/operation_logs/1',
|
||||||
|
headers={})
|
||||||
|
|
||||||
|
@mock.patch('karborclient.common.http.HTTPClient.json_request')
|
||||||
|
def test_show_operation_log_with_headers(self, mock_request):
|
||||||
|
mock_request.return_value = mock_request_return
|
||||||
|
cs.operation_logs.get('1', session_id='fake_session_id')
|
||||||
|
mock_request.assert_called_with(
|
||||||
|
'GET',
|
||||||
|
'/operation_logs/1',
|
||||||
|
headers={'X-Configuration-Session': 'fake_session_id'})
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
from karborclient.common import http
|
from karborclient.common import http
|
||||||
from karborclient.v1 import checkpoints
|
from karborclient.v1 import checkpoints
|
||||||
|
from karborclient.v1 import operation_logs
|
||||||
from karborclient.v1 import plans
|
from karborclient.v1 import plans
|
||||||
from karborclient.v1 import protectables
|
from karborclient.v1 import protectables
|
||||||
from karborclient.v1 import providers
|
from karborclient.v1 import providers
|
||||||
@@ -42,3 +43,5 @@ class Client(object):
|
|||||||
self.triggers = triggers.TriggerManager(self.http_client)
|
self.triggers = triggers.TriggerManager(self.http_client)
|
||||||
self.scheduled_operations = \
|
self.scheduled_operations = \
|
||||||
scheduled_operations.ScheduledOperationManager(self.http_client)
|
scheduled_operations.ScheduledOperationManager(self.http_client)
|
||||||
|
self.operation_logs = \
|
||||||
|
operation_logs.OperationLogManager(self.http_client)
|
||||||
|
|||||||
44
karborclient/v1/operation_logs.py
Normal file
44
karborclient/v1/operation_logs.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from karborclient.common import base
|
||||||
|
|
||||||
|
|
||||||
|
class OperationLog(base.Resource):
|
||||||
|
def __repr__(self):
|
||||||
|
return "<OperationLog %s>" % self._info
|
||||||
|
|
||||||
|
|
||||||
|
class OperationLogManager(base.ManagerWithFind):
|
||||||
|
resource_class = OperationLog
|
||||||
|
|
||||||
|
def get(self, operation_log_id, session_id=None):
|
||||||
|
if session_id:
|
||||||
|
headers = {'X-Configuration-Session': session_id}
|
||||||
|
else:
|
||||||
|
headers = {}
|
||||||
|
url = "/operation_logs/{operation_log_id}".format(
|
||||||
|
operation_log_id=operation_log_id)
|
||||||
|
return self._get(url, response_key="operation_log", headers=headers)
|
||||||
|
|
||||||
|
def list(self, detailed=False, search_opts=None, marker=None, limit=None,
|
||||||
|
sort_key=None, sort_dir=None, sort=None):
|
||||||
|
"""Lists all operation_logs.
|
||||||
|
|
||||||
|
"""
|
||||||
|
resource_type = "operation_logs"
|
||||||
|
url = self._build_list_url(
|
||||||
|
resource_type, detailed=detailed,
|
||||||
|
search_opts=search_opts, marker=marker,
|
||||||
|
limit=limit, sort_key=sort_key,
|
||||||
|
sort_dir=sort_dir, sort=sort)
|
||||||
|
return self._list(url, 'operation_logs')
|
||||||
@@ -1018,3 +1018,93 @@ def do_scheduledoperation_delete(cs, args):
|
|||||||
if failure_count == len(args.scheduledoperation):
|
if failure_count == len(args.scheduledoperation):
|
||||||
raise exceptions.CommandError("Unable to find and delete any of the "
|
raise exceptions.CommandError("Unable to find and delete any of the "
|
||||||
"specified scheduled operation.")
|
"specified scheduled operation.")
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('--all-tenants',
|
||||||
|
dest='all_tenants',
|
||||||
|
metavar='<0|1>',
|
||||||
|
nargs='?',
|
||||||
|
type=int,
|
||||||
|
const=1,
|
||||||
|
default=0,
|
||||||
|
help='Shows details for all tenants. Admin only.')
|
||||||
|
@utils.arg('--all_tenants',
|
||||||
|
nargs='?',
|
||||||
|
type=int,
|
||||||
|
const=1,
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
|
@utils.arg('--status',
|
||||||
|
metavar='<status>',
|
||||||
|
default=None,
|
||||||
|
help='Filters results by a status. Default=None.')
|
||||||
|
@utils.arg('--marker',
|
||||||
|
metavar='<marker>',
|
||||||
|
default=None,
|
||||||
|
help='Begin returning restores that appear later in the '
|
||||||
|
'operation_log list than that represented by this '
|
||||||
|
'operation_logs id. Default=None.')
|
||||||
|
@utils.arg('--limit',
|
||||||
|
metavar='<limit>',
|
||||||
|
default=None,
|
||||||
|
help='Maximum number of operation_logs to return. Default=None.')
|
||||||
|
@utils.arg('--sort_key',
|
||||||
|
metavar='<sort_key>',
|
||||||
|
default=None,
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
|
@utils.arg('--sort_dir',
|
||||||
|
metavar='<sort_dir>',
|
||||||
|
default=None,
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
|
@utils.arg('--sort',
|
||||||
|
metavar='<key>[:<direction>]',
|
||||||
|
default=None,
|
||||||
|
help=(('Comma-separated list of sort keys and directions in the '
|
||||||
|
'form of <key>[:<asc|desc>]. '
|
||||||
|
'Valid keys: %s. '
|
||||||
|
'Default=None.') % ', '.join(base.SORT_KEY_VALUES)))
|
||||||
|
@utils.arg('--tenant',
|
||||||
|
type=str,
|
||||||
|
dest='tenant',
|
||||||
|
nargs='?',
|
||||||
|
metavar='<tenant>',
|
||||||
|
help='Display information from single tenant (Admin only).')
|
||||||
|
def do_operationlog_list(cs, args):
|
||||||
|
"""Lists all operation_logs."""
|
||||||
|
|
||||||
|
all_tenants = 1 if args.tenant else \
|
||||||
|
int(os.environ.get("ALL_TENANTS", args.all_tenants))
|
||||||
|
search_opts = {
|
||||||
|
'all_tenants': all_tenants,
|
||||||
|
'project_id': args.tenant,
|
||||||
|
'status': args.status,
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.sort and (args.sort_key or args.sort_dir):
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
'The --sort_key and --sort_dir arguments are deprecated and are '
|
||||||
|
'not supported with --sort.')
|
||||||
|
|
||||||
|
operation_logs = cs.operation_logs.list(
|
||||||
|
search_opts=search_opts, marker=args.marker,
|
||||||
|
limit=args.limit, sort_key=args.sort_key,
|
||||||
|
sort_dir=args.sort_dir, sort=args.sort)
|
||||||
|
|
||||||
|
key_list = ['Id', 'Operation Type', 'Checkpoint id', 'Plan Id',
|
||||||
|
'Provider id', 'Restore Id', 'Scheduled Operation Id',
|
||||||
|
'Status', 'Started At', 'Ended At', 'Error Info', 'Extra Info']
|
||||||
|
|
||||||
|
if args.sort_key or args.sort_dir or args.sort:
|
||||||
|
sortby_index = None
|
||||||
|
else:
|
||||||
|
sortby_index = 0
|
||||||
|
utils.print_list(operation_logs, key_list, exclude_unavailable=True,
|
||||||
|
sortby_index=sortby_index)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('operation_log',
|
||||||
|
metavar='<operation_log>',
|
||||||
|
help='ID of operation_log.')
|
||||||
|
def do_operationlog_show(cs, args):
|
||||||
|
"""Shows operation_log details."""
|
||||||
|
operation_log = cs.operation_logs.get(args.operation_log)
|
||||||
|
utils.print_dict(operation_log.to_dict())
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ openstack.data_protection.v1 =
|
|||||||
data_protection_scheduledoperation_show = karborclient.osc.v1.scheduled_operations:ShowScheduledOperation
|
data_protection_scheduledoperation_show = karborclient.osc.v1.scheduled_operations:ShowScheduledOperation
|
||||||
data_protection_scheduledoperation_create = karborclient.osc.v1.scheduled_operations:CreateScheduledOperation
|
data_protection_scheduledoperation_create = karborclient.osc.v1.scheduled_operations:CreateScheduledOperation
|
||||||
data_protection_scheduledoperation_delete = karborclient.osc.v1.scheduled_operations:DeleteScheduledOperation
|
data_protection_scheduledoperation_delete = karborclient.osc.v1.scheduled_operations:DeleteScheduledOperation
|
||||||
|
data_protection_operationlog_list = karborclient.osc.v1.operation_logs:ListOperationLogs
|
||||||
|
data_protection_operationlog_show = karborclient.osc.v1.operation_logs:ShowOperationLog
|
||||||
|
|
||||||
[compile_catalog]
|
[compile_catalog]
|
||||||
directory = karborclient/locale
|
directory = karborclient/locale
|
||||||
|
|||||||
Reference in New Issue
Block a user