From 5dddc68b7288afb58e75ef2dac339dbf8c4584d4 Mon Sep 17 00:00:00 2001 From: "Richard (Rick) Hawkins" Date: Fri, 25 Apr 2014 16:05:46 -0500 Subject: [PATCH] Added bulk_delete method to client. Change-Id: Id17870c0780739e8bc9af3895ed9fcac1b1f1620 --- .../objectstorage_api/behaviors.py | 42 +++++++++++++++++++ .../objectstorage/objectstorage_api/client.py | 40 ++++++++++++------ .../objectstorage/objectstorage_api/config.py | 7 ++++ configs/objectstorage/saio.config | 3 ++ 4 files changed, 79 insertions(+), 13 deletions(-) diff --git a/cloudcafe/objectstorage/objectstorage_api/behaviors.py b/cloudcafe/objectstorage/objectstorage_api/behaviors.py index 93ce3b14..e7841976 100644 --- a/cloudcafe/objectstorage/objectstorage_api/behaviors.py +++ b/cloudcafe/objectstorage/objectstorage_api/behaviors.py @@ -360,6 +360,48 @@ class ObjectStorageAPI_Behaviors(BaseBehavior): return response + @behavior(ObjectStorageAPIClient) + def get_object_count(self, container_name, headers=None, params=None, + expected_object_count=None, requestslib_kwargs=None): + """ + Get the number of objects in a container. This method allows for a + success function to be provided, ensuring that the system has + stabilized and become consistent. + + @param container_name: container to list the object from. + @type container_name: string + @param headers: headers to be added to the HTTP request. + @type headers: dictionary + @param params: query string parameters to be added to the HTTP request. + @type params: dictionary + @param expected_object_count: object names expected to be in the + container listing. + @type expected_object_count: int + @param requestslib_kwargs: keyword arguments to be passed on to + python requests. + @type requestslib_kwargs: dictionary + + @return: object listing + @rtype: int + """ + + def success_func(response): + object_count = response.headers.get('x-container-object-count') + if not response.ok or object_count is None: + return False + if expected_object_count != object_count: + return False + return True + + response = self.retry_until_success( + self.client.get_container_metadata, + func_args=[container_name], + func_kwargs={'requestslib_kwargs': requestslib_kwargs}, + success_func=success_func, + timeout=self.config.list_timeout) + + return int(response.headers.get('x-container-object-count')) + @behavior(ObjectStorageAPIClient) def list_objects(self, container_name, headers=None, params=None, expected_objects=None, requestslib_kwargs=None): diff --git a/cloudcafe/objectstorage/objectstorage_api/client.py b/cloudcafe/objectstorage/objectstorage_api/client.py index 852aed65..4615c11a 100644 --- a/cloudcafe/objectstorage/objectstorage_api/client.py +++ b/cloudcafe/objectstorage/objectstorage_api/client.py @@ -16,6 +16,7 @@ limitations under the License. import hmac import requests import tarfile +import urllib from cStringIO import StringIO from datetime import datetime from hashlib import sha1 @@ -368,19 +369,6 @@ class ObjectStorageAPIClient(HTTPClient): return response - def get_object_count(self, container_name, - requestslib_kwargs=None): - """ - Returns the number of objects in a container. - """ - response = self.get_container_metadata( - container_name, - requestslib_kwargs=requestslib_kwargs) - - obj_count = int(response.headers.get('x-container-object-count')) - - return obj_count - #Storage Object------------------------------------------------------------ def get_object(self, container_name, object_name, headers=None, @@ -746,3 +734,29 @@ class ObjectStorageAPIClient(HTTPClient): archive_name) return archive_path + + def bulk_delete(self, targets, headers=None, requestslib_kwargs=None): + """ + Deletes container/objects from an account. + + @type targets: list of strings + @param targets: A list of the '/container/object' or '/container' + to be bulk deleted. Note, bulk delete will not remove + containers that have objects in them, and there is limit of + 1000 containers/objects per delete. + + @rtype: object + @return: The requests response object returned from the call. + """ + if not headers: + headers = {} + url = '{0}{1}'.format(self.storage_url, '?bulk-delete') + data = '\n'.join([urllib.quote(target) for target in targets]) + headers['content-type'] = 'text/plain' + headers['content-length'] = str(len(data)) + + response = self.request( + 'DELETE', url, data=data, headers=headers, + requestslib_kwargs=requestslib_kwargs) + + return response diff --git a/cloudcafe/objectstorage/objectstorage_api/config.py b/cloudcafe/objectstorage/objectstorage_api/config.py index c774bf1a..c47867aa 100644 --- a/cloudcafe/objectstorage/objectstorage_api/config.py +++ b/cloudcafe/objectstorage/objectstorage_api/config.py @@ -216,3 +216,10 @@ class ObjectStorageAPIConfig(ConfigSectionInterface): CORS works more strictly according to the spec. """ return self.get_boolean('strict_cors_mode', True) + + @property + def bulk_delete_max_count(self): + """ + The max number of objects bulk delete can delete. + """ + return int(self.get('bulk_delete_max_count', 1000)) diff --git a/configs/objectstorage/saio.config b/configs/objectstorage/saio.config index 0ea44caa..d901bc00 100644 --- a/configs/objectstorage/saio.config +++ b/configs/objectstorage/saio.config @@ -50,6 +50,9 @@ username=test:tester # but there may be some test cases which warrant ignoring this value. # base_container_name = # +# The max number of objects bulk delete can delete. +# bulk_delete_max_count = 1000 +# # Max object count for a container listing. # container_listing_limit = 10000 #