summaryrefslogtreecommitdiffstats
path: root/gluster/swift/obj/server.py
diff options
context:
space:
mode:
Diffstat (limited to 'gluster/swift/obj/server.py')
-rw-r--r--gluster/swift/obj/server.py78
1 files changed, 67 insertions, 11 deletions
diff --git a/gluster/swift/obj/server.py b/gluster/swift/obj/server.py
index 1d8d418..3e27cc3 100644
--- a/gluster/swift/obj/server.py
+++ b/gluster/swift/obj/server.py
@@ -14,16 +14,19 @@
# limitations under the License.
""" Object Server for Gluster for Swift """
+import errno
+import os
from swift.common.swob import HTTPConflict, HTTPNotImplemented
-from swift.common.utils import public, timing_stats, replication
-from gluster.swift.common.exceptions import AlreadyExistsAsFile, \
- AlreadyExistsAsDir
+from swift.common.utils import public, timing_stats, replication, mkdirs
from swift.common.request_helpers import split_and_validate_path
-
from swift.obj import server
from gluster.swift.obj.diskfile import DiskFileManager
+from gluster.swift.common.fs_utils import do_ismount
+from gluster.swift.common.ring import Ring
+from gluster.swift.common.exceptions import AlreadyExistsAsFile, \
+ AlreadyExistsAsDir
class GlusterSwiftDiskFileRouter(object):
@@ -55,6 +58,9 @@ class ObjectController(server.ObjectController):
"""
# Replaces Swift's DiskFileRouter object reference with ours.
self._diskfile_router = GlusterSwiftDiskFileRouter(conf, self.logger)
+ self.devices = conf.get('devices', '/mnt/gluster-object')
+ self.swift_dir = conf.get('swift_dir', '/etc/swift')
+ self.object_ring = self.get_object_ring()
def container_update(self, *args, **kwargs):
"""
@@ -65,15 +71,65 @@ class ObjectController(server.ObjectController):
"""
return
- def delete_at_update(self, *args, **kwargs):
- """
- Update the expiring objects container when objects are updated.
+ def get_object_ring(self):
+ return Ring(self.swift_dir, ring_name='object')
- For Gluster, this is a no-op as there are no container DB entries
- to be created that tracks objects to be expired. Objects to be
- expired will be determined by crawling the filesystem directly.
+ def _create_expiring_tracker_object(self, object_path):
+ try:
+
+ # Check if gsexpiring volume is present in ring
+ if not any(d.get('device', None) == self.expiring_objects_account
+ for d in self.object_ring.devs):
+ raise Exception("%s volume not in ring" %
+ self.expiring_objects_account)
+
+ # Check if gsexpiring is mounted.
+ expiring_objects_account_path = \
+ os.path.join(self.devices, self.expiring_objects_account)
+ mount_check = self._diskfile_router['junk'].mount_check
+ if mount_check and not do_ismount(expiring_objects_account_path):
+ raise Exception("Path %s doesn't exist or is not a mount "
+ "point" % expiring_objects_account_path)
+
+ # Create object directory
+ object_dir = os.path.dirname(object_path)
+ try:
+ mkdirs(object_dir)
+ except OSError as err:
+ mkdirs(object_dir) # handle race
+
+ # Create zero-byte file
+ try:
+ os.mknod(object_path)
+ except OSError as err:
+ if err.errno != errno.EEXIST:
+ raise
+ except Exception as e:
+ self.logger.error("Creation of tracker object %s failed: %s" %
+ (object_path, str(e)))
+
+ def async_update(self, op, account, container, obj, host, partition,
+ contdevice, headers_out, objdevice, policy):
"""
- return
+ In Openstack Swift, this method is called by:
+ * container_update (a no-op in gluster-swift)
+ * delete_at_update (to PUT objects into .expiring_objects account)
+
+ The Swift's version of async_update only sends the request to
+ container-server to PUT the object. The container-server calls
+ container_update method which makes an entry for the object in it's
+ database. No actual object is created on disk.
+
+ But in gluster-swift container_update is a no-op, so we'll
+ have to PUT an actual object. We override async_update to create a
+ container first and then the corresponding "tracker object" which
+ tracks expired objects scheduled for deletion.
+ """
+ object_path = os.path.join(self.devices, account, container, obj)
+
+ threadpool = self._diskfile_router[policy].threadpools[objdevice]
+ threadpool.run_in_thread(self._create_expiring_tracker_object,
+ object_path)
@public
@timing_stats()