diff options
Diffstat (limited to 'gluster/swift/obj/server.py')
-rw-r--r-- | gluster/swift/obj/server.py | 155 |
1 files changed, 43 insertions, 112 deletions
diff --git a/gluster/swift/obj/server.py b/gluster/swift/obj/server.py index 8bc080a..1d8d418 100644 --- a/gluster/swift/obj/server.py +++ b/gluster/swift/obj/server.py @@ -15,26 +15,27 @@ """ Object Server for Gluster for Swift """ -# Simply importing this monkey patches the constraint handling to fit our -# needs -import gluster.swift.common.constraints # noqa -from swift.common.swob import HTTPConflict -from swift.common.utils import public, timing_stats +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.request_helpers import split_and_validate_path from swift.obj import server -from gluster.swift.obj.diskfile import OnDiskManager +from gluster.swift.obj.diskfile import DiskFileManager -import os -from swift.common.exceptions import ConnectionTimeout -from swift.common.bufferedhttp import http_connect -from eventlet import Timeout -from swift.common.http import is_success -from gluster.swift.common.ring import Ring -from swift import gettext_ as _ + +class GlusterSwiftDiskFileRouter(object): + """ + Replacement for Swift's DiskFileRouter object. + Always returns GlusterSwift's DiskFileManager implementation. + """ + def __init__(self, *args, **kwargs): + self.manager_cls = DiskFileManager(*args, **kwargs) + + def __getitem__(self, policy): + return self.manager_cls class ObjectController(server.ObjectController): @@ -52,23 +53,8 @@ class ObjectController(server.ObjectController): :param conf: WSGI configuration parameter """ - # Common on-disk hierarchy shared across account, container and object - # servers. - self._ondisk_mgr = OnDiskManager(conf, self.logger) - self.swift_dir = conf.get('swift_dir', '/etc/swift') - - def get_diskfile(self, device, partition, account, container, obj, - **kwargs): - """ - Utility method for instantiating a DiskFile object supporting a given - REST API. - - An implementation of the object server that wants to use a different - DiskFile class would simply over-ride this method to provide that - behavior. - """ - return self._ondisk_mgr.get_diskfile(device, account, container, obj, - **kwargs) + # Replaces Swift's DiskFileRouter object reference with ours. + self._diskfile_router = GlusterSwiftDiskFileRouter(conf, self.logger) def container_update(self, *args, **kwargs): """ @@ -79,102 +65,47 @@ class ObjectController(server.ObjectController): """ return - def get_object_ring(self): - if hasattr(self, 'object_ring'): - if not self.object_ring: - self.object_ring = Ring(self.swift_dir, ring_name='object') - else: - self.object_ring = Ring(self.swift_dir, ring_name='object') - return self.object_ring - - def async_update(self, op, account, container, obj, host, partition, - contdevice, headers_out, objdevice): - """ - 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. + def delete_at_update(self, *args, **kwargs): """ + Update the expiring objects container when objects are updated. - headers_out['user-agent'] = 'obj-server %s' % os.getpid() - if all([host, partition, contdevice]): - # PUT the container. Send request directly to container-server - container_path = '/%s/%s' % (account, container) - try: - with ConnectionTimeout(self.conn_timeout): - ip, port = host.rsplit(':', 1) - conn = http_connect(ip, port, contdevice, partition, op, - container_path, headers_out) - with Timeout(self.node_timeout): - response = conn.getresponse() - response.read() - if not is_success(response.status): - self.logger.error(_( - 'async_update : ' - 'ERROR Container update failed :%(status)d ' - 'response from %(ip)s:%(port)s/%(dev)s'), - {'status': response.status, 'ip': ip, 'port': port, - 'dev': contdevice}) - return - except (Exception, Timeout): - self.logger.exception(_( - 'async_update : ' - 'ERROR Container update failed :%(ip)s:%(port)s/%(dev)s'), - {'ip': ip, 'port': port, 'dev': contdevice}) - - # PUT the tracker object. Send request directly to object-server - object_path = '/%s/%s/%s' % (account, container, obj) - headers_out['Content-Length'] = 0 - headers_out['Content-Type'] = 'text/plain' - try: - with ConnectionTimeout(self.conn_timeout): - # FIXME: Assuming that get_nodes returns single node - part, nodes = self.get_object_ring().get_nodes(account, - container, - obj) - ip = nodes[0]['ip'] - port = nodes[0]['port'] - objdevice = nodes[0]['device'] - conn = http_connect(ip, port, objdevice, partition, op, - object_path, headers_out) - with Timeout(self.node_timeout): - response = conn.getresponse() - response.read() - if is_success(response.status): - return - else: - self.logger.error(_( - 'async_update : ' - 'ERROR Object PUT failed : %(status)d ' - 'response from %(ip)s:%(port)s/%(dev)s'), - {'status': response.status, 'ip': ip, 'port': port, - 'dev': objdevice}) - except (Exception, Timeout): - self.logger.exception(_( - 'async_update : ' - 'ERROR Object PUT failed :%(ip)s:%(port)s/%(dev)s'), - {'ip': ip, 'port': port, 'dev': objdevice}) + 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. + """ return @public @timing_stats() def PUT(self, request): try: + # now call swift's PUT method return server.ObjectController.PUT(self, request) except (AlreadyExistsAsFile, AlreadyExistsAsDir): device = \ split_and_validate_path(request, 1, 5, True) return HTTPConflict(drive=device, request=request) + @public + @replication + @timing_stats(sample_rate=0.1) + def REPLICATE(self, request): + """ + In Swift, this method handles REPLICATE requests for the Swift + Object Server. This is used by the object replicator to get hashes + for directories. + + Gluster-Swift does not support this as it expects the underlying + GlusterFS to take care of replication + """ + return HTTPNotImplemented(request=request) + + @public + @replication + @timing_stats(sample_rate=0.1) + def REPLICATION(self, request): + return HTTPNotImplemented(request=request) + def app_factory(global_conf, **local_conf): """paste.deploy app factory for creating WSGI object server apps""" |