Skip to content

Commit

Permalink
Merge pull request #10710: jewel: rgw: improve support for Swift's ob…
Browse files Browse the repository at this point in the history
…ject versioning.

Reviewed-by: Loic Dachary <ldachary@redhat.com>
  • Loading branch information
Loic Dachary committed Aug 22, 2016
2 parents 1730e4e + dbf8cf0 commit 8c8efb3
Show file tree
Hide file tree
Showing 8 changed files with 331 additions and 64 deletions.
14 changes: 14 additions & 0 deletions doc/radosgw/config-ref.rst
Expand Up @@ -778,6 +778,20 @@ Swift Settings
:Default: ``auth``


``rgw swift versioning enabled``

:Description: Enables the Object Versioning of OpenStack Object Storage API.
This allows clients to put the ``X-Versions-Location`` attribute
on containers that should be versioned. The attribute specifies
the name of container storing archived versions. It must be owned
by the same user that the versioned container due to access
control verification - ACLs are NOT taken into consideration.
Those containers cannot be versioned by the S3 object versioning
mechanism.
:Type: Boolean
:Default: ``false``



Logging Settings
================
Expand Down
2 changes: 1 addition & 1 deletion doc/radosgw/swift.rst
Expand Up @@ -67,7 +67,7 @@ The following table describes the support status for current Swift functional fe
+---------------------------------+-----------------+----------------------------------------+
| **Expiring Objects** | Supported | |
+---------------------------------+-----------------+----------------------------------------+
| **Object Versioning** | Not Supported | |
| **Object Versioning** | Supported | |
+---------------------------------+-----------------+----------------------------------------+
| **CORS** | Not Supported | |
+---------------------------------+-----------------+----------------------------------------+
Expand Down
7 changes: 5 additions & 2 deletions src/rgw/rgw_common.h
Expand Up @@ -992,11 +992,14 @@ struct RGWBucketInfo

void decode_json(JSONObj *obj);

bool versioned() { return (flags & BUCKET_VERSIONED) != 0; }
bool versioned() const { return (flags & BUCKET_VERSIONED) != 0; }
int versioning_status() { return flags & (BUCKET_VERSIONED | BUCKET_VERSIONS_SUSPENDED); }
bool versioning_enabled() { return versioning_status() == BUCKET_VERSIONED; }

bool has_swift_versioning() { return swift_versioning; }
bool has_swift_versioning() const {
/* A bucket may be versioned through one mechanism only. */
return swift_versioning && !versioned();
}

RGWBucketInfo() : flags(0), has_instance_obj(false), num_shards(0), bucket_index_shard_hash_type(MOD), requester_pays(false),
has_website(false), swift_versioning(false) {}
Expand Down
100 changes: 74 additions & 26 deletions src/rgw/rgw_op.cc
Expand Up @@ -2012,10 +2012,17 @@ void RGWCreateBucket::execute()

s->bucket.tenant = s->bucket_tenant; /* ignored if bucket exists */
s->bucket.name = s->bucket_name;

/* Handle updates of the metadata for Swift's object versioning. */
if (swift_ver_location) {
s->bucket_info.swift_ver_location = *swift_ver_location;
s->bucket_info.swift_versioning = (! swift_ver_location->empty());
}

op_ret = store->create_bucket(*(s->user), s->bucket, zonegroup_id,
placement_rule, swift_ver_location, attrs,
info, pobjv, &ep_objv, creation_time,
pmaster_bucket, true);
placement_rule, s->bucket_info.swift_ver_location,
attrs, info, pobjv, &ep_objv, creation_time,
pmaster_bucket, true);
/* continue if EEXIST and create_bucket will fail below. this way we can
* recover from a partial create by retrying it. */
ldout(s->cct, 20) << "rgw_create_bucket returned ret=" << op_ret << " bucket=" << s->bucket << dendl;
Expand Down Expand Up @@ -2083,6 +2090,12 @@ void RGWCreateBucket::execute()
prepare_add_del_attrs(s->bucket_attrs, rmattr_names, attrs);
populate_with_generic_attrs(s, attrs);

/* Handle updates of the metadata for Swift's object versioning. */
if (swift_ver_location) {
s->bucket_info.swift_ver_location = *swift_ver_location;
s->bucket_info.swift_versioning = (! swift_ver_location->empty());
}

op_ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs,
&s->bucket_info.objv_tracker);
} while (op_ret == -ECANCELED && tries++ < 20);
Expand Down Expand Up @@ -2426,6 +2439,18 @@ void RGWPutObj::execute()

processor = select_processor(*static_cast<RGWObjectCtx *>(s->obj_ctx), &multipart);

/* Handle object versioning of Swift API. */
if (! multipart) {
rgw_obj obj(s->bucket, s->object);
op_ret = store->swift_versioning_copy(*static_cast<RGWObjectCtx *>(s->obj_ctx),
s->bucket_owner.get_id(),
s->bucket_info,
obj);
if (op_ret < 0) {
return;
}
}

