
PUT of a directory fails with gluster-swift when there exists object of a same name. This is because the objects and directories are placed on the glusterfs. And hence the filesystem semantics are applicable there. Exceptions raised in such situation are needed to be handled and reported correctly back to proxy-server with HTTPConflict as a error code. Although swift still continues to choose 503 as the best respose in such cases. No tracebacks reported. Fix covers the case when there exists a directory and object of the same name is PUT. Code changes fixes both the failure cases mentioned in the bug. Examples of failing PUT requests: 1) curl -v -X PUT http://127.0.0.1:8080/v1/AUTH_test/c1/dir1/obj2/anotherobject -d'asdasdsadA' -- obj2 was already an object. 2)curl -v -H 'Content-Length: 0' -H 'Content-Type: application/directory' -X PUT http://127.0.0.1:8080/v1/AUTH_test/c1/obj1 -- obj1 was already and object Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1071021 Change-Id: Id3042d920e3f99e740d4042ef5907ac8c59e04db Signed-off-by: Chetan Risbud <crisbud@redhat.com> Reviewed-on: http://review.gluster.org/7181 Reviewed-by: Prashanth Pai <ppai@redhat.com> Tested-by: Prashanth Pai <ppai@redhat.com>
104 lines
3.7 KiB
Python
104 lines
3.7 KiB
Python
# Copyright (c) 2012-2014 Red Hat, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
""" 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 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
|
|
|
|
|
|
class ObjectController(server.ObjectController):
|
|
"""
|
|
Subclass of the object server's ObjectController which replaces the
|
|
container_update method with one that is a no-op (information is simply
|
|
stored on disk and already updated by virtue of performing the file system
|
|
operations directly).
|
|
"""
|
|
def setup(self, conf):
|
|
"""
|
|
Implementation specific setup. This method is called at the very end
|
|
by the constructor to allow a specific implementation to modify
|
|
existing attributes or add its own attributes.
|
|
|
|
: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)
|
|
|
|
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)
|
|
|
|
def container_update(self, *args, **kwargs):
|
|
"""
|
|
Update the container when objects are updated.
|
|
|
|
For Gluster, this is just a no-op, since a container is just the
|
|
directory holding all the objects (sub-directory hierarchy of files).
|
|
"""
|
|
return
|
|
|
|
def delete_at_update(self, *args, **kwargs):
|
|
"""
|
|
Update the expiring objects container when objects are updated.
|
|
|
|
FIXME: Gluster currently does not support delete_at headers.
|
|
"""
|
|
return
|
|
|
|
@public
|
|
@timing_stats()
|
|
def PUT(self, request):
|
|
try:
|
|
return server.ObjectController.PUT(self, request)
|
|
except (AlreadyExistsAsFile, AlreadyExistsAsDir):
|
|
device = \
|
|
split_and_validate_path(request, 1, 5, True)
|
|
return HTTPConflict(drive=device, request=request)
|
|
|
|
|
|
def app_factory(global_conf, **local_conf):
|
|
"""paste.deploy app factory for creating WSGI object server apps"""
|
|
conf = global_conf.copy()
|
|
conf.update(local_conf)
|
|
return ObjectController(conf)
|