files/default/rgw_s3_api.py (202 lines of code) (raw):

#!/usr/bin/env python # # Author: Hans Chris Jones <chris.jones@lambdastack.io> # # Copyright 2017, Bloomberg Finance L.P. # # 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. # import math import glob import os from os import listdir from os.path import isfile, join import boto import boto.s3.connection from boto.s3.connection import Location from boto.s3.bucket import Bucket # NOTE: Modify these values with your key, secret and url/ip for s3 endpoint access_key = "<whatever your access_key is>" secret_key = "<whatever your secret_key is>" endpoint = "<whatever your s3 url or IP is>" admin_user = "<whatever your RGW admin user is>" # NOTE: Add the proxy if you need one. def connect(key, secret, host, proxy=None, user_agent=None, port=80, proxy_port=8080, is_secure=False, debug=0, verbose=False): conn = None try: conn = boto.connect_s3( aws_access_key_id=key, aws_secret_access_key=secret, port=port, host=host, proxy=proxy, proxy_port=proxy_port, is_secure=is_secure, calling_format=boto.s3.connection.OrdinaryCallingFormat(), debug=debug) if conn and verbose: print('RGW Connected.') except BaseException, e: print(e.message) return conn def bucket_handle(conn, bucket_name, validate=True, headers=None, create=False, make_public=False, verbose=False): if not conn or not bucket_name: if verbose: print('Connection and/or bucket name not valid - unable to get handle.') return None bucket = None try: bucket = conn.lookup(bucket_name, validate=validate, headers=headers) if not bucket and create: bucket = bucket_create(conn, bucket_name, headers=headers, make_public=make_public, verbose=verbose) # add policy for acls if bucket: if verbose: print('Bucket %s created.' % bucket_name) else: if verbose: print('Bucket %s not created.' % bucket_name) else: if verbose: print('Bucket %s found.' % bucket_name) if bucket and make_public: # temporary... bucket.make_public(recursive=False, headers=headers) if verbose: print('Bucket %s made public.' % bucket_name) except BaseException, e: print(e.message) return bucket def bucket_create(conn, bucket_name, location=Location.DEFAULT, policy=None, headers=None, make_public=False, verbose=False): if not conn or not bucket_name: if verbose: print('Connection and/or bucket name not valid - unable to create.') return None bucket = None try: bucket = conn.create_bucket(bucket_name, location=location, policy=policy, headers=headers) if make_public: bucket.make_public(recursive=True, headers=headers) if bucket and verbose: print('Bucket %s created.' % bucket_name) except BaseException, e: print(e.message) return bucket def bucket_list(bucket, verbose=False): if not bucket: if verbose: print('Bucket handle not valid.') return None try: for i in bucket.list(): obj_name = i.key.split("/")[-1] # i.name # i.key.split("/")[-1] size = i.size # i.get_contents_to_filename(obj_name) print('%s: %d' % (obj_name, size)) except BaseException, e: print(e.message) return None # This is only a debug test function... def object_create(bucket, name, string_value=None, file_name_path=None, make_public=False, headers=None, verbose=False): if not bucket or not name or (string_value is None and file_name_path is None): if verbose: print('Bucket handle not valid OR string_value or file_name is empty.') return None key = None try: key = bucket.get_key(name) if not key: key = bucket.new_key(name) if key: if string_value: key.set_contents_from_string(string_value) if file_name_path: # Check the size of the file. If it's larger than xxx then do a multipart else do a normal set_content key.set_contents_from_filename(file_name_path) if key and make_public: key.make_public(headers=headers) if verbose: print('Object %s created/updated.' % name) else: if verbose: print('Object %s was not created/updated.' % name) except BaseException, e: print(e.message) return key def object_delete(bucket, name, headers=None, version_id=None, mfa_token=None, verbose=False): if not bucket or not name: if verbose: print('Bucket and/or object name is not valid.') return None key_object = None try: key_object = bucket.delete_key(name, headers=headers, version_id=version_id, mfa_token=mfa_token) if verbose: print('Object %s deleted.' % name) except BaseException, e: print(e.message) return key_object def object_get(bucket, name, file_name_path, headers=None, version_id=None, response_headers=None, verbose=False): if not bucket or not name: if verbose: print('Bucket and/or object name is not valid.') return None if not file_name_path: file_name_path = name key_object = None try: key_object = bucket.get_key(name, headers=headers, version_id=version_id, response_headers=response_headers) key_object.get_contents_to_filename(file_name_path) if verbose: print('Retrieved object %s.' % name) except BaseException, e: print(e.message) return key_object def object_url(bucket, name, signed_duration=0, query_auth=False, force_http=False, verbose=False): """ :param bucket: :param name: :param signed_duration: :param query_auth: :param force_http: default is False so that the port is included if the port is not 80 :param verbose: :return: url """ if not bucket or not name: if verbose: print('Bucket and/or object name is not valid.') return None url = None try: if signed_duration < 0: signed_duration = 0 if signed_duration > 0 and query_auth is False: query_auth = True key_object = bucket.get_key(name) # If the signed_duration is > than 0 then assume a signed url with signed_duration the amount of time the url # is valid. url = key_object.generate_url(signed_duration, query_auth=query_auth, force_http=force_http) if url and verbose: print('Generated %s' % url) except BaseException, e: print(e.message) return url def upload_directory(bucket, directory, pattern='*', include_dir_prefix=False, make_public=False, verbose=False): if not bucket or not directory: if verbose: print('Bucket and/or directory name is not valid.') return None # One way # files = [f for f in listdir(directory) if isfile(join(directory, f))] # Using glob allows for simple patterns and no hidden files... files = glob.glob(os.path.join(directory, pattern)) files = [f for f in files if isfile(f)] # Scrub the list for only files file_names = [f.split('/')[-1] for f in files] if verbose: print('Directory list obtained and scrubbed.') key_objects = [] count = 0 for file_name in file_names: key_objects.append(object_create(bucket, file_name, file_name_path=files[count], make_public=make_public, verbose=verbose)) if verbose: print('File: %s uploaded.' % file_name) count += 1 return key_objects # NB: Create a Tenancy (user) using the RGW API which is part of RGW on the same port(s). # NB: *MUST USE* user with admin caps such as the default 'radosgw' user ceph-chef creates by default. def user_create(conn, admin_user, user_name, display_name, caps=None, verbose=False): if not conn or not user_name: if verbose: print('Connection and/or user name not valid - unable to create.') return None user = None try: print "/%s/user?format=json&uid=%s&display-name='%s'" % (admin_user, user_name, display_name) resp = conn.make_request("PUT", query_args="/%s/user?format=json&uid=%s&display-name='%s'" % (admin_user, user_name, display_name)) if resp: print resp.status print resp.read() if user and verbose: print('User %s created.' % user_name) except BaseException, e: print(e.message) return user def main(): # NOTE: This is just a number of samples that can be called via the cli. However, the primary purpose of this # are the functions defined above which are imported into rgw-admin.py conn = connect(key, secret, is_secure=False, verbose=True) # debug=2 Add more options later... # Sample header for object_get # headers={'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'en-US,en;q=0.8'} bucket = bucket_handle(conn, 'bcs-test', make_public=True, validate=True, create=True, verbose=True) object_create(bucket, 'hello1.txt', string_value='Hello everyone :)', make_public=True, verbose=True) # file_name_path = 'eabbcab9-1d30-4218-ad78-640f234463d0_2400.mp4' # file_name = file_name_path.split('/')[-1] # object_create(bucket,file_name, file_name_path=file_name_path, make_public=True, verbose=True) bucket_list(bucket, verbose=True) # object_delete(bucket, 'hello.txt', verbose=True) # Example usage: key_object = object_get(bucket, 'hello1.txt', 'hello1.txt', verbose=True) # upload_directory(bucket, '<directory>', make_public=True, verbose=True) # print object_url(bucket, 'test_video.mp4') print object_url(bucket, 'hello1.txt', signed_duration=60) if __name__ == "__main__": main()