Clean up raw policy stats in account stat

Storage policy stats was not well parsed in account stat. This
patch parses the stats and print out the stats in a format like below:

$swift -A http://swift_cluster/auth/v1.0 -U test:tester -K testing stat
                   Account: AUTH_test
                Containers: 5
                   Objects: 1
                     Bytes: 2097152
Objects in policy "golden": 1
 Bytess in policy "golden": 2097152
Objects in policy "silver": 0
  Bytes in policy "silver": 0
               X-Timestamp: 1404697760.88809
                X-Trans-Id: txec519e24b44a413abb705-0053da2dcb
              Content-Type: text/plain; charset=utf-8
             Accept-Ranges: bytes

Change-Id: I7ad0ee6d88f8393e3a93e90cd52b9b592da7072d
This commit is contained in:
Yuan Zhou 2014-07-31 19:51:50 +08:00
parent fd1594937d
commit 776133bd29
4 changed files with 85 additions and 26 deletions

@ -15,9 +15,11 @@ from swiftclient.utils import prt_bytes
def stat_account(conn, options, thread_manager):
items_to_print = []
headers = conn.head_account()
if options.verbose > 1:
thread_manager.print_items((
items_to_print.extend((
('StorageURL', conn.url),
('Auth Token', conn.token),
))
@ -26,19 +28,40 @@ def stat_account(conn, options, thread_manager):
options.human).lstrip()
bytes_used = prt_bytes(headers.get('x-account-bytes-used', 0),
options.human).lstrip()
thread_manager.print_items((
items_to_print.extend((
('Account', conn.url.rsplit('/', 1)[-1]),
('Containers', container_count),
('Objects', object_count),
('Bytes', bytes_used),
))
thread_manager.print_headers(headers,
meta_prefix='x-account-meta-',
exclude_headers=(
'content-length', 'date',
'x-account-container-count',
'x-account-object-count',
'x-account-bytes-used'))
policies = set()
exclude_policy_headers = []
ps_header_prefix = 'x-account-storage-policy-'
for header_key, header_value in headers.items():
if header_key.lower().startswith(ps_header_prefix):
policy_name = header_key.rsplit('-', 2)[0].split('-', 4)[-1]
policies.add(policy_name)
exclude_policy_headers.append(header_key)
for policy in policies:
items_to_print.extend((
('Objects in policy "' + policy + '"',
prt_bytes(headers.get(ps_header_prefix + policy + '-object-count',
0), options.human).lstrip()),
('Bytes in policy "' + policy + '"',
prt_bytes(headers.get(ps_header_prefix + policy + '-bytes-used',
0), options.human).lstrip()),
))
items_to_print.extend(thread_manager.headers_to_items(
headers, meta_prefix='x-account-meta-',
exclude_headers=([
'content-length', 'date',
'x-account-container-count',
'x-account-object-count',
'x-account-bytes-used'] + exclude_policy_headers)))
# line up the items nicely
offset = max(len(item) for item, value in items_to_print)
thread_manager.print_items(items_to_print, offset=offset)
def stat_container(conn, options, args, thread_manager):

@ -193,6 +193,7 @@ class MultiThreadingManager(object):
The swift command-line tool uses this to exit non-zero if any error strings
were printed.
"""
DEFAULT_OFFSET = 14
def __init__(self, print_stream=sys.stdout, error_stream=sys.stderr):
"""
@ -231,7 +232,7 @@ class MultiThreadingManager(object):
msg = msg % fmt_args
self.printer.queue.put(msg)
def print_items(self, items, offset=14, skip_missing=False):
def print_items(self, items, offset=DEFAULT_OFFSET, skip_missing=False):
lines = []
template = '%%%ds: %%s' % offset
for k, v in items:
@ -241,7 +242,7 @@ class MultiThreadingManager(object):
self.print_msg('\n'.join(lines))
def print_headers(self, headers, meta_prefix='', exclude_headers=None,
offset=14):
offset=DEFAULT_OFFSET):
exclude_headers = exclude_headers or []
meta_headers = []
other_headers = []
@ -254,6 +255,18 @@ class MultiThreadingManager(object):
other_headers.append(template % (key.title(), value))
self.print_msg('\n'.join(chain(meta_headers, other_headers)))
def headers_to_items(self, headers, meta_prefix='', exclude_headers=None):
exclude_headers = exclude_headers or []
meta_items = []
other_items = []
for key, value in headers.items():
if key.startswith(meta_prefix):
meta_key = 'Meta %s' % key[len(meta_prefix):].title()
meta_items.append((meta_key, value))
elif key not in exclude_headers:
other_items.append((key.title(), value))
return meta_items + other_items
def error(self, msg, *fmt_args):
if fmt_args:
msg = msg % fmt_args

@ -69,10 +69,10 @@ class TestStatHelpers(testtools.TestCase):
with self.thread_manager as thread_manager:
h.stat_account(self.conn, self.options, thread_manager)
expected = """
Account: a
Containers: 42
Objects: 976K
Bytes: 1.0G
Account: a
Containers: 42
Objects: 976K
Bytes: 1.0G
"""
self.assertOut(expected)
@ -89,12 +89,35 @@ class TestStatHelpers(testtools.TestCase):
with self.thread_manager as thread_manager:
h.stat_account(self.conn, self.options, thread_manager)
expected = """
StorageURL: http://storage/v1/a
Auth Token: tk12345
Account: a
Containers: 42
Objects: 1000000
Bytes: 1073741824
StorageURL: http://storage/v1/a
Auth Token: tk12345
Account: a
Containers: 42
Objects: 1000000
Bytes: 1073741824
"""
self.assertOut(expected)
def test_stat_account_policy_stat(self):
# stub head_account
stub_headers = {
'x-account-container-count': 42,
'x-account-object-count': 1000000,
'x-account-bytes-used': 2 ** 30,
'x-account-storage-policy-nada-object-count': 1000000,
'x-account-storage-policy-nada-bytes-used': 2 ** 30,
}
self.conn.head_account.return_value = stub_headers
with self.thread_manager as thread_manager:
h.stat_account(self.conn, self.options, thread_manager)
expected = """
Account: a
Containers: 42
Objects: 1000000
Bytes: 1073741824
Objects in policy "nada": 1000000
Bytes in policy "nada": 1073741824
"""
self.assertOut(expected)

@ -63,11 +63,11 @@ class TestShell(unittest.TestCase):
connection.return_value.head_account.return_value = return_headers
connection.return_value.url = 'http://127.0.0.1/v1/AUTH_account'
swiftclient.shell.main(argv)
calls = [mock.call(' Account: AUTH_account\n' +
' Containers: 1\n' +
' Objects: 2\n' +
' Bytes: 3'),
mock.call('')]
calls = [mock.call(' Account: AUTH_account\n' +
'Containers: 1\n' +
' Objects: 2\n' +
' Bytes: 3'),
]
mock_print.assert_has_calls(calls)
@mock.patch('swiftclient.shell.MultiThreadingManager._print')