summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rwxr-xr-xbin/swift190
1 files changed, 53 insertions, 137 deletions
diff --git a/bin/swift b/bin/swift
index 0de5fbe..b61f47d 100755
--- a/bin/swift
+++ b/bin/swift
@@ -33,7 +33,8 @@ except ImportError:
import json
from swiftclient import Connection, HTTPException
-from swiftclient.utils import config_true_value
+from swiftclient import command_helpers
+from swiftclient.utils import config_true_value, prt_bytes
from swiftclient.multithreading import MultiThreadingManager
from swiftclient.exceptions import ClientException
from swiftclient import __version__ as client_version
@@ -244,9 +245,11 @@ st_download_help = '''
Download objects from containers
Positional arguments:
- <container> Name of container to download from
+ <container> Name of container to download from. To download a
+ whole account, omit this and specify --all.
<object> Name of object to download. Specify multiple times
- for multiple objects
+ for multiple objects. Omit this to download all
+ objects from the container.
Optional arguments:
--all Indicates that you really want to download
@@ -263,6 +266,11 @@ Optional arguments:
Number of threads to use for deleting containers
--no-download Perform download(s), but don't actually write anything
to disk
+ --header <header_name:header_value>
+ Adds a customized request header to the query, like
+ "Range" or "If-Match". This argument is repeatable.
+ Example --header "content-type:text/plain"
+
'''.strip("\n")
@@ -291,6 +299,13 @@ def st_download(parser, args, thread_manager):
'', '--no-download', action='store_true',
default=False,
help="Perform download(s), but don't actually write anything to disk")
+ parser.add_option(
+ '-H', '--header', action='append', dest='header',
+ default=[],
+ help='Specify a request header, as --header NAME:VALUE. '
+ 'Adds a customized request header to the query, like "Range" or '
+ '"If-Match". This argument is repeatable. Example'
+ ' --header "content-type:text/plain"')
(options, args) = parse_args(parser, args)
args = args[1:]
if options.out_file == '-':
@@ -301,6 +316,7 @@ def st_download(parser, args, thread_manager):
thread_manager.error('Usage: %s download %s\n%s', basename(argv[0]),
st_download_options, st_download_help)
return
+ req_headers = split_headers(options.header, '', thread_manager)
def _download_object(queue_arg, conn):
if len(queue_arg) == 2:
@@ -313,8 +329,9 @@ def st_download(parser, args, thread_manager):
try:
start_time = time()
headers, body = \
- conn.get_object(container, obj, resp_chunk_size=65536)
- header_receipt = time()
+ conn.get_object(container, obj, resp_chunk_size=65536,
+ headers=req_headers)
+ headers_receipt = time()
content_type = headers.get('content-type')
if 'content-length' in headers:
content_length = int(headers.get('content-length'))
@@ -374,9 +391,14 @@ def st_download(parser, args, thread_manager):
utime(path, (mtime, mtime))
if options.verbose:
finish_time = time()
- time_str = 'headers %.3fs, total %.3fs, %.3f MB/s' % (
- header_receipt - start_time, finish_time - start_time,
- float(read_length) / (finish_time - start_time) / 1000000)
+ auth_time = conn.auth_end_time - start_time
+ headers_receipt = headers_receipt - start_time
+ total_time = finish_time - start_time
+ download_time = total_time - auth_time
+ time_str = ('auth %.3fs, headers %.3fs, total %.3fs, '
+ '%.3f MB/s' % (
+ auth_time, headers_receipt, total_time,
+ float(read_length) / download_time / 1000000))
if conn.attempts > 1:
thread_manager.print_msg('%s [%s after %d attempts]', path,
time_str, conn.attempts)
@@ -443,9 +465,10 @@ def st_download(parser, args, thread_manager):
thread_manager.error('Account not found')
elif len(args) == 1:
if '/' in args[0]:
- print >> stderr, ('WARNING: / in container name; you '
- 'might have meant %r instead of %r.' % (
- args[0].replace('/', ' ', 1), args[0]))
+ print >> stderr, (
+ 'WARNING: / in container name; you might have meant '
+ '%r instead of %r.' % (
+ args[0].replace('/', ' ', 1), args[0]))
container_queue.put((args[0], object_queue, options.prefix))
else:
if len(args) == 2:
@@ -455,34 +478,6 @@ def st_download(parser, args, thread_manager):
for obj in args[1:]:
object_queue.put((args[0], obj))
-
-def prt_bytes(bytes, human_flag):
- """
- convert a number > 1024 to printable format, either in 4 char -h format as
- with ls -lh or return as 12 char right justified string
- """
-
- if human_flag:
- suffix = ''
- mods = 'KMGTPEZY'
- temp = float(bytes)
- if temp > 0:
- while (temp > 1023):
- temp /= 1024.0
- suffix = mods[0]
- mods = mods[1:]
- if suffix != '':
- if temp >= 10:
- bytes = '%3d%s' % (temp, suffix)
- else:
- bytes = '%.1f%s' % (temp, suffix)
- if suffix == '': # must be < 1024
- bytes = '%4s' % bytes
- else:
- bytes = '%12s' % bytes
-
- return(bytes)
-
st_list_options = '''[--long] [--lh] [--totals]
[--container-threads <threads>]
'''
@@ -628,34 +623,7 @@ def st_stat(parser, args, thread_manager):
conn = get_conn(options)
if not args:
try:
- headers = conn.head_account()
- if options.verbose > 1:
- thread_manager.print_msg('''
-StorageURL: %s
-Auth Token: %s
-'''.strip('\n'), conn.url, 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()
- thread_manager.print_msg('''
- Account: %s
-Containers: %d
- Objects: %s
- Bytes: %s'''.strip('\n'), conn.url.rsplit('/', 1)[-1], container_count,
- object_count, bytes_used)
- for key, value in headers.items():
- if key.startswith('x-account-meta-'):
- thread_manager.print_msg(
- '%10s: %s',
- 'Meta %s' % key[len('x-account-meta-'):].title(),
- value)
- for key, value in headers.items():
- if not key.startswith('x-account-meta-') and key not in (
- 'content-length', 'date', 'x-account-container-count',
- 'x-account-object-count', 'x-account-bytes-used'):
- thread_manager.print_msg('%10s: %s', key.title(), value)
+ command_helpers.stat_account(conn, options, thread_manager)
except ClientException as err:
if err.http_status != 404:
raise
@@ -666,75 +634,15 @@ Containers: %d
'meant %r instead of %r.' % \
(args[0].replace('/', ' ', 1), args[0])
try:
- headers = conn.head_container(args[0])
- 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()
- thread_manager.print_msg('''
- Account: %s
-Container: %s
- Objects: %s
- Bytes: %s
- Read ACL: %s
-Write ACL: %s
- Sync To: %s
- Sync Key: %s'''.strip('\n'), conn.url.rsplit('/', 1)[-1], args[0],
- object_count, bytes_used,
- headers.get('x-container-read', ''),
- headers.get('x-container-write', ''),
- headers.get('x-container-sync-to', ''),
- headers.get('x-container-sync-key', ''))
- for key, value in headers.items():
- if key.startswith('x-container-meta-'):
- thread_manager.print_msg(
- '%9s: %s',
- 'Meta %s' % key[len('x-container-meta-'):].title(),
- value)
- for key, value in headers.items():
- if not key.startswith('x-container-meta-') and key not in (
- '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'):
- thread_manager.print_msg('%9s: %s', key.title(), value)
+ command_helpers.stat_container(conn, options, args,
+ thread_manager)
except ClientException as err:
if err.http_status != 404:
raise
thread_manager.error('Container %r not found', args[0])
elif len(args) == 2:
try:
- headers = conn.head_object(args[0], args[1])
- thread_manager.print_msg('''
- Account: %s
- Container: %s
- Object: %s
- Content Type: %s'''.strip('\n'), conn.url.rsplit('/', 1)[-1], args[0],
- args[1], headers.get('content-type'))
- if 'content-length' in headers:
- thread_manager.print_msg('Content Length: %s',
- prt_bytes(headers['content-length'],
- options.human).lstrip())
- if 'last-modified' in headers:
- thread_manager.print_msg(' Last Modified: %s',
- headers['last-modified'])
- if 'etag' in headers:
- thread_manager.print_msg(' ETag: %s', headers['etag'])
- if 'x-object-manifest' in headers:
- thread_manager.print_msg(' Manifest: %s',
- headers['x-object-manifest'])
- for key, value in headers.items():
- if key.startswith('x-object-meta-'):
- thread_manager.print_msg(
- '%14s: %s',
- 'Meta %s' % key[len('x-object-meta-'):].title(),
- value)
- for key, value in headers.items():
- if not key.startswith('x-object-meta-') and key not in (
- 'content-type', 'content-length', 'last-modified',
- 'etag', 'date', 'x-object-manifest'):
- thread_manager.print_msg('%14s: %s', key.title(), value)
+ command_helpers.stat_object(conn, options, args, thread_manager)
except ClientException as err:
if err.http_status != 404:
raise
@@ -807,6 +715,7 @@ def st_post(parser, args, thread_manager):
if not args:
headers = split_headers(
options.meta, 'X-Account-Meta-', thread_manager)
+ headers.update(split_headers(options.header, '', thread_manager))
try:
conn.post_account(headers=headers)
except ClientException as err:
@@ -820,6 +729,7 @@ def st_post(parser, args, thread_manager):
(args[0].replace('/', ' ', 1), args[0])
headers = split_headers(options.meta, 'X-Container-Meta-',
thread_manager)
+ headers.update(split_headers(options.header, '', thread_manager))
if options.read_acl is not None:
headers['X-Container-Read'] = options.read_acl
if options.write_acl is not None:
@@ -1266,7 +1176,7 @@ if __name__ == '__main__':
parser = OptionParser(version='%%prog %s' % version,
usage='''
usage: %%prog [--version] [--help] [--snet] [--verbose]
- [--debug] [--quiet] [--auth <auth_url>]
+ [--debug] [--info] [--quiet] [--auth <auth_url>]
[--auth-version <auth_version>] [--user <username>]
[--key <api_key>] [--retries <num_retries>]
[--os-username <auth-user-name>] [--os-password <auth-password>]
@@ -1285,11 +1195,11 @@ Command-line interface to the OpenStack Swift API.
Positional arguments:
<subcommand>
delete Delete a container or objects within a container
- downlad Download objects from containers
+ download Download objects from containers
list Lists the containers for the account or the objects
for a container
post Updates meta information for the account, container,
- or object
+ or object; creates containers if not present
stat Displays information for the account, container,
or object
upload Uploads files or directories to the given container
@@ -1311,8 +1221,11 @@ Examples:
parser.add_option('-v', '--verbose', action='count', dest='verbose',
default=1, help='Print more info')
parser.add_option('--debug', action='store_true', dest='debug',
- default=False, help='Show the curl commands of all http '
- 'queries.')
+ default=False, help='Show the curl commands and results '
+ 'of all http queries regardless of result status.')
+ parser.add_option('--info', action='store_true', dest='info',
+ default=False, help='Show the curl commands and results '
+ ' of all http queries which return an error.')
parser.add_option('-q', '--quiet', action='store_const', dest='verbose',
const=0, default=1, help='Suppress status output')
parser.add_option('-A', '--auth', dest='auth',
@@ -1434,9 +1347,12 @@ Examples:
signal.signal(signal.SIGINT, immediate_exit)
- if options.debug:
+ if options.debug or options.info:
logger = logging.getLogger("swiftclient")
- logging.basicConfig(level=logging.DEBUG)
+ if options.debug:
+ logging.basicConfig(level=logging.DEBUG)
+ elif options.info:
+ logging.basicConfig(level=logging.INFO)
had_error = False