Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jewel: rgw: improve support for Swift's object versioning. #10710

Merged
1 commit merged into from Aug 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -2000,10 +2000,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 @@ -2071,6 +2078,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 @@ -2414,6 +2427,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 @@ -2883,8 +2908,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 @@ -3056,35 +3083,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 @@ -3306,6 +3344,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