diff options
Diffstat (limited to 'gluster/swift/obj/server.py')
-rw-r--r-- | gluster/swift/obj/server.py | 102 |
1 files changed, 91 insertions, 11 deletions
diff --git a/gluster/swift/obj/server.py b/gluster/swift/obj/server.py index 3cdd3c0..8bc080a 100644 --- a/gluster/swift/obj/server.py +++ b/gluster/swift/obj/server.py @@ -28,6 +28,14 @@ from swift.obj import server from gluster.swift.obj.diskfile import OnDiskManager +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 ObjectController(server.ObjectController): """ @@ -44,16 +52,10 @@ class ObjectController(server.ObjectController): :param conf: WSGI configuration parameter """ - # FIXME: Gluster currently does not support x-delete-at, as there is - # no mechanism in GlusterFS itself to expire an object, or an external - # process that will cull expired objects. - try: - self.allowed_headers.remove('x-delete-at') - except KeyError: - pass # 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): @@ -77,12 +79,90 @@ 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): + 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 - FIXME: Gluster currently does not support delete_at headers. + 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. + """ + + 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}) return @public |