Joel Wright 24673f8d19 Add importable SwiftService incorporating shell.py logic
This patch adds a SwiftService class that incorporates the high
level logic from swiftclient/shell.py. It also ports shell.py to
use the new class, and updates the code in swiftclient/multithreading.py
to allow the SwiftService to be used for multiple operations whilst
using only one thread pool.

Currently, code that imports swiftclient has to have its own logic for
things like creating large objects, parallel uploads, and parallel
downloads. This patch adds a SwiftService class that makes that
functionality available in Python code as well as through the shell.

Change-Id: I08c5796b4c01001d79fd571651c3017c16462ffd
Implements: blueprint bin-swift-logic-as-importable-library
2014-08-26 14:14:21 +02:00

181 lines
6.1 KiB
Python

# 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 swiftclient.utils import prt_bytes
POLICY_HEADER_PREFIX = 'x-account-storage-policy-'
def stat_account(conn, options):
items = []
headers = conn.head_account()
if options['verbose'] > 1:
items.extend([
('StorageURL', conn.url),
('Auth Token', conn.token),
])
container_count = int(headers.get('x-account-container-count', 0))
object_count = prt_bytes(headers.get('x-account-object-count', 0),
options['human']).lstrip()
bytes_used = prt_bytes(headers.get('x-account-bytes-used', 0),
options['human']).lstrip()
items.extend([
('Account', conn.url.rsplit('/', 1)[-1]),
('Containers', container_count),
('Objects', object_count),
('Bytes', bytes_used),
])
policies = set()
for header_key, header_value in headers.items():
if header_key.lower().startswith(POLICY_HEADER_PREFIX):
policy_name = header_key.rsplit('-', 2)[0].split('-', 4)[-1]
policies.add(policy_name)
for policy in policies:
items.extend((
('Objects in policy "' + policy + '"',
prt_bytes(
headers.get(
POLICY_HEADER_PREFIX + policy + '-object-count', 0),
options['human']
).lstrip()),
('Bytes in policy "' + policy + '"',
prt_bytes(
headers.get(
POLICY_HEADER_PREFIX + policy + '-bytes-used', 0),
options['human']
).lstrip()),
))
return items, headers
def print_account_stats(items, headers, output_manager):
exclude_policy_headers = []
for header_key, header_value in headers.items():
if header_key.lower().startswith(POLICY_HEADER_PREFIX):
exclude_policy_headers.append(header_key)
items.extend(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)
output_manager.print_items(items, offset=offset)
def stat_container(conn, options, container):
headers = conn.head_container(container)
items = []
if options['verbose'] > 1:
path = '%s/%s' % (conn.url, container)
items.extend([
('URL', path),
('Auth Token', conn.token)
])
object_count = prt_bytes(
headers.get('x-container-object-count', 0),
options['human']).lstrip()
bytes_used = prt_bytes(headers.get('x-container-bytes-used', 0),
options['human']).lstrip()
items.extend([
('Account', conn.url.rsplit('/', 1)[-1]),
('Container', container),
('Objects', object_count),
('Bytes', bytes_used),
('Read ACL', headers.get('x-container-read', '')),
('Write ACL', headers.get('x-container-write', '')),
('Sync To', headers.get('x-container-sync-to', '')),
('Sync Key', headers.get('x-container-sync-key', ''))
])
return items, headers
def print_container_stats(items, headers, output_manager):
items.extend(headers_to_items(
headers,
meta_prefix='x-container-meta-',
exclude_headers=(
'content-length', 'date',
'x-container-object-count',
'x-container-bytes-used',
'x-container-read',
'x-container-write',
'x-container-sync-to',
'x-container-sync-key'
)
))
# line up the items nicely
offset = max(len(item) for item, value in items)
output_manager.print_items(items, offset=offset)
def stat_object(conn, options, container, obj):
headers = conn.head_object(container, obj)
items = []
if options['verbose'] > 1:
path = '%s/%s/%s' % (conn.url, container, obj)
items.extend([
('URL', path),
('Auth Token', conn.token)
])
content_length = prt_bytes(headers.get('content-length', 0),
options['human']).lstrip()
items.extend([
('Account', conn.url.rsplit('/', 1)[-1]),
('Container', container),
('Object', obj),
('Content Type', headers.get('content-type')),
('Content Length', content_length),
('Last Modified', headers.get('last-modified')),
('ETag', headers.get('etag')),
('Manifest', headers.get('x-object-manifest'))
])
return items, headers
def print_object_stats(items, headers, output_manager):
items.extend(headers_to_items(
headers,
meta_prefix='x-object-meta-',
exclude_headers=(
'content-type', 'content-length',
'last-modified', 'etag', 'date',
'x-object-manifest')
))
# line up the items nicely
offset = max(len(item) for item, value in items)
output_manager.print_items(items, offset=offset, skip_missing=True)
def headers_to_items(headers, meta_prefix='', exclude_headers=None):
exclude_headers = exclude_headers or []
other_items = []
meta_items = []
for key, value in headers.items():
if key not in exclude_headers:
if key.startswith(meta_prefix):
meta_key = 'Meta %s' % key[len(meta_prefix):].title()
meta_items.append((meta_key, value))
else:
other_items.append((key.title(), value))
return meta_items + other_items