Merge "Add CLI to show instance usage audit logs"

This commit is contained in:
Zuul 2018-02-05 16:53:53 +00:00 committed by Gerrit Code Review
commit 5de74bef5c
8 changed files with 285 additions and 0 deletions

View File

@ -0,0 +1,87 @@
# 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 datetime
from oslo_utils import timeutils
from novaclient.tests.functional import base
class TestInstanceUsageAuditLogCLI(base.ClientTestBase):
COMPUTE_API_VERSION = '2.1'
# NOTE(takashin): By default, 'instance_usage_audit' is False in nova.
# So the instance usage audit log is not recoreded.
# Therefore an empty result can be got.
# But it is tested here to call APIs and get responses normally.
@staticmethod
def _get_begin_end_time():
current = timeutils.utcnow()
end = datetime.datetime(day=1, month=current.month, year=current.year)
year = end.year
if current.month == 1:
year -= 1
month = 12
else:
month = current.month - 1
begin = datetime.datetime(day=1, month=month, year=year)
return (begin, end)
def test_get_os_instance_usage_audit_log(self):
(begin, end) = self._get_begin_end_time()
expected = {
'hosts_not_run': '[]',
'log': '{}',
'num_hosts': '0',
'num_hosts_done': '0',
'num_hosts_not_run': '0',
'num_hosts_running': '0',
'overall_status': 'ALL hosts done. 0 errors.',
'total_errors': '0',
'total_instances': '0',
'period_beginning': str(begin),
'period_ending': str(end)
}
output = self.nova('instance-usage-audit-log')
for key in expected.keys():
self.assertEqual(expected[key],
self._get_value_from_the_table(output, key))
def test_get_os_instance_usage_audit_log_with_before(self):
expected = {
'hosts_not_run': '[]',
'log': '{}',
'num_hosts': '0',
'num_hosts_done': '0',
'num_hosts_not_run': '0',
'num_hosts_running': '0',
'overall_status': 'ALL hosts done. 0 errors.',
'total_errors': '0',
'total_instances': '0',
'period_beginning': '2016-11-01 00:00:00',
'period_ending': '2016-12-01 00:00:00'
}
output = self.nova(
'instance-usage-audit-log --before "2016-12-10 13:59:59.999999"')
for key in expected.keys():
self.assertEqual(expected[key],
self._get_value_from_the_table(output, key))

View File

@ -124,6 +124,8 @@ class FakeSessionClient(base_client.SessionClient):
munged_url = munged_url.replace(' ', '_')
munged_url = munged_url.replace('!', '_')
munged_url = munged_url.replace('@', '_')
munged_url = munged_url.replace('%20', '_')
munged_url = munged_url.replace('%3A', '_')
callback = "%s_%s" % (method.lower(), munged_url)
if url is None or callback == "get_http:__nova_api:8774":
@ -2006,6 +2008,86 @@ class FakeSessionClient(base_client.SessionClient):
return (200, FAKE_RESPONSE_HEADERS, {
"instanceAction": action})
def get_os_instance_usage_audit_log(self, **kw):
return (200, FAKE_RESPONSE_HEADERS, {
"instance_usage_audit_logs": {
"hosts_not_run": ["samplehost3"],
"log": {
"samplehost0": {
"errors": 1,
"instances": 1,
"message": ("Instance usage audit ran for host "
"samplehost0, 1 instances in 0.01 "
"seconds."),
"state": "DONE"
},
"samplehost1": {
"errors": 1,
"instances": 2,
"message": ("Instance usage audit ran for host "
"samplehost1, 2 instances in 0.01 "
"seconds."),
"state": "DONE"
},
"samplehost2": {
"errors": 1,
"instances": 3,
"message": ("Instance usage audit ran for host "
"samplehost2, 3 instances in 0.01 "
"seconds."),
"state": "DONE"
},
},
"num_hosts": 4,
"num_hosts_done": 3,
"num_hosts_not_run": 1,
"num_hosts_running": 0,
"overall_status": "3 of 4 hosts done. 3 errors.",
"period_beginning": "2012-06-01 00:00:00",
"period_ending": "2012-07-01 00:00:00",
"total_errors": 3,
"total_instances": 6}})
def get_os_instance_usage_audit_log_2016_12_10_13_59_59_999999(self, **kw):
return (200, FAKE_RESPONSE_HEADERS, {
"instance_usage_audit_log": {
"hosts_not_run": ["samplehost3"],
"log": {
"samplehost0": {
"errors": 1,
"instances": 1,
"message": ("Instance usage audit ran for host "
"samplehost0, 1 instances in 0.01 "
"seconds."),
"state": "DONE"
},
"samplehost1": {
"errors": 1,
"instances": 2,
"message": ("Instance usage audit ran for host "
"samplehost1, 2 instances in 0.01 "
"seconds."),
"state": "DONE"
},
"samplehost2": {
"errors": 1,
"instances": 3,
"message": ("Instance usage audit ran for host "
"samplehost2, 3 instances in 0.01 "
"seconds."),
"state": "DONE"
},
},
"num_hosts": 4,
"num_hosts_done": 3,
"num_hosts_not_run": 1,
"num_hosts_running": 0,
"overall_status": "3 of 4 hosts done. 3 errors.",
"period_beginning": "2012-06-01 00:00:00",
"period_ending": "2012-07-01 00:00:00",
"total_errors": 3,
"total_instances": 6}})
def post_servers_uuid1_action(self, **kw):
return 202, {}, {}

