Skip to content

Commit 2d0041a

Browse files
committed
Allow to use bucket storage policy
1 parent 5820e7b commit 2d0041a

File tree

4 files changed

+86
-22
lines changed

4 files changed

+86
-22
lines changed

conf/default.cfg

+8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ sds_default_account = myaccount
4343
# backend.
4444
oio_storage_policies=SINGLE,EC123,EC64,THREECOPIES,FOURCOPIES
4545

46+
# Enable or disable the use of bucket storage policy.
47+
# When enabled, and if a storage policy is defined for a bucket (root container),
48+
# all objects in this bucket will be uploaded with this storage policy.
49+
# NOTE: The bucket storage policy can optionally be kept in the cache with its old
50+
# value. To force the update of this value, it is enough to modify a property
51+
# of this bucket via the AWS CLI (for example: add a tag).
52+
# use_bucket_storage_policy = false
53+
4654
# The configuration to chose the policy when unspecified. All the storage
4755
# policies mentioned here must have been listed in the `oio_storage_policies`
4856
# configuration directive. The string must respect the subsequent format:

oioswift/proxy/controllers/container.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -376,12 +376,15 @@ def POST(self, req):
376376
clear_info_cache(self.app, req.environ,
377377
self.account_name, self.container_name)
378378

379-
memcache = getattr(self.app, 'memcache', None) or \
380-
req.environ.get('swift.cache')
381-
if memcache is not None:
382-
key = "/".join(("versioning", self.account_name,
383-
self.container_name))
384-
memcache.delete(key)
379+
if req.environ.get('oio.cache') is None:
380+
memcache = getattr(self.app, 'memcache', None) or \
381+
req.environ.get('swift.cache')
382+
if memcache is not None:
383+
for memcache_prefix in ("versioning", "storage_policy"):
384+
memcache_key = "/".join(
385+
(memcache_prefix, self.account_name,
386+
self.container_name))
387+
memcache.delete(memcache_key)
385388

386389
resp = self.get_container_post_resp(req, headers)
387390
return resp

oioswift/proxy/controllers/obj.py

+66-16
Original file line numberDiff line numberDiff line change
@@ -213,20 +213,68 @@ def enforce_versioning(self, req):
213213

214214
# We can't use _get_info_from_caches as it would use local worker cache
215215
# first and an update of versioning mode may not be detected.
216-
memcache = getattr(self.app, 'memcache', None) or \
217-
req.environ.get('swift.cache')
218-
if memcache is None:
216+
oio_cache = req.environ.get('oio.cache')
217+
memcache = None
218+
if oio_cache is None:
219+
memcache = getattr(self.app, 'memcache', None) or \
220+
req.environ.get('swift.cache')
221+
222+
if memcache is not None:
223+
memcache_key = "/".join(
224+
("versioning", self.account_name, root_container))
225+
version_policy = memcache.get(memcache_key)
226+
if version_policy is not None:
227+
if version_policy:
228+
req.headers[FORCEVERSIONING_HEADER] = version_policy
229+
return
230+
231+
oio_headers = {REQID_HEADER: self.trans_id}
232+
perfdata = req.environ.get('oio.perfdata')
233+
try:
234+
meta = self.app.storage.container_get_properties(
235+
self.account_name, root_container, headers=oio_headers,
236+
cache=oio_cache, perfdata=perfdata)
237+
except exceptions.NoSuchContainer:
238+
raise HTTPNotFound(request=req)
239+
240+
version_policy = meta['system'].get('sys.m2.policy.version')
241+
if memcache is not None:
242+
memcache.set(memcache_key, version_policy or '')
243+
if version_policy:
244+
req.headers[FORCEVERSIONING_HEADER] = version_policy
245+
246+
def use_bucket_storage_policy(self, req):
247+
"""
248+
Enforce the storage policy mode of a container just before executing
249+
an object operation. This is useful when the current object is not
250+
stored in the "main" container but in a shard,
251+
where the storage policy mode may not have been set yet.
252+
"""
253+
if not self.app.use_bucket_storage_policy:
254+
return None
255+
256+
root_container = req.headers.get(BUCKET_NAME_HEADER)
257+
if root_container is None:
219258
return None
259+
if root_container.endswith(MULTIUPLOAD_SUFFIX):
260+
root_container = root_container[:-len(MULTIUPLOAD_SUFFIX)]
220261

