diff options
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/swift | 190 |
1 files changed, 53 insertions, 137 deletions
@@ -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 |