diff options
author | Prashanth Pai <ppai@redhat.com> | 2015-11-02 11:55:17 +0530 |
---|---|---|
committer | Thiago da Silva <thiago@redhat.com> | 2016-03-07 10:38:49 -0800 |
commit | ea4750a366123f78411d90082733642376dc6afc (patch) | |
tree | 5124b5a407791afcd2dd1cfef00a3959cbb26033 /gluster/swift/common | |
parent | c5d76cdd2e2e99d4ac65b645b17cf8a43e4ccab4 (diff) |
Rebase to stable/kilo
This change ports most of swiftonfile object server fixes and changes
into gluster-swift. Storage policy as a feature is not usable here
(it doesn't make sense).
The hacky way of creating zero byte tracker objects for object
expiration has not been ported to this release due to scalability
issues and the need to have a separate volume.
Change-Id: I17ba27dacea9ac000bdb8934700996e4d17f4251
Signed-off-by: Prashanth Pai <ppai@redhat.com>
Reviewed-on: http://review.gluster.org/13269
Reviewed-by: Thiago da Silva <thiago@redhat.com>
Tested-by: Thiago da Silva <thiago@redhat.com>
Diffstat (limited to 'gluster/swift/common')
-rw-r--r-- | gluster/swift/common/DiskDir.py | 90 | ||||
-rw-r--r-- | gluster/swift/common/Glusterfs.py | 2 | ||||
-rw-r--r-- | gluster/swift/common/middleware/gswauth/swauth/middleware.py | 1 | ||||
-rw-r--r-- | gluster/swift/common/utils.py | 41 |
4 files changed, 105 insertions, 29 deletions
diff --git a/gluster/swift/common/DiskDir.py b/gluster/swift/common/DiskDir.py index 6112709..e8dba35 100644 --- a/gluster/swift/common/DiskDir.py +++ b/gluster/swift/common/DiskDir.py @@ -255,7 +255,7 @@ class DiskDir(DiskCommon): :param uid: user ID container object should assume :param gid: group ID container object should assume - Usage pattern from container/server.py (Havana, 1.8.0+): + Usage pattern from container/server.py (Kilo, 2.3.0): DELETE: if auto-create and obj and not .db_file: # Creates container @@ -287,36 +287,43 @@ class DiskDir(DiskCommon): return 404 .put_object() else: - if not .db_file: - # Creates container - .initialize() - else: - # Update container timestamp - .is_deleted() + _update_or_create(): + if not .db_file: + # Creates container + .initialize() + recreated = .is_deleted(): + if recreated: + .set_storage_policy_index() + .storage_policy_index .update_put_timestamp() if .is_deleted() return conflict - if metadata: + if recreated: + .update_status_changed_at() + + if 'X-Container-Sync-To' in metadata: if .metadata .set_x_container_sync_points() .update_metadata() account_update(): .get_info() HEAD: - .pending_timeout - .stale_reads_ok - if .is_deleted(): - return 404 - .get_info() + info, is_deleted = .get_info_is_deleted() + .get_info_is_deleted(): + if not .db_file: + return {}, True + info = .get_info() + return info, ._is_deleted_info() .metadata GET: - .pending_timeout - .stale_reads_ok - if .is_deleted(): - return 404 - .get_info() - .metadata + info, is_deleted = .get_info_is_deleted() + .get_info_is_deleted(): + if not .db_file: + return {}, True + info = .get_info() + return info, ._is_deleted_info() .list_objects_iter() + .metadata POST: if .is_deleted(): return 404 @@ -346,8 +353,22 @@ class DiskDir(DiskCommon): create_container_metadata(self.datadir) self.metadata = _read_metadata(self.datadir) + def update_status_changed_at(self, timestamp): + return + + @property + def storage_policy_index(self): + if not hasattr(self, '_storage_policy_index'): + self._storage_policy_index = \ + self.get_info()['storage_policy_index'] + return self._storage_policy_index + + def set_storage_policy_index(self, policy_index, timestamp=None): + self._storage_policy_index = policy_index + def list_objects_iter(self, limit, marker, end_marker, - prefix, delimiter, path=None): + prefix, delimiter, path=None, + storage_policy_index=0): """ Returns tuple of name, created_at, size, content_type, etag. """ @@ -451,6 +472,12 @@ class DiskDir(DiskCommon): return objects + def get_info_is_deleted(self): + if not do_exists(self.datadir): + return {}, True + info = self.get_info() + return info, False + def get_info(self): """ Get global data for the container. @@ -477,7 +504,10 @@ class DiskDir(DiskCommon): 'x_container_sync_point1', -1), 'x_container_sync_point2': self.metadata.get( 'x_container_sync_point2', -1), + 'storage_policy_index': self.metadata.get( + 'storage_policy_index', 0) } + self._storage_policy_index = data['storage_policy_index'] return data def put_object(self, name, timestamp, size, content_type, etag, deleted=0): @@ -540,13 +570,14 @@ class DiskDir(DiskCommon): class DiskAccount(DiskCommon): """ - Usage pattern from account/server.py (Havana, 1.8.0+): + Usage pattern from account/server.py (Kilo, 2.3.0): DELETE: .is_deleted() + .is_status_deleted() .delete_db() + .is_status_deleted() PUT: container: - .pending_timeout .db_file .initialize() .is_deleted() @@ -555,25 +586,27 @@ class DiskAccount(DiskCommon): .db_file .initialize() .is_status_deleted() + .is_status_deleted() .is_deleted() .update_put_timestamp() - .is_deleted() ??? + .is_deleted() .update_metadata() HEAD: - .pending_timeout - .stale_reads_ok .is_deleted() + .is_status_deleted() .get_info() + .get_policy_stats() .metadata GET: - .pending_timeout - .stale_reads_ok .is_deleted() + .is_status_deleted() .get_info() + .get_policy_stats() .metadata .list_containers_iter() POST: .is_deleted() + .is_status_deleted() .update_metadata() """ @@ -748,3 +781,6 @@ class DiskAccount(DiskCommon): 'bytes_used': self.metadata.get(X_BYTES_USED, (0, 0))[0], 'hash': '', 'id': ''} return data + + def get_policy_stats(self, do_migrations=False): + return {} diff --git a/gluster/swift/common/Glusterfs.py b/gluster/swift/common/Glusterfs.py index 6a2fdb2..910f752 100644 --- a/gluster/swift/common/Glusterfs.py +++ b/gluster/swift/common/Glusterfs.py @@ -148,7 +148,7 @@ def _get_unique_id(): # own the lock. continue raise - except: + except Exception: os.close(fd) raise else: diff --git a/gluster/swift/common/middleware/gswauth/swauth/middleware.py b/gluster/swift/common/middleware/gswauth/swauth/middleware.py index cdcc638..3cd9cf7 100644 --- a/gluster/swift/common/middleware/gswauth/swauth/middleware.py +++ b/gluster/swift/common/middleware/gswauth/swauth/middleware.py @@ -28,6 +28,7 @@ import base64 from eventlet.timeout import Timeout from eventlet import TimeoutError +from swift import gettext_ as _ from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPConflict, \ HTTPCreated, HTTPForbidden, HTTPMethodNotAllowed, HTTPMovedPermanently, \ HTTPNoContent, HTTPNotFound, HTTPUnauthorized, \ diff --git a/gluster/swift/common/utils.py b/gluster/swift/common/utils.py index b6a5a09..e6f4bcc 100644 --- a/gluster/swift/common/utils.py +++ b/gluster/swift/common/utils.py @@ -17,6 +17,7 @@ import os import stat import json import errno +import random import logging from hashlib import md5 from eventlet import sleep @@ -29,7 +30,7 @@ from swift.common.db import utf8encodekeys from gluster.swift.common.fs_utils import do_getctime, do_getmtime, do_stat, \ do_listdir, do_walk, do_rmdir, do_log_rl, get_filename_from_fd, do_open, \ do_isdir, do_getsize, do_getxattr, do_setxattr, do_removexattr, do_read, \ - do_close, do_dup, do_lseek, do_fstat + do_close, do_dup, do_lseek, do_fstat, do_fsync, do_rename from gluster.swift.common import Glusterfs X_CONTENT_TYPE = 'Content-Type' @@ -607,3 +608,41 @@ def rmobjdir(dir_path): raise else: return True + + +def write_pickle(obj, dest, tmp=None, pickle_protocol=0): + """ + Ensure that a pickle file gets written to disk. The file is first written + to a tmp file location in the destination directory path, ensured it is + synced to disk, then moved to its final destination name. + + This version takes advantage of Gluster's dot-prefix-dot-suffix naming + where the a file named ".thefile.name.9a7aasv" is hashed to the same + Gluster node as "thefile.name". This ensures the renaming of a temp file + once written does not move it to another Gluster node. + + :param obj: python object to be pickled + :param dest: path of final destination file + :param tmp: path to tmp to use, defaults to None (ignored) + :param pickle_protocol: protocol to pickle the obj with, defaults to 0 + """ + dirname = os.path.dirname(dest) + # Create destination directory + try: + os.makedirs(dirname) + except OSError as err: + if err.errno != errno.EEXIST: + raise + basename = os.path.basename(dest) + tmpname = '.' + basename + '.' + \ + md5(basename + str(random.random())).hexdigest() + tmppath = os.path.join(dirname, tmpname) + with open(tmppath, 'wb') as fo: + pickle.dump(obj, fo, pickle_protocol) + # TODO: This flush() method call turns into a flush() system call + # We'll need to wrap this as well, but we would do this by writing + # a context manager for our own open() method which returns an object + # in fo which makes the gluster API call. + fo.flush() + do_fsync(fo) + do_rename(tmppath, dest) |