diff options
Diffstat (limited to 'gluster/swift/obj/server.py')
-rw-r--r-- | gluster/swift/obj/server.py | 78 |
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() |