See `Adding a Storage Class <https://docs.ceph.com/en/latest/radosgw/placement/#adding-a-storage-class>`__ for how to configure storage-class for a zonegroup. The cloud transition requires a creation of a special storage class with tier type defined as ``cloud``
-Note: Once a storage class is created of ``-tier-type=cloud``, it cannot be later modified to any other storage class type.
+Note: Once a storage class is created of ``--tier-type=cloud``, it cannot be later modified to any other storage class type.
::
Since the transition is unidirectional, while configuring S3 lifecycle rules, the cloud storage class should be specified last among all the storage classes the object transitions to. Subsequent rules (if any) do not apply post transition to the cloud.
+To avoid object names collision across various buckets, source bucket name is prepended to the target object name. If the object is versioned, object versionid is appended to the end.
+
+Below is the sample object name format:
+::
+
+ s3://<target_path>/<source_bucket_name>/<source_object_name>(:<source_object_version_id>)
+
Due to API limitations there is no way to preserve original object modification time and ETag but they get stored as metadata attributes on the destination objects, as shown below:
::
x-amz-meta-rgwx-source-mtime: 1608546349.757100363
x-amz-meta-rgwx-versioned-epoch: 0
-
By default, post transition, the source object gets deleted. But it is possible to retain its metadata but with updated values (like storage-class and object-size) by setting config option 'retain_object' to true. However GET on those objects shall still fail with 'InvalidObjectState' error.
For example,
ERROR: S3 error: 403 (InvalidObjectState)
-Since all the objects are transitioned to a single target bucket, bucket versioning is not enabled on the remote endpoint. That means multiple versions of the same object (if any) shall get overwritten based on the order of their transition.
-
Future Work
-----------
+* Send presigned redirect or read-through the objects transitioned to cloud
+
* Support s3:RestoreObject operation on cloud transitioned objects.
* Federation between RGW and Cloud services.
-
-* Support Object versioning for the transitioned objects
return !(lhs == rhs);
}
+string get_acl_type_str (const ACLGranteeTypeEnum& type) {
+ string s;
+ switch (type) {
+ case ACL_TYPE_EMAIL_USER:
+ s = "email";
+ break;
+ case ACL_TYPE_GROUP:
+ s = "uri";
+ break;
+ default:
+ s = "id";
+ break;
+ }
+
+ return s;
+}
+
+ACLGranteeTypeEnum get_acl_type (const string& t) {
+ ACLGranteeTypeEnum type;
+ if (t == "email") {
+ type = ACL_TYPE_EMAIL_USER;
+ } else if (t == "uri") {
+ type = ACL_TYPE_GROUP;
+ } else {
+ type = ACL_TYPE_CANON_USER;
+ }
+
+ return type;
+}
+
void RGWAccessControlList::_add_grant(ACLGrant *grant)
{
ACLPermission& perm = grant->get_permission();
ACL_GROUP_AUTHENTICATED_USERS = 2,
};
+string get_acl_type_str (const ACLGranteeTypeEnum& type);
+ACLGranteeTypeEnum get_acl_type (const string& t);
+
class ACLPermission
{
protected:
case OPT::ZONEGROUP_PLACEMENT_RM:
case OPT::ZONEGROUP_PLACEMENT_DEFAULT:
{
- if (placement_id.empty()) {
- cerr << "ERROR: --placement-id not specified" << std::endl;
- return EINVAL;
- }
+ if (placement_id.empty()) {
+ cerr << "ERROR: --placement-id not specified" << std::endl;
+ return EINVAL;
+ }
- rgw_placement_rule rule;
- rule.from_str(placement_id);
+ rgw_placement_rule rule;
+ rule.from_str(placement_id);
- if (!rule.storage_class.empty() && opt_storage_class &&
- rule.storage_class != *opt_storage_class) {
- cerr << "ERROR: provided contradicting storage class configuration" << std::endl;
- return EINVAL;
- } else if (rule.storage_class.empty()) {
- rule.storage_class = opt_storage_class.value_or(string());
- }
+ if (!rule.storage_class.empty() && opt_storage_class &&
+ rule.storage_class != *opt_storage_class) {
+ cerr << "ERROR: provided contradicting storage class configuration" << std::endl;
+ return EINVAL;
+ } else if (rule.storage_class.empty()) {
+ rule.storage_class = opt_storage_class.value_or(string());
+ }
RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
int ret = zonegroup.init(dpp(), g_ceph_context, static_cast<rgw::sal::RadosStore*>(store)->svc()->sysobj, null_yield);
return -ret;
}
- if (opt_cmd == OPT::ZONEGROUP_PLACEMENT_ADD ||
- opt_cmd == OPT::ZONEGROUP_PLACEMENT_MODIFY) {
- RGWZoneGroupPlacementTarget& target = zonegroup.placement_targets[placement_id];
- if (!tags.empty()) {
- target.tags.clear();
- for (auto& t : tags) {
- target.tags.insert(t);
- }
- }
- target.name = placement_id;
- for (auto& t : tags_rm) {
- target.tags.erase(t);
- }
- for (auto& t : tags_add) {
- target.tags.insert(t);
- }
- target.storage_classes.insert(rule.get_storage_class());
+ if (opt_cmd == OPT::ZONEGROUP_PLACEMENT_ADD ||
+ opt_cmd == OPT::ZONEGROUP_PLACEMENT_MODIFY) {
+ RGWZoneGroupPlacementTarget& target = zonegroup.placement_targets[placement_id];
+ if (!tags.empty()) {
+ target.tags.clear();
+ for (auto& t : tags) {
+ target.tags.insert(t);
+ }
+ }
- /* Tier options */
- bool tier_class = false;
- std::string storage_class = rule.get_storage_class();
- RGWZoneGroupPlacementTier t{storage_class};
- RGWZoneGroupPlacementTier *pt = &t;
+ target.name = placement_id;
+ for (auto& t : tags_rm) {
+ target.tags.erase(t);
+ }
+ for (auto& t : tags_add) {
+ target.tags.insert(t);
+ }
+ target.storage_classes.insert(rule.get_storage_class());
+
+ /* Tier options */
+ bool tier_class = false;
+ std::string storage_class = rule.get_storage_class();
+ RGWZoneGroupPlacementTier t{storage_class};
+ RGWZoneGroupPlacementTier *pt = &t;
auto ptiter = target.tier_targets.find(storage_class);
if (ptiter != target.tier_targets.end()) {
- pt = &ptiter->second;
- tier_class = true;
- } else if (tier_type_specified && tier_type == "cloud") {
- /* we support only cloud tier-type for now.
- * Once set cant be reset. */
- tier_class = true;
- pt->tier_type = tier_type;
- }
+ pt = &ptiter->second;
+ tier_class = true;
+ } else if (tier_type_specified) {
+ if (tier_type == "cloud") {
+ /* we support only cloud tier-type for now.
+ * Once set cant be reset. */
+ tier_class = true;
+ pt->tier_type = tier_type;
+ } else {
+ cerr << "ERROR: Invalid tier-type specified" << std::endl;
+ return EINVAL;
+ }
+ }
- if (tier_class) {
- if (tier_config_add.size() > 0) {
- JSONFormattable tconfig;
- for (auto add : tier_config_add) {
- int r = tconfig.set(add.first, add.second);
- if (r < 0) {
- cerr << "ERROR: failed to set configurable: " << add << std::endl;
- return EINVAL;
- }
- }
- int r = pt->update_params(tconfig);
- if (r < 0) {
- cerr << "ERROR: failed to update tier_config options"<< std::endl;
- }
+ if (tier_class) {
+ if (tier_config_add.size() > 0) {
+ JSONFormattable tconfig;
+ for (auto add : tier_config_add) {
+ int r = tconfig.set(add.first, add.second);
+ if (r < 0) {
+ cerr << "ERROR: failed to set configurable: " << add << std::endl;
+ return EINVAL;
}
- if (tier_config_rm.size() > 0) {
- JSONFormattable tconfig;
- for (auto add : tier_config_rm) {
- int r = tconfig.set(add.first, add.second);
- if (r < 0) {
- cerr << "ERROR: failed to set configurable: " << add << std::endl;
- return EINVAL;
- }
- }
- int r = pt->clear_params(tconfig);
- if (r < 0) {
- cerr << "ERROR: failed to update tier_config options"<< std::endl;
- }
+ }
+ int r = pt->update_params(tconfig);
+ if (r < 0) {
+ cerr << "ERROR: failed to update tier_config options"<< std::endl;
+ }
+ }
+ if (tier_config_rm.size() > 0) {
+ JSONFormattable tconfig;
+ for (auto add : tier_config_rm) {
+ int r = tconfig.set(add.first, add.second);
+ if (r < 0) {
+ cerr << "ERROR: failed to set configurable: " << add << std::endl;
+ return EINVAL;
}
-
- target.tier_targets.emplace(std::make_pair(storage_class, *pt));
}
+ int r = pt->clear_params(tconfig);
+ if (r < 0) {
+ cerr << "ERROR: failed to update tier_config options"<< std::endl;
+ }
+ }
- } else if (opt_cmd == OPT::ZONEGROUP_PLACEMENT_RM) {
- if (!opt_storage_class ||
- opt_storage_class->empty()) {
- zonegroup.placement_targets.erase(placement_id);
- } else {
- auto iter = zonegroup.placement_targets.find(placement_id);
- if (iter != zonegroup.placement_targets.end()) {
- RGWZoneGroupPlacementTarget& info = zonegroup.placement_targets[placement_id];
- info.storage_classes.erase(*opt_storage_class);
+ target.tier_targets.emplace(std::make_pair(storage_class, *pt));
+ }
+
+ } else if (opt_cmd == OPT::ZONEGROUP_PLACEMENT_RM) {
+ if (!opt_storage_class || opt_storage_class->empty()) {
+ zonegroup.placement_targets.erase(placement_id);
+ } else {
+ auto iter = zonegroup.placement_targets.find(placement_id);
+ if (iter != zonegroup.placement_targets.end()) {
+ RGWZoneGroupPlacementTarget& info = zonegroup.placement_targets[placement_id];
+ info.storage_classes.erase(*opt_storage_class);
auto ptiter = info.tier_targets.find(*opt_storage_class);
if (ptiter != info.tier_targets.end()) {
- info.tier_targets.erase(ptiter);
+ info.tier_targets.erase(ptiter);
}
- }
- }
- } else if (opt_cmd == OPT::ZONEGROUP_PLACEMENT_DEFAULT) {
- if (!zonegroup.placement_targets.count(placement_id)) {
- cerr << "failed to find a zonegroup placement target named '"
- << placement_id << "'" << std::endl;
- return -ENOENT;
- }
- zonegroup.default_placement = rule;
}
+ }
+ } else if (opt_cmd == OPT::ZONEGROUP_PLACEMENT_DEFAULT) {
+ if (!zonegroup.placement_targets.count(placement_id)) {
+ cerr << "failed to find a zonegroup placement target named '"
+ << placement_id << "'" << std::endl;
+ return -ENOENT;
+ }
+ zonegroup.default_placement = rule;
+ }
- zonegroup.post_process_params(dpp(), null_yield);
- ret = zonegroup.update(dpp(), null_yield);
- if (ret < 0) {
- cerr << "failed to update zonegroup: " << cpp_strerror(-ret) << std::endl;
- return -ret;
- }
+ zonegroup.post_process_params(dpp(), null_yield);
+ ret = zonegroup.update(dpp(), null_yield);
+ if (ret < 0) {
+ cerr << "failed to update zonegroup: " << cpp_strerror(-ret) << std::endl;
+ return -ret;
+ }
- encode_json("placement_targets", zonegroup.placement_targets, formatter.get());
- formatter->flush(cout);
+ encode_json("placement_targets", zonegroup.placement_targets, formatter.get());
+ formatter->flush(cout);
}
break;
case OPT::ZONE_CREATE:
void RGWObjTier::dump(Formatter *f) const
{
- f->dump_string("name", name);
- f->dump_object("tier_placement", tier_placement);
- f->dump_bool("is_multipart_upload", is_multipart_upload);
+ encode_json("name", name, f);
+ encode_json("tier_placement", tier_placement, f);
+ encode_json("is_multipart_upload", is_multipart_upload, f);
}
void rgw_bucket_placement::dump(Formatter *f) const
return need_to_process;
}
- /* find out if the the storage class is remote cloud */
- int get_tier_target(const RGWZoneGroup &zonegroup, rgw_placement_rule& rule,
- string& storage_class, RGWZoneGroupPlacementTier &tier) {
- std::map<std::string, RGWZoneGroupPlacementTarget>::const_iterator titer;
- titer = zonegroup.placement_targets.find(rule.name);
- if (titer == zonegroup.placement_targets.end()) {
- return -1;
- }
-
- if (storage_class.empty()) {
- storage_class = rule.storage_class;
- }
-
- const auto& target_rule = titer->second;
- std::map<std::string, RGWZoneGroupPlacementTier>::const_iterator ttier;
- ttier = target_rule.tier_targets.find(storage_class);
- if (ttier != target_rule.tier_targets.end()) {
- tier = ttier->second;
- }
-
- return 0;
- }
+ /* find out if the the storage class is remote cloud */
+ int get_tier_target(const RGWZoneGroup &zonegroup, rgw_placement_rule& rule,
+ string& storage_class, RGWZoneGroupPlacementTier &tier) {
+ std::map<std::string, RGWZoneGroupPlacementTarget>::const_iterator titer;
+ titer = zonegroup.placement_targets.find(rule.name);
+ if (titer == zonegroup.placement_targets.end()) {
+ return -ENOENT;
+ }
+
+ if (storage_class.empty()) {
+ storage_class = rule.storage_class;
+ }
+
+ const auto& target_rule = titer->second;
+ std::map<std::string, RGWZoneGroupPlacementTier>::const_iterator ttier;
+ ttier = target_rule.tier_targets.find(storage_class);
+ if (ttier != target_rule.tier_targets.end()) {
+ tier = ttier->second;
+ }
+ return 0;
+ }
int delete_tier_obj(lc_op_ctx& oc, RGWLCCloudTierCtx& tier_ctx) {
- int ret = -1;
+ int ret = 0;
- /* XXX: do we need to check for retention/versioning attributes
- * as done in RGWDeleteObj?
+ /* XXX: do we need to check for retention attributes * as done in RGWDeleteObj?
*/
- ret = oc.store->getRados()->delete_obj(oc.rctx, oc.bucket->get_info(), oc.obj->get_obj(), tier_ctx.bucket_info.versioning_status());
+ ret = oc.store->getRados()->delete_obj(oc.dpp, oc.rctx, oc.bucket->get_info(), oc.obj->get_obj(), tier_ctx.bucket_info.versioning_status());
return ret;
}
read_op.params.attrs = &attrs;
read_op.params.lastmod = &read_mtime;
- int r = read_op.prepare(null_yield);
+ int r = read_op.prepare(null_yield, oc.dpp);
if (r < 0) {
return r;
}
attrs.erase(RGW_ATTR_ID_TAG);
attrs.erase(RGW_ATTR_TAIL_TAG);
- obj_op.write_meta(tier_ctx.o.meta.size, 0, attrs, null_yield);
+ obj_op.write_meta(oc.dpp, tier_ctx.o.meta.size, 0, attrs, null_yield);
if (r < 0) {
return r;
}
return ret;
}
- RGWLCCloudTierCtx tier_ctx(oc.cct, oc.o, oc.store, oc.bucket->get_info(),
- oc.obj->get_obj(), oc.rctx, conn, bucket_name, oc.tier.target_storage_class,
- &http_manager);
+ RGWLCCloudTierCtx tier_ctx(oc.cct, oc.dpp, oc.o, oc.store, oc.bucket->get_info(),
+ oc.obj->get_obj(), oc.rctx, conn, bucket_name,
+ oc.tier.target_storage_class, &http_manager);
tier_ctx.acl_mappings = oc.tier.acl_mappings;
tier_ctx.multipart_min_part_size = oc.tier.multipart_min_part_size;
tier_ctx.multipart_sync_threshold = oc.tier.multipart_sync_threshold;
tier_ctx.storage_class = oc.tier.storage_class;
bool al_tiered = false;
+
+ /* Since multiple zones may try to transition the same object to the cloud,
+ * verify if the object is already transitioned. And since its just a best
+ * effort, do not bail out in case of any errors.
+ */
ret = crs.run(new RGWLCCloudCheckCR(tier_ctx, &al_tiered));
if (ret < 0) {
}
if (!al_tiered) {
- ldout(tier_ctx.cct, 20) << "is_already_tiered false" << dendl;
+ ldout(tier_ctx.cct, 20) << "is already tiered false" << dendl;
ret = crs.run(new RGWLCCloudTierCR(tier_ctx));
} else {
- ldout(tier_ctx.cct, 20) << "is_already_tiered true" << dendl;
+ ldout(tier_ctx.cct, 20) << "is already tiered true" << dendl;
}
http_manager.stop();
target_placement.inherit_from(oc.bucket->get_placement_rule());
target_placement.storage_class = transition.storage_class;
- ldpp_dout(oc.dpp, 0) << "XXXXXXXXXXX ERROR: in lifecycle::process" << dendl;
r = get_tier_target(zonegroup, target_placement, target_placement.storage_class, oc.tier);
if (!r && oc.tier.tier_type == "cloud") {
- ldpp_dout(oc.dpp, 0) << "Found cloud tier: " << target_placement.storage_class << dendl;
- r = transition_obj_to_cloud(oc);
- if (r < 0) {
- ldpp_dout(oc.dpp, 0) << "ERROR: failed to transition obj to cloud (r=" << r << ")"
- << dendl;
- }
+ ldpp_dout(oc.dpp, 20) << "Found cloud tier: " << target_placement.storage_class << dendl;
+ r = transition_obj_to_cloud(oc);
+ if (r < 0) {
+ ldpp_dout(oc.dpp, 0) << "ERROR: failed to transition obj to cloud (r=" << r << ")"
+ << dendl;
+ }
} else {
if (!oc.store->get_zone()->get_params().
valid_placement(target_placement)) {
using namespace std;
+static string get_key_instance(const rgw_obj_key& key)
+{
+ if (!key.instance.empty() &&
+ !key.have_null_instance()) {
+ return "-" + key.instance;
+ }
+ return "";
+}
+
static string get_key_oid(const rgw_obj_key& key)
{
string oid = key.name;
class RGWLCStreamReadCRF : public RGWStreamReadCRF
{
CephContext *cct;
+ const DoutPrefixProvider *dpp;
map<string, bufferlist> attrs;
uint64_t obj_size;
rgw_obj& obj;
off_t m_part_end;
public:
- RGWLCStreamReadCRF(CephContext *_cct, RGWRados* rados, RGWBucketInfo& bucket_info,
+ RGWLCStreamReadCRF(CephContext *_cct, const DoutPrefixProvider *_dpp,
+ RGWRados* rados, RGWBucketInfo& bucket_info,
RGWObjectCtx& obj_ctx, rgw_obj& _obj, const real_time &_mtime) :
RGWStreamReadCRF(rados, bucket_info, obj_ctx, _obj), cct(_cct),
- obj(_obj), mtime(_mtime) {}
+ dpp(_dpp), obj(_obj), mtime(_mtime) {}
~RGWLCStreamReadCRF() {};
read_op.params.lastmod = &read_mtime;
read_op.params.obj_size = &obj_size;
- int ret = read_op.prepare(y);
+ int ret = read_op.prepare(y, dpp);
if (ret < 0) {
ldout(cct, 0) << "ERROR: fail to prepare read_op, ret = " << ret << dendl;
return ret;
int read(off_t ofs, off_t end, bufferlist &bl) {
optional_yield y = null_yield;
- return read_op.read(ofs, end, bl, y);
+ return read_op.read(ofs, end, bl, y, dpp);
}
};
target_bucket.name = tier_ctx.target_bucket_name;
target_obj_name = tier_ctx.bucket_info.bucket.name + "/" +
- tier_ctx.obj.key.name;
+ tier_ctx.obj.key.name + get_key_instance(tier_ctx.obj.key);
dest_bucket.reset(new rgw::sal::RGWRadosBucket(tier_ctx.store, target_bucket));
// tier_ctx.obj.set_atomic(&tier_ctx.rctx); -- might need when updated to zipper SAL
/* Prepare Read from source */
- in_crf.reset(new RGWLCStreamReadCRF(tier_ctx.cct, tier_ctx.store->getRados(), tier_ctx.bucket_info,
+ in_crf.reset(new RGWLCStreamReadCRF(tier_ctx.cct, tier_ctx.dpp,
+ tier_ctx.store->getRados(), tier_ctx.bucket_info,
tier_ctx.rctx, tier_ctx.obj, tier_ctx.o.meta.mtime));
out_crf.reset(new RGWLCStreamPutCRF((CephContext *)(tier_ctx.cct), get_env(), this,
target_bucket.name = tier_ctx.target_bucket_name;
target_obj_name = tier_ctx.bucket_info.bucket.name + "/" +
- tier_ctx.obj.key.name;
+ tier_ctx.obj.key.name + get_key_instance(tier_ctx.obj.key);
dest_bucket.reset(new rgw::sal::RGWRadosBucket(tier_ctx.store, target_bucket));
// tier_ctx.obj.set_atomic(&tier_ctx.rctx); -- might need when updated to zipper SAL
/* Prepare Read from source */
- in_crf.reset(new RGWLCStreamReadCRF(tier_ctx.cct, tier_ctx.store->getRados(),
+ in_crf.reset(new RGWLCStreamReadCRF(tier_ctx.cct, tier_ctx.dpp, tier_ctx.store->getRados(),
tier_ctx.bucket_info, tier_ctx.rctx, tier_ctx.obj, tier_ctx.o.meta.mtime));
end = part_info.ofs + part_info.size - 1;
string target_obj_name;
target_obj_name = tier_ctx.bucket_info.bucket.name + "/" +
- tier_ctx.obj.key.name;
+ tier_ctx.obj.key.name + get_key_instance(tier_ctx.obj.key);
rgw_obj dest_obj(target_bucket, target_obj_name);
std::shared_ptr<RGWStreamReadCRF> in_crf;
rgw_rest_obj rest_obj;
}
if (retcode == -ENOENT) {
- in_crf.reset(new RGWLCStreamReadCRF(tier_ctx.cct, tier_ctx.store->getRados(), tier_ctx.bucket_info, tier_ctx.rctx, tier_ctx.obj, tier_ctx.o.meta.mtime));
+ in_crf.reset(new RGWLCStreamReadCRF(tier_ctx.cct, tier_ctx.dpp, tier_ctx.store->getRados(), tier_ctx.bucket_info, tier_ctx.rctx, tier_ctx.obj, tier_ctx.o.meta.mtime));
in_crf->init();
target_bucket.name = tier_ctx.target_bucket_name;
target_obj_name = tier_ctx.bucket_info.bucket.name + "/" +
- tier_ctx.obj.key.name;
+ tier_ctx.obj.key.name + get_key_instance(tier_ctx.obj.key);
std::shared_ptr<rgw::sal::RGWRadosBucket> dest_bucket;
dest_bucket.reset(new rgw::sal::RGWRadosBucket(tier_ctx.store, target_bucket));
struct RGWLCCloudTierCtx {
CephContext *cct;
+ const DoutPrefixProvider *dpp;
/* Source */
rgw_bucket_dir_entry& o;
bool is_multipart_upload{false};
- RGWLCCloudTierCtx(CephContext* _cct, rgw_bucket_dir_entry& _o,
- rgw::sal::RGWRadosStore* _store, RGWBucketInfo &_binfo, rgw_obj _obj,
- RGWObjectCtx& _rctx, std::shared_ptr<RGWRESTConn> _conn, string _bucket,
+ RGWLCCloudTierCtx(CephContext* _cct, const DoutPrefixProvider *_dpp,
+ rgw_bucket_dir_entry& _o, rgw::sal::RGWRadosStore* _store,
+ RGWBucketInfo &_binfo, rgw_obj _obj, RGWObjectCtx& _rctx,
+ std::shared_ptr<RGWRESTConn> _conn, string _bucket,
string _storage_class, RGWHTTPManager *_http)
- : cct(_cct), o(_o), store(_store), bucket_info(_binfo),
+ : cct(_cct), dpp(_dpp), o(_o), store(_store), bucket_info(_binfo),
obj(_obj), rctx(_rctx), conn(_conn), target_bucket_name(_bucket),
target_storage_class(_storage_class), http_manager(_http) {}
};
return max_head_size;
}
- string get_tier_type() {
+ const string get_tier_type() {
return tier_type;
}
tier_config.is_multipart_upload = t.is_multipart_upload;
}
- void get_tier_config(RGWObjTier* t) {
+ const void get_tier_config(RGWObjTier* t) {
if (tier_type != "cloud")
return;
RGWObjManifest m;
decode(m, attr_iter->second);
if (m.get_tier_type() == "cloud") {
+ /* XXX: Instead send presigned redirect or read-through */
op_ret = -ERR_INVALID_OBJECT_STATE;
ldpp_dout(this, 0) << "ERROR: Cannot get cloud tiered object. Failing with "
<< op_ret << dendl;
void init(const JSONFormattable& config) {
const string& t = config["type"];
- if (t == "email") {
- type = ACL_TYPE_EMAIL_USER;
- } else if (t == "uri") {
- type = ACL_TYPE_GROUP;
- } else {
- type = ACL_TYPE_CANON_USER;
- }
-
+ type = get_acl_type(t);
source_id = config["source_id"];
dest_id = config["dest_id"];
}
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
- string s;
- switch (type) {
- case ACL_TYPE_EMAIL_USER:
- s = "email";
- break;
- case ACL_TYPE_GROUP:
- s = "uri";
- break;
- default:
- s = "id";
- break;
- }
+
+ string s = get_acl_type_str(type);
encode(s, bl);
encode(source_id, bl);
encode(dest_id, bl);
void decode(bufferlist::const_iterator& bl) {
DECODE_START(1, bl);
- string s;
- decode(s, bl);
- if (s == "email") {
- type = ACL_TYPE_EMAIL_USER;
- } else if (s == "uri") {
- type = ACL_TYPE_GROUP;
- } else {
- type = ACL_TYPE_CANON_USER;
- }
+ string s;
+ decode(s, bl);
+
+ type = get_acl_type(s);
decode(source_id, bl);
decode(dest_id, bl);
DECODE_FINISH(bl);