View File

@ -0,0 +1,37 @@
# Copyright 2013 Rackspace Hosting
# All Rights Reserved.
#
# 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 novaclient import api_versions
from novaclient.tests.unit import utils
from novaclient.tests.unit.v2 import fakes
class InstanceUsageAuditLogTests(utils.TestCase):
def setUp(self):
super(InstanceUsageAuditLogTests, self).setUp()
self.cs = fakes.FakeClient(api_versions.APIVersion("2.1"))
def test_instance_usage_audit_log(self):
audit_log = self.cs.instance_usage_audit_log.get()
self.assert_request_id(audit_log, fakes.FAKE_REQUEST_ID_LIST)
self.cs.assert_called('GET', '/os-instance_usage_audit_log')
def test_instance_usage_audit_log_with_before(self):
audit_log = self.cs.instance_usage_audit_log.get(
before='2016-12-10 13:59:59.999999')
self.assert_request_id(audit_log, fakes.FAKE_REQUEST_ID_LIST)
self.cs.assert_called(
'GET',
'/os-instance_usage_audit_log/2016-12-10%2013%3A59%3A59.999999')

View File

@ -3210,6 +3210,17 @@ class ShellTest(utils.TestCase):
api_version='2.58')
self.assertIn('Invalid changes-since value', six.text_type(ex))
def test_instance_usage_audit_log(self):
self.run_command('instance-usage-audit-log')
self.assert_called('GET', '/os-instance_usage_audit_log')
def test_instance_usage_audit_log_with_before(self):
self.run_command(
["instance-usage-audit-log", "--before",
"2016-12-10 13:59:59.999999"])
self.assert_called('GET', '/os-instance_usage_audit_log'
'/2016-12-10%2013%3A59%3A59.999999')
def test_cell_show(self):
self.run_command('cell-show child_cell')
self.assert_called('GET', '/os-cells/child_cell')

View File

@ -29,6 +29,7 @@ from novaclient.v2 import flavors
from novaclient.v2 import hypervisors
from novaclient.v2 import images
from novaclient.v2 import instance_action
from novaclient.v2 import instance_usage_audit_log
from novaclient.v2 import keypairs
from novaclient.v2 import limits
from novaclient.v2 import list_extensions
@ -169,6 +170,8 @@ class Client(object):
assisted_volume_snapshots.AssistedSnapshotManager(self)
self.cells = cells.CellsManager(self)
self.instance_action = instance_action.InstanceActionManager(self)
self.instance_usage_audit_log = \
instance_usage_audit_log.InstanceUsageAuditLogManager(self)
self.list_extensions = list_extensions.ListExtManager(self)
self.migrations = migrations.MigrationManager(self)
self.server_external_events = \

View File

@ -0,0 +1,40 @@
# Copyright 2013 Rackspace Hosting
# All Rights Reserved.
#
# 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 six.moves.urllib import parse
from novaclient import base
class InstanceUsageAuditLog(base.Resource):
pass
class InstanceUsageAuditLogManager(base.Manager):
resource_class = InstanceUsageAuditLog
def get(self, before=None):
"""Get server usage audits.
:param before: Filters the response by the date and time
before which to list usage audits.
"""
if before:
return self._get('/os-instance_usage_audit_log/%s' %
parse.quote(before, safe=''),
'instance_usage_audit_log')
else:
return self._get('/os-instance_usage_audit_log',
'instance_usage_audit_logs')

View File

@ -5120,3 +5120,20 @@ def do_migration_list(cs, args):
changes_since=args.changes_since)
# TODO(yikun): Output a "Marker" column if there is a next link?
_print_migrations(cs, migrations)
@utils.arg(
'--before',
dest='before',
metavar='<before>',
default=None,
help=_("Filters the response by the date and time before which to list "
"usage audits. The date and time stamp format is as follows: "
"CCYY-MM-DD hh:mm:ss.NNNNNN ex 2015-08-27 09:49:58 or "
"2015-08-27 09:49:58.123456."))
def do_instance_usage_audit_log(cs, args):
"""List/Get server usage audits."""
audit_log = cs.instance_usage_audit_log.get(before=args.before).to_dict()
if 'hosts_not_run' in audit_log:
audit_log['hosts_not_run'] = pprint.pformat(audit_log['hosts_not_run'])
utils.print_dict(audit_log)

View File

@ -0,0 +1,8 @@
---
features:
- Added new client API and CLI (``nova instance-usage-audit-log``)
to get server usage audit logs.
By default, it lists usage audits for all servers on all
compute hosts where usage auditing is configured.
If you specify the ``--before`` option, the result is filtered
by the date and time before which to list server usage audits.