From c3cef9207b9477f604bedc5780fae60210a60bc5 Mon Sep 17 00:00:00 2001 From: gholt Date: Sun, 5 Jun 2011 23:22:35 +0000 Subject: [PATCH] Adding account_autocreate mode and refactoring TRUE_VALUES --- doc/source/deployment_guide.rst | 4 ++++ etc/proxy-server.conf-sample | 3 +++ swift/common/bench.py | 4 ++-- swift/common/daemon.py | 3 ++- swift/common/middleware/staticweb.py | 2 +- swift/common/utils.py | 2 +- swift/proxy/server.py | 23 ++++++++++++++++++----- swift/stats/log_uploader.py | 2 +- 8 files changed, 32 insertions(+), 11 deletions(-) diff --git a/doc/source/deployment_guide.rst b/doc/source/deployment_guide.rst index 52a4f80f6e..04b99fa1f6 100644 --- a/doc/source/deployment_guide.rst +++ b/doc/source/deployment_guide.rst @@ -547,6 +547,10 @@ error_suppression_limit 10 Error count to consider a node error limited allow_account_management false Whether account PUTs and DELETEs are even callable +account_autocreate false If set to 'true' authorized + accounts that do not yet exist + within the Swift cluster will + be automatically created. ============================ =============== ============================= [tempauth] diff --git a/etc/proxy-server.conf-sample b/etc/proxy-server.conf-sample index fef0e81fa0..496eb4aea1 100644 --- a/etc/proxy-server.conf-sample +++ b/etc/proxy-server.conf-sample @@ -40,6 +40,9 @@ use = egg:swift#proxy # If set to 'true' any authorized user may create and delete accounts; if # 'false' no one, even authorized, can. # allow_account_management = false +# If set to 'true' authorized accounts that do not yet exist within the Swift +# cluster will be automatically created. +# account_autocreate = false [filter:tempauth] use = egg:swift#tempauth diff --git a/swift/common/bench.py b/swift/common/bench.py index 28d8c7e8d9..51e39f793d 100644 --- a/swift/common/bench.py +++ b/swift/common/bench.py @@ -43,7 +43,7 @@ class Bench(object): self.user = conf.user self.key = conf.key self.auth_url = conf.auth - self.use_proxy = conf.use_proxy in TRUE_VALUES + self.use_proxy = conf.use_proxy.lower() in TRUE_VALUES if self.use_proxy: url, token = client.get_auth(self.auth_url, self.user, self.key) self.token = token @@ -125,7 +125,7 @@ class BenchController(object): self.logger = logger self.conf = conf self.names = [] - self.delete = conf.delete in TRUE_VALUES + self.delete = conf.delete.lower() in TRUE_VALUES self.gets = int(conf.num_gets) def run(self): diff --git a/swift/common/daemon.py b/swift/common/daemon.py index 96914d9510..abcc8dea1e 100644 --- a/swift/common/daemon.py +++ b/swift/common/daemon.py @@ -75,7 +75,8 @@ def run_daemon(klass, conf_file, section_name='', once=False, **kwargs): log_name=kwargs.get('log_name')) # once on command line (i.e. daemonize=false) will over-ride config - once = once or conf.get('daemonize', 'true') not in utils.TRUE_VALUES + once = once or \ + conf.get('daemonize', 'true').lower() not in utils.TRUE_VALUES # pre-configure logger if 'logger' in kwargs: diff --git a/swift/common/middleware/staticweb.py b/swift/common/middleware/staticweb.py index 8e58ad5068..81225a90ea 100644 --- a/swift/common/middleware/staticweb.py +++ b/swift/common/middleware/staticweb.py @@ -270,7 +270,7 @@ class StaticWeb(object): :param start_response: The original WSGI start_response hook. :param prefix: Any prefix desired for the container listing. """ - if self._listings not in TRUE_VALUES: + if self._listings.lower() not in TRUE_VALUES: resp = HTTPNotFound()(env, self._start_response) return self._error_response(resp, env, start_response) tmp_env = self._get_escalated_env(env) diff --git a/swift/common/utils.py b/swift/common/utils.py index 4ee57db8f7..ac18331703 100644 --- a/swift/common/utils.py +++ b/swift/common/utils.py @@ -72,7 +72,7 @@ if hash_conf.read('/etc/swift/swift.conf'): pass # Used when reading config values -TRUE_VALUES = set(('true', '1', 'yes', 'True', 'Yes', 'on', 'On', 't', 'y')) +TRUE_VALUES = set(('true', '1', 'yes', 'on', 't', 'y')) def validate_configuration(): diff --git a/swift/proxy/server.py b/swift/proxy/server.py index 3300e7a384..01e33d8498 100644 --- a/swift/proxy/server.py +++ b/swift/proxy/server.py @@ -41,8 +41,8 @@ from webob.exc import HTTPBadRequest, HTTPMethodNotAllowed, \ from webob import Request, Response from swift.common.ring import Ring -from swift.common.utils import get_logger, normalize_timestamp, split_path, \ - cache_from_env, ContextPool +from swift.common.utils import cache_from_env, ContextPool, get_logger, \ + normalize_timestamp, split_path, TRUE_VALUES from swift.common.bufferedhttp import http_connect from swift.common.constraints import check_metadata, check_object_creation, \ check_utf8, CONTAINER_LISTING_LIMIT, MAX_ACCOUNT_NAME_LENGTH, \ @@ -353,7 +353,7 @@ class Controller(object): result_code = self.app.memcache.get(cache_key) if result_code == 200: return partition, nodes - elif result_code == 404: + elif result_code == 404 and not self.app.account_autocreate: return None, None result_code = 0 attempts_left = self.app.account_ring.replica_count @@ -386,6 +386,17 @@ class Controller(object): except (Exception, TimeoutError): self.exception_occurred(node, _('Account'), _('Trying to get account info for %s') % path) + if result_code == 404: + if self.app.account_autocreate: + if len(account) > MAX_ACCOUNT_NAME_LENGTH: + return None, None + headers = {'X-Timestamp': normalize_timestamp(time.time()), + 'x-trans-id': self.trans_id} + resp = self.make_requests(Request.blank('/v1' + path), + self.app.account_ring, partition, 'PUT', + path, [headers] * len(nodes)) + if resp.status_int // 100 == 2: + result_code = 200 if self.app.memcache and result_code in (200, 404): if result_code == 200: cache_timeout = self.app.recheck_account_existence @@ -1391,7 +1402,7 @@ class BaseApplication(object): self.put_queue_depth = int(conf.get('put_queue_depth', 10)) self.object_chunk_size = int(conf.get('object_chunk_size', 65536)) self.client_chunk_size = int(conf.get('client_chunk_size', 65536)) - self.log_headers = conf.get('log_headers') == 'True' + self.log_headers = conf.get('log_headers', 'no').lower() in TRUE_VALUES self.error_suppression_interval = \ int(conf.get('error_suppression_interval', 60)) self.error_suppression_limit = \ @@ -1401,7 +1412,7 @@ class BaseApplication(object): self.recheck_account_existence = \ int(conf.get('recheck_account_existence', 60)) self.allow_account_management = \ - conf.get('allow_account_management', 'false').lower() == 'true' + conf.get('allow_account_management', 'no').lower() in TRUE_VALUES self.resellers_conf = ConfigParser() self.resellers_conf.read(os.path.join(swift_dir, 'resellers.conf')) self.object_ring = object_ring or \ @@ -1413,6 +1424,8 @@ class BaseApplication(object): self.memcache = memcache mimetypes.init(mimetypes.knownfiles + [os.path.join(swift_dir, 'mime.types')]) + self.account_autocreate = \ + conf.get('account_autocreate', 'no').lower() in TRUE_VALUES def get_controller(self, path): """ diff --git a/swift/stats/log_uploader.py b/swift/stats/log_uploader.py index 6051107a86..ea51061d54 100644 --- a/swift/stats/log_uploader.py +++ b/swift/stats/log_uploader.py @@ -69,7 +69,7 @@ class LogUploader(Daemon): self.internal_proxy = InternalProxy(proxy_server_conf) self.new_log_cutoff = int(cutoff or uploader_conf.get('new_log_cutoff', '7200')) - self.unlink_log = uploader_conf.get('unlink_log', 'True').lower() in \ + self.unlink_log = uploader_conf.get('unlink_log', 'true').lower() in \ utils.TRUE_VALUES self.filename_pattern = regex or \ uploader_conf.get('source_filename_pattern',