#!/usr/bin/python # # Ceph - scalable distributed file system # # Copyright (C) 2011 New Dream Network # # This is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License version 2.1, as published by the Free Software # Foundation. See file COPYING. # """ boto_tool.py: s3cmd-like tool for operating on s3 A lot of common s3 clients can't handle weird names. But this little script can do it! """ from boto.s3.connection import OrdinaryCallingFormat from boto.s3.connection import S3Connection from boto.s3.key import Key from optparse import OptionParser from sys import stderr import ast import ConfigParser import boto import os import string import sys def list_all_buckets(conn, opts): blrs = conn.get_all_buckets() for b in blrs: if (opts.verbose): print b.__dict__ else: print b def list_objects(conn, opts): if opts.list_objects == True: prefix = None else: prefix = opts.list_objects bucket = conn.get_bucket(opts.bucket_name) for key in bucket.list(prefix = prefix): print key.name def mkbucket(conn, opts): print "creating bucket '%s' ..." % opts.bucket_name bucket = conn.create_bucket(opts.bucket_name) print "done." return 0 def rmobjects(conn, opts): bucket = conn.get_bucket(opts.bucket_name) print "deleting all objects from bucket '%s' ..." % opts.bucket_name bucket = conn.get_bucket(opts.bucket_name) for key in bucket.list(): print key.name bucket.delete_key(key) print "done." return 0 def rmbucket(conn, opts): bucket = conn.get_bucket(opts.bucket_name) print "deleting bucket '%s' ..." % opts.bucket_name bucket.delete() print "done." return 0 def get_bucket_acl(conn, opts): bucket = conn.get_bucket(opts.bucket_name) print "getting bucket acl..." xml = bucket.get_xml_acl() if (opts.getacl_file == "-"): print xml else: f = open(opts.getacl_file, "w") try: f.write(xml) finally: f.close() def put_bucket_acl(conn, opts): bucket = conn.get_bucket(opts.bucket_name) print "setting bucket acl..." f = open(opts.putacl_file, "r") try: xml = f.read() finally: f.close() bucket.set_xml_acl(xml) return 0 def bucket_exists(conn, opts): bucket = conn.get_bucket(opts.bucket_name) if (bucket == None): print "bucket '%s' does not exist" % opts.bucket_name return 1 else: print "found bucket '%s'." % opts.bucket_name if (opts.verbose): print bucket.__dict__ return 0 def put_obj(conn, opts): if (opts.xattr == None): xattr = {} else: xattr = ast.literal_eval(opts.xattr) if not type(xattr) is dict: raise "You must supply a dictionary of xattr names to xattr " + \ "values. Example. \"{\"foo\" : \"bar\"}\"" print "uploading to bucket: '%s', object name: '%s' \ xattr: '%s'" % (opts.bucket_name, opts.obj_name, str(xattr)) bucket = conn.get_bucket(opts.bucket_name) k = Key(bucket) k.key = opts.obj_name k.metadata = xattr k.set_contents_from_filename(opts.put_file) return 0 def put_obj_acl(conn, opts): print "uploading object ACL to bucket: '%s', object name: '%s'" \ % (opts.bucket_name, opts.obj_name) bucket = conn.get_bucket(opts.bucket_name) k = Key(bucket) k.key = opts.obj_name f = open(opts.putacl_file, "r") try: xml = f.read() finally: f.close() k.set_xml_acl(xml) return 0 def get_obj(conn, opts): print "downloading from bucket: '%s', object name: '%s'" % \ (opts.bucket_name, opts.obj_name) bucket = conn.get_bucket(opts.bucket_name) k = Key(bucket) k.key = opts.obj_name if (opts.get_file == "-"): k.get_contents_to_file(sys.stdout) else: k.get_contents_to_filename(opts.get_file) return 0 def get_obj_acl(conn, opts): print "downloading object acl from bucket: '%s', object name: '%s'" % \ (opts.bucket_name, opts.obj_name) bucket = conn.get_bucket(opts.bucket_name) k = Key(bucket) k.key = opts.obj_name xml = k.get_xml_acl() if (opts.getacl_file == "-"): print xml else: f = open(opts.getacl_file, "w") try: f.write(xml) finally: f.close() def rm_obj(conn, opts): print "removing from bucket: '%s', object name: '%s'" \ % (opts.bucket_name, opts.obj_name) bucket = conn.get_bucket(opts.bucket_name) bucket.delete_key(opts.obj_name) print "done." return 0 def head_obj(conn, opts): print "downloading from bucket: '%s', object name: '%s'" \ % (opts.bucket_name, opts.obj_name) bucket = conn.get_bucket(opts.bucket_name) k = bucket.get_key(opts.obj_name) print k def get_obj_xattr(conn, opts): print "downloading object xattr. bucket: '%s', object name: '%s'" % \ (opts.bucket_name, opts.obj_name) bucket = conn.get_bucket(opts.bucket_name) k = bucket.get_key(opts.obj_name) print k.metadata def get_obj_xattr(conn, opts): print "downloading object xattr. bucket: '%s', object name: '%s'" % \ (opts.bucket_name, opts.obj_name) bucket = conn.get_bucket(opts.bucket_name) k = bucket.get_key(opts.obj_name) print k.metadata ########################## main ########################## host = None aws_access_key_id = None secret_key = None USAGE = """ boto_tool.py is a simple S3 client that can be used for testing. It uses libboto. ENVIRONMENT VARIABLES S3TEST_CONF: if this is set, we'll get the host, access key, and secret key from this file. AKEY AWS access key SKEY AWS secret access key""" parser = OptionParser(USAGE) parser.add_option("-b", "--bucket-name", dest="bucket_name", help="specify bucket name") parser.add_option("-l", "--list-objects", action="store_true", \ dest="list_objects", help="list all objects") parser.add_option("-L", "--list-objects-with-prefix", dest="list_objects", help="list all objects with the given prefix") parser.add_option("--mkbucket", action="store_true", dest="mkbucket", help="create a bucket") parser.add_option("--rmbucket", action="store_true", dest="rmbucket", help="remove a bucket") parser.add_option("-o", "--object-name", dest="obj_name", help="object name") parser.add_option("--put", dest="put_file", help="put FILE") parser.add_option("--xattr", dest="xattr", help="xattrs to use") parser.add_option("--get", dest="get_file", help="get to FILE") parser.add_option("--rm", action="store_true", dest="rm", help="remove an object") parser.add_option("--rmobjects", action="store_true", dest="rmobjects", help="remove all objects from a bucket") parser.add_option("--rm_rf", action="store_true", dest="rm_rf", help="remove all objects from a bucket and remove the bucket") parser.add_option("--head", action="store_true", dest="head", help="use the HEAD operation to find out about an object") parser.add_option("--putacl", dest="putacl_file", help="set XML acl from FILE") parser.add_option("--getacl", dest="getacl_file", help="dump XML acl into FILE") parser.add_option("--get-obj-xattr", action="store_true", dest="get_obj_xattr", help="print the object's xattrs") parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="be verbose") (opts, args) = parser.parse_args() if os.environ.has_key("S3TEST_CONF"): # use S3TEST_CONF path = os.environ["S3TEST_CONF"] cfg = ConfigParser.RawConfigParser() with file(path) as f: cfg.readfp(f) host = cfg.get("DEFAULT", "host") aws_access_key_id = cfg.get("s3 main", "access_key") secret_key = cfg.get("s3 main", "secret_key") elif len(args) < 1: print >>stderr, "boto_tool: You must specify an action. Try --help." sys.exit(1) else: # use environment variables and command line host = args[0] aws_access_key_id=os.environ["AKEY"] secret_key=os.environ["SKEY"] conn = S3Connection(calling_format=OrdinaryCallingFormat(), is_secure=False, host = host, aws_access_key_id=aws_access_key_id, aws_secret_access_key=secret_key) if not opts.bucket_name: sys.exit(list_all_buckets(conn, opts)) elif opts.list_objects: sys.exit(list_objects(conn, opts)) elif opts.mkbucket: sys.exit(mkbucket(conn, opts)) elif opts.rmobjects: sys.exit(rmobjects(conn, opts)) elif opts.rm_rf: ret =rmobjects(conn, opts) if (ret): sys.exit(ret) ret = rmbucket(conn, opts) sys.exit(ret) elif opts.rmbucket: sys.exit(rmbucket(conn, opts)) elif not opts.obj_name: if opts.getacl_file: sys.exit(get_bucket_acl(conn, opts)) elif opts.putacl_file: sys.exit(put_bucket_acl(conn, opts)) else: sys.exit(bucket_exists(conn, opts)) elif opts.put_file: sys.exit(put_obj(conn, opts)) elif opts.get_file: sys.exit(get_obj(conn, opts)) elif opts.rm: sys.exit(rm_obj(conn, opts)) elif opts.head: sys.exit(head_obj(conn, opts)) elif opts.putacl_file: sys.exit(put_obj_acl(conn, opts)) elif opts.getacl_file: sys.exit(get_obj_acl(conn, opts)) elif opts.get_obj_xattr: sys.exit(get_obj_xattr(conn, opts)) elif opts.head: sys.exit(head_obj(conn, opts)) else: print "unknown arguments. Try --help" sys.exit(255)