Skip to content

Commit

Permalink
rgw: add the support for X-History-Location in swift API
Browse files Browse the repository at this point in the history
The feature is described at
https://github.com/openstack/swift/blob/2.12.0/swift/common/middleware/versioned_writes.py#L23-L30

Signed-off-by: Jing Wenjun <jingwenjun@cmss.chinamobile.com>
  • Loading branch information
Jing-Scott committed May 11, 2017
1 parent c863f8c commit 29b7951
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 23 deletions.
14 changes: 7 additions & 7 deletions doc/radosgw/config-ref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -827,13 +827,13 @@ Swift Settings
``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.
This allows clients to put the ``X-Versions-Location`` or
``X-History-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``

Expand Down
29 changes: 26 additions & 3 deletions src/rgw/rgw_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2380,11 +2380,16 @@ void RGWCreateBucket::execute()
if (swift_ver_location) {
s->bucket_info.swift_ver_location = *swift_ver_location;
s->bucket_info.swift_versioning = (! swift_ver_location->empty());
s->bucket_info.swift_his_location.clear();
} else if (swift_his_location) {
s->bucket_info.swift_his_location = *swift_his_location;
s->bucket_info.swift_versioning = (! swift_his_location->empty());
s->bucket_info.swift_ver_location.clear();
}

op_ret = store->create_bucket(*(s->user), s->bucket, zonegroup_id,
placement_rule, s->bucket_info.swift_ver_location,
pquota_info, attrs,
s->bucket_info.swift_his_location, pquota_info, attrs,
info, pobjv, &ep_objv, creation_time,
pmaster_bucket, pmaster_num_shards, true);
/* continue if EEXIST and create_bucket will fail below. this way we can
Expand Down Expand Up @@ -2462,6 +2467,11 @@ void RGWCreateBucket::execute()
if (swift_ver_location) {
s->bucket_info.swift_ver_location = *swift_ver_location;
s->bucket_info.swift_versioning = (! swift_ver_location->empty());
s->bucket_info.swift_his_location.clear();
} else if(swift_his_location) {
s->bucket_info.swift_his_location = *swift_his_location;
s->bucket_info.swift_versioning = (! swift_his_location->empty());
s->bucket_info.swift_ver_location.clear();
}

/* Web site of Swift API. */
Expand Down Expand Up @@ -3624,6 +3634,11 @@ void RGWPutMetadataBucket::execute()
if (swift_ver_location) {
s->bucket_info.swift_ver_location = *swift_ver_location;
s->bucket_info.swift_versioning = (! swift_ver_location->empty());
s->bucket_info.swift_his_location.clear();
} else if(swift_his_location) {
s->bucket_info.swift_his_location = *swift_his_location;
s->bucket_info.swift_versioning = (! swift_his_location->empty());
s->bucket_info.swift_ver_location.clear();
}

/* Web site of Swift API. */
Expand Down Expand Up @@ -3778,6 +3793,14 @@ void RGWDeleteObj::execute()


