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/obj/server.py | |
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/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""" |