op_ret = processor->prepare(store, NULL);
if (op_ret < 0) {
ldout(s->cct, 20) << "processor->prepare() returned ret=" << op_ret
Expand Down Expand Up @@ -2895,8 +2920,10 @@ void RGWPutMetadataBucket::execute()
prepare_add_del_attrs(s->bucket_attrs, rmattr_names, attrs);
populate_with_generic_attrs(s, attrs);

s->bucket_info.swift_ver_location = swift_ver_location;
s->bucket_info.swift_versioning = (!swift_ver_location.empty());
if (swift_ver_location) {
s->bucket_info.swift_ver_location = *swift_ver_location;
s->bucket_info.swift_versioning = (! swift_ver_location->empty());
}

op_ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs,
&s->bucket_info.objv_tracker);
Expand Down Expand Up @@ -3068,35 +3095,46 @@ void RGWDeleteObj::execute()
}

RGWObjectCtx *obj_ctx = static_cast<RGWObjectCtx *>(s->obj_ctx);

obj_ctx->set_atomic(obj);

RGWRados::Object del_target(store, s->bucket_info, *obj_ctx, obj);
RGWRados::Object::Delete del_op(&del_target);

op_ret = get_system_versioning_params(s, &del_op.params.olh_epoch,
&del_op.params.marker_version_id);
bool ver_restored = false;
op_ret = store->swift_versioning_restore(*obj_ctx, s->bucket_owner.get_id(),
s->bucket_info, obj, ver_restored);
if (op_ret < 0) {
return;
}

del_op.params.bucket_owner = s->bucket_owner.get_id();
del_op.params.versioning_status = s->bucket_info.versioning_status();
del_op.params.obj_owner = s->owner;
del_op.params.unmod_since = unmod_since;
del_op.params.high_precision_time = s->system_request; /* system request uses high precision time */
if (!ver_restored) {
/* Swift's versioning mechanism hasn't found any previous version of
* the object that could be restored. This means we should proceed
* with the regular delete path. */
RGWRados::Object del_target(store, s->bucket_info, *obj_ctx, obj);
RGWRados::Object::Delete del_op(&del_target);

op_ret = del_op.delete_obj();
if (op_ret >= 0) {
delete_marker = del_op.result.delete_marker;
version_id = del_op.result.version_id;
}
op_ret = get_system_versioning_params(s, &del_op.params.olh_epoch,
&del_op.params.marker_version_id);
if (op_ret < 0) {
return;
}

/* Check whether the object has expired. Swift API documentation
* stands that we should return 404 Not Found in such case. */
if (need_object_expiration() && object_is_expired(attrs)) {
op_ret = -ENOENT;
return;
del_op.params.bucket_owner = s->bucket_owner.get_id();
del_op.params.versioning_status = s->bucket_info.versioning_status();
del_op.params.obj_owner = s->owner;
del_op.params.unmod_since = unmod_since;
del_op.params.high_precision_time = s->system_request; /* system request uses high precision time */

op_ret = del_op.delete_obj();
if (op_ret >= 0) {
delete_marker = del_op.result.delete_marker;
version_id = del_op.result.version_id;
}

/* Check whether the object has expired. Swift API documentation
* stands that we should return 404 Not Found in such case. */
if (need_object_expiration() && object_is_expired(attrs)) {
op_ret = -ENOENT;
return;
}
}

if (op_ret == -ERR_PRECONDITION_FAILED && no_precondition_error) {
Expand Down Expand Up @@ -3318,6 +3356,16 @@ void RGWCopyObj::execute()

bool high_precision_time = (s->system_request);

/* Handle object versioning of Swift API. In case of copying to remote this
* should fail gently (op_ret == 0) as the dst_obj will not exist here. */
op_ret = store->swift_versioning_copy(obj_ctx,
dest_bucket_info.owner,
dest_bucket_info,
dst_obj);
if (op_ret < 0) {
return;
}

op_ret = store->copy_obj(obj_ctx,
s->user->user_id,
client_id,
Expand Down
6 changes: 4 additions & 2 deletions src/rgw/rgw_op.h
Expand Up @@ -18,6 +18,8 @@
#include <set>
#include <map>

#include <boost/optional.hpp>

#include "common/armor.h"
#include "common/mime.h"
#include "common/utf8.h"
Expand Down Expand Up @@ -535,7 +537,7 @@ class RGWCreateBucket : public RGWOp {
obj_version ep_objv;
bool has_cors;
RGWCORSConfiguration cors_config;
string swift_ver_location;
boost::optional<std::string> swift_ver_location;
map<string, buffer::list> attrs;
set<string> rmattr_names;

Expand Down Expand Up @@ -781,7 +783,7 @@ class RGWPutMetadataBucket : public RGWOp {
RGWAccessControlPolicy policy;
RGWCORSConfiguration cors_config;
string placement_rule;
string swift_ver_location;
boost::optional<std::string> swift_ver_location;

public:
RGWPutMetadataBucket()
Expand Down

0 comments on commit 8c8efb3

Please sign in to comment.