if (!s->object.empty()) {
bool his_deleted = false;
/* If obj does not exits, the "delete marker" still
* can be written in swift history location. */
op_ret = store->swift_versioning_history(s, user_quota, bucket_quota, obj, his_deleted);
if (op_ret < 0) {
return;
}

if (need_object_expiration() || multipart_delete) {
/* check if obj exists, read orig attrs */
op_ret = get_obj_attrs(store, s, obj, attrs);
Expand Down Expand Up @@ -3811,7 +3834,7 @@ void RGWDeleteObj::execute()
return;
}

if (!ver_restored) {
if (!ver_restored && !his_deleted) {
/* 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. */
Expand Down Expand Up @@ -5621,7 +5644,7 @@ int RGWBulkUploadOp::handle_dir(const boost::string_ref path)
bucket,
store->get_zonegroup().get_id(),
placement_rule, binfo.swift_ver_location,
pquota_info, attrs,
binfo.swift_his_location, pquota_info, attrs,
out_info, pobjv, &ep_objv, creation_time,
pmaster_bucket, pmaster_num_shards, true);
/* continue if EEXIST and create_bucket will fail below. this way we can
Expand Down
17 changes: 11 additions & 6 deletions src/rgw/rgw_rados.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5392,6 +5392,7 @@ int RGWRados::create_bucket(RGWUserInfo& owner, rgw_bucket& bucket,
const string& zonegroup_id,
const string& placement_rule,
const string& swift_ver_location,
const string& swift_his_location,
const RGWQuotaInfo * pquota_info,
map<std::string, bufferlist>& attrs,
RGWBucketInfo& info,
Expand Down Expand Up @@ -5435,7 +5436,8 @@ int RGWRados::create_bucket(RGWUserInfo& owner, rgw_bucket& bucket,
info.placement_rule = selected_placement_rule_name;
info.index_type = rule_info.index_type;
info.swift_ver_location = swift_ver_location;
info.swift_versioning = (!swift_ver_location.empty());
info.swift_his_location = swift_his_location;
info.swift_versioning = (!swift_ver_location.empty() || !swift_his_location.empty());
if (pmaster_num_shards) {
info.num_shards = *pmaster_num_shards;
} else {
Expand Down Expand Up @@ -6191,7 +6193,8 @@ int RGWRados::swift_versioning_copy(RGWObjectCtx& obj_ctx,
RGWBucketInfo& bucket_info,
rgw_obj& obj)
{
if (! swift_versioning_enabled(bucket_info)) {
boost::optional<std::string> versioning_location = get_swift_versioning_location(bucket_info);
if (! versioning_location) {
return 0;
}

Expand All @@ -6218,7 +6221,7 @@ int RGWRados::swift_versioning_copy(RGWObjectCtx& obj_ctx,

RGWBucketInfo dest_bucket_info;

r = get_bucket_info(obj_ctx, bucket_info.bucket.tenant, bucket_info.swift_ver_location, dest_bucket_info, NULL, NULL);
r = get_bucket_info(obj_ctx, bucket_info.bucket.tenant, *versioning_location, dest_bucket_info, NULL, NULL);
if (r < 0) {
ldout(cct, 10) << "failed to read dest bucket info: r=" << r << dendl;
if (r == -ENOENT) {
Expand Down Expand Up @@ -6280,15 +6283,17 @@ int RGWRados::swift_versioning_restore(RGWObjectCtx& obj_ctx,
rgw_obj& obj,
bool& restored) /* out */
{
if (! swift_versioning_enabled(bucket_info)) {
boost::optional<std::string> versioning_location = get_swift_versioning_location(bucket_info);
if (! versioning_location ||
versioning_location->compare(bucket_info.swift_ver_location) != 0) {
return 0;
}

/* Bucket info of the bucket that stores previous versions of our object. */
RGWBucketInfo archive_binfo;

int ret = get_bucket_info(obj_ctx, bucket_info.bucket.tenant,
bucket_info.swift_ver_location, archive_binfo,
*versioning_location, archive_binfo,
nullptr, nullptr);
if (ret < 0) {
return ret;
Expand Down Expand Up @@ -6524,7 +6529,7 @@ int RGWRados::swift_versioning_history(req_state *s,
attrs.emplace(RGW_ATTR_ETAG, std::move(etag_bl));

/* Create metadata: CONTENT_TYPE. */
std::string content_type = "application/x-deleted;swift_versions_deleted=1";
const std::string content_type = "application/x-deleted;swift_versions_deleted=1";
bufferlist ct_bl;
ct_bl.append(content_type.c_str(), content_type.size() + 1);
attrs.emplace(RGW_ATTR_CONTENT_TYPE, std::move(ct_bl));
Expand Down
13 changes: 10 additions & 3 deletions src/rgw/rgw_rados.h
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,7 @@ class RGWRados
const string& zonegroup_id,
const string& placement_rule,
const string& swift_ver_location,
const string& swift_his_location,
const RGWQuotaInfo * pquota_info,
map<std::string,bufferlist>& attrs,
RGWBucketInfo& bucket_info,
Expand Down Expand Up @@ -2947,9 +2948,15 @@ class RGWRados
const std::string& obj_delim,
std::function<int(const rgw_bucket_dir_entry&)> handler);

bool swift_versioning_enabled(const RGWBucketInfo& bucket_info) const {
return bucket_info.has_swift_versioning() &&
bucket_info.swift_ver_location.size();
boost::optional<std::string> get_swift_versioning_location(const RGWBucketInfo& bucket_info) const {
if (bucket_info.has_swift_versioning()) {
if (bucket_info.swift_ver_location.size()) {
return bucket_info.swift_ver_location;
} else if (bucket_info.swift_his_location.size()) {
return bucket_info.swift_his_location;
}
}
return boost::none;
}

int swift_versioning_copy(RGWObjectCtx& obj_ctx, /* in/out */
Expand Down
28 changes: 24 additions & 4 deletions src/rgw/rgw_rest_swift.cc
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ static void dump_container_metadata(struct req_state *s,
url_encode(s->bucket_info.swift_ver_location));
}

if (! s->bucket_info.swift_his_location.empty()) {
dump_header(s, "X-History-Location",
url_encode(s->bucket_info.swift_his_location));
}

/* Dump quota headers. */
if (quota.enabled) {
if (quota.max_size >= 0) {
Expand Down Expand Up @@ -599,7 +604,8 @@ static void get_rmattrs_from_headers(const req_state * const s,

static int get_swift_versioning_settings(
req_state * const s,
boost::optional<std::string>& swift_ver_location)
boost::optional<std::string>& swift_ver_location,
boost::optional<std::string>& swift_his_location)
{
/* Removing the Swift's versions location has lower priority than setting
* a new one. That's the reason why we're handling it first. */
Expand All @@ -609,7 +615,13 @@ static int get_swift_versioning_settings(
swift_ver_location = boost::in_place(std::string());
}

if (s->info.env->exists("HTTP_X_VERSIONS_LOCATION")) {
bool ver_exists = s->info.env->exists("HTTP_X_VERSIONS_LOCATION");
bool his_exists = s->info.env->exists("HTTP_X_HISTORY_LOCATION");
if (ver_exists && his_exists) {
return -EINVAL;
}

if (ver_exists) {
/* If the Swift's versioning is globally disabled but someone wants to
* enable it for a given container, new version of Swift will generate
* the precondition failed error. */
Expand All @@ -618,6 +630,14 @@ static int get_swift_versioning_settings(
}

swift_ver_location = s->info.env->get("HTTP_X_VERSIONS_LOCATION", "");
swift_his_location = boost::none;
} else if (his_exists) {
if (! s->cct->_conf->rgw_swift_versioning_enabled) {
return -ERR_PRECONDITION_FAILED;
}

swift_his_location = s->info.env->get("HTTP_X_HISTORY_LOCATION", "");
swift_ver_location = boost::none;
}

return 0;
Expand All @@ -643,7 +663,7 @@ int RGWCreateBucket_ObjStore_SWIFT::get_params()
CONT_REMOVE_ATTR_PREFIX, rmattr_names);
placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");

return get_swift_versioning_settings(s, swift_ver_location);
return get_swift_versioning_settings(s, swift_ver_location, swift_his_location);
}

void RGWCreateBucket_ObjStore_SWIFT::send_response()
Expand Down Expand Up @@ -917,7 +937,7 @@ int RGWPutMetadataBucket_ObjStore_SWIFT::get_params()
rmattr_names);
placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");

return get_swift_versioning_settings(s, swift_ver_location);
return get_swift_versioning_settings(s, swift_ver_location, swift_his_location);
}

void RGWPutMetadataBucket_ObjStore_SWIFT::send_response()
Expand Down

0 comments on commit 29b7951

Please sign in to comment.