Skip to content

Commit

Permalink
Merge pull request ceph#9188 from rzarzynski/wip-rgw-swift-versioning…
Browse files Browse the repository at this point in the history
…-new-2

rgw: improve support for Swift's object versioning.
Reviewed-by: Orit Wasserman <[email protected]>
  • Loading branch information
oritwas authored Jun 20, 2016
2 parents 0774aa7 + 237ad12 commit 7554ef0
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 65 deletions.
14 changes: 14 additions & 0 deletions doc/radosgw/config-ref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -1006,11 +1006,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
102 changes: 75 additions & 27 deletions src/rgw/rgw_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2208,11 +2208,18 @@ 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,
pquota_info, attrs,
info, pobjv, &ep_objv, creation_time,
pmaster_bucket, true);
placement_rule, s->bucket_info.swift_ver_location,
pquota_info, 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 @@ -2284,6 +2291,12 @@ void RGWCreateBucket::execute()
return;
}

/* 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());
}

/* This will also set the quota on the bucket. */
op_ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs,
&s->bucket_info.objv_tracker);
Expand Down Expand Up @@ -2630,6 +2643,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 @@ -3118,8 +3143,10 @@ void RGWPutMetadataBucket::execute()
return;
}

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());
}

/* Setting attributes also stores the provided bucket info. Due to this
* fact, the new quota settings can be serialized with the same call. */
Expand Down Expand Up @@ -3294,35 +3321,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 @@ -3545,6 +3583,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
Original file line number Diff line number Diff line change
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 @@ -532,7 +534,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 @@ -789,7 +791,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
Loading

0 comments on commit 7554ef0

Please sign in to comment.