221-
key = "/".join(("versioning", self.account_name, root_container))
222-
val = memcache.get(key)
223-
if val is not None:
224-
if val != '':
225-
req.headers[FORCEVERSIONING_HEADER] = val
226-
return
262+
# We can't use _get_info_from_caches as it would use local worker cache
263+
# first and an update of storage policy mode may not be detected.
264+
oio_cache = req.environ.get('oio.cache')
265+
memcache = None
266+
if oio_cache is None:
267+
memcache = getattr(self.app, 'memcache', None) or \
268+
req.environ.get('swift.cache')
269+
270+
if memcache is not None:
271+
memcache_key = "/".join(
272+
("storage_policy", self.account_name, root_container))
273+
storage_policy = memcache.get(memcache_key)
274+
if storage_policy is not None:
275+
return storage_policy or None
227276

228277
oio_headers = {REQID_HEADER: self.trans_id}
229-
oio_cache = req.environ.get('oio.cache')
230278
perfdata = req.environ.get('oio.perfdata')
231279
try:
232280
meta = self.app.storage.container_get_properties(
@@ -235,10 +283,10 @@ def enforce_versioning(self, req):
235283
except exceptions.NoSuchContainer:
236284
raise HTTPNotFound(request=req)
237285

238-
val = meta['system'].get('sys.m2.policy.version', '')
239-
memcache.set(key, val)
240-
if val:
241-
req.headers[FORCEVERSIONING_HEADER] = val
286+
storage_policy = meta['system'].get('sys.m2.policy.storage')
287+
if memcache is not None:
288+
memcache.set(memcache_key, storage_policy or '')
289+
return storage_policy
242290

243291
def get_object_head_resp(self, req):
244292
storage = self.app.storage
@@ -647,15 +695,15 @@ def _object_create(self, account, container, **kwargs):
647695
def _store_object(self, req, data_source, headers):
648696
content_type = req.headers.get('content-type', 'octet/stream')
649697
policy = None
650-
container_info = self.container_info(self.account_name,
651-
self.container_name, req)
652698
if 'X-Oio-Storage-Policy' in req.headers:
653699
policy = req.headers.get('X-Oio-Storage-Policy')
654700
if not self.app.POLICIES.get_by_name(policy):
655701
raise HTTPBadRequest(
656702
"invalid policy '%s', must be in %s" %
657703
(policy, self.app.POLICIES.by_name.keys()))
658704
else:
705+
container_info = self.container_info(self.account_name,
706+
self.container_name, req)
659707
try:
660708
policy_index = int(
661709
req.headers.get('X-Backend-Storage-Policy-Index',
@@ -665,6 +713,8 @@ def _store_object(self, req, data_source, headers):
665713
if policy_index != 0:
666714
policy = self.app.POLICIES.get_by_index(policy_index).name
667715
else:
716+
policy = self.use_bucket_storage_policy(req)
717+
if policy is None:
668718
content_length = int(req.headers.get('content-length', 0))
669719
policy = self._get_auto_policy_from_size(content_length)
670720

oioswift/server.py

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ def __init__(self, conf, memcache=None, logger=None, account_ring=None,
5959
for k, v in conf.iteritems()
6060
if k.startswith("sds_")}
6161

62+
self.use_bucket_storage_policy = config_true_value(
63+
conf.get('use_bucket_storage_policy', 'false'))
64+
6265
self.oio_stgpol = []
6366
if 'auto_storage_policies' in conf:
6467
for elem in conf['auto_storage_policies'].split(','):

0 commit comments

Comments
 (0)