]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/cloud-transition: New attrs to detect cloudtiered objects
authorSoumya Koduri <skoduri@redhat.com>
Tue, 25 Apr 2023 18:04:28 +0000 (23:34 +0530)
committerSoumya Koduri <skoduri@redhat.com>
Mon, 1 May 2023 14:04:06 +0000 (19:34 +0530)
Add new attrs "RGW_ATTR_CLOUD_TIER_TYPE" and "RGW_ATTR_CLOUD_TIER_CONFIG"
to store details about cloud-tiered objects so that they get synced accordingly
in a multisite environment.

Signed-off-by: Soumya Koduri <skoduri@redhat.com>
src/rgw/driver/rados/rgw_putobj_processor.cc
src/rgw/rgw_common.h
src/rgw/rgw_op.cc

index d52e303291d1af26a48d470dbae9c61ddd6390c8..11ba9d713aa9399c274b5c9dbff432b393222782 100644 (file)
@@ -28,6 +28,41 @@ using namespace std;
 
 namespace rgw::putobj {
 
+/*
+ * For the cloudtiered objects, update the object manifest with the
+ * cloudtier config info read from the attrs.
+ * Since these attrs are used internally for only replication, do not store them
+ * in the head object.
+ */
+void read_cloudtier_info_from_attrs(rgw::sal::Attrs& attrs, RGWObjCategory& category,
+                          RGWObjManifest& manifest) {
+  auto attr_iter = attrs.find(RGW_ATTR_CLOUD_TIER_TYPE);
+  if (attr_iter != attrs.end()) {
+    auto i = attr_iter->second;
+    string m = i.to_str();
+
+    if (m == "cloud-s3") {
+      category = RGWObjCategory::CloudTiered;
+      manifest.set_tier_type("cloud-s3");
+
+      auto config_iter = attrs.find(RGW_ATTR_CLOUD_TIER_CONFIG);
+      if (config_iter != attrs.end()) {
+        auto i = config_iter->second.cbegin();
+        RGWObjTier tier_config;
+
+        try {
+          using ceph::decode;
+          decode(tier_config, i);
+          manifest.set_tier_config(tier_config);
+          attrs.erase(config_iter);
+        } catch (buffer::error& err) {
+        }
+      }
+    }
+    attrs.erase(attr_iter);
+  }
+}
+
 int HeadObjectProcessor::process(bufferlist&& data, uint64_t logical_offset)
 {
   const bool flush = (data.length() == 0);
@@ -341,6 +376,8 @@ int AtomicObjectProcessor::complete(size_t accounted_size,
   obj_op.meta.zones_trace = zones_trace;
   obj_op.meta.modify_tail = true;
 
+  read_cloudtier_info_from_attrs(attrs, obj_op.meta.category, manifest);
+
   r = obj_op.write_meta(dpp, actual_size, accounted_size, attrs, y);
   if (r < 0) {
     if (r == -ETIMEDOUT) {
index 7cabd8e4ca690ce2c52313cae7f3de6a6e202f5f..7d649f3c1f46c873adb027ea53a881b390ddae7b 100644 (file)
@@ -137,6 +137,12 @@ using ceph::crypto::MD5;
 
 #define RGW_ATTR_APPEND_PART_NUM    RGW_ATTR_PREFIX "append_part_num"
 
+/* Attrs to store cloudtier config information. These are used internally
+ * for the replication of cloudtiered objects but not stored as xattrs in
+ * the head object. */
+#define RGW_ATTR_CLOUD_TIER_TYPE    RGW_ATTR_PREFIX "cloud_tier_type"
+#define RGW_ATTR_CLOUD_TIER_CONFIG    RGW_ATTR_PREFIX "cloud_tier_config"
+
 #define RGW_ATTR_OBJ_REPLICATION_STATUS RGW_ATTR_PREFIX "amz-replication-status"
 
 /* IAM Policy */
index 731dc101d4dffd72d80bfd0cf7e574bed741789a..8b23c1c2da9f26781166cf2ba1dfbceefa1529f9 100644 (file)
@@ -914,6 +914,41 @@ void rgw_build_iam_environment(rgw::sal::Driver* driver,
   }
 }
 
+/*
+ * GET on CloudTiered objects is processed only when sent from the sync client.
+ * In all other cases, fail with `ERR_INVALID_OBJECT_STATE`.
+ */
+int handle_cloudtier_obj(rgw::sal::Attrs& attrs, bool sync_cloudtiered) {
+  int op_ret = 0;
+  auto attr_iter = attrs.find(RGW_ATTR_MANIFEST);
+  if (attr_iter != attrs.end()) {
+    RGWObjManifest m;
+    try {
+      decode(m, attr_iter->second);
+      if (m.get_tier_type() == "cloud-s3") {
+        if (!sync_cloudtiered) {
+          /* XXX: Instead send presigned redirect or read-through */
+          op_ret = -ERR_INVALID_OBJECT_STATE;
+        } else { // fetch object for sync and set cloud_tier attrs
+          bufferlist t, t_tier;
+          RGWObjTier tier_config;
+          m.get_tier_config(&tier_config);
+
+          t.append("cloud-s3");
+          attrs[RGW_ATTR_CLOUD_TIER_TYPE] = t;
+          encode(tier_config, t_tier);
+          attrs[RGW_ATTR_CLOUD_TIER_CONFIG] = t_tier;
+        }
+      }
+    } catch (const buffer::end_of_buffer&) {
+      // ignore empty manifest; it's not cloud-tiered
+    } catch (const std::exception& e) {
+    }
+  }
+
+  return op_ret;
+}
+
 void rgw_bucket_object_pre_exec(req_state *s)
 {
   if (s->expect_cont)
@@ -2257,24 +2292,15 @@ void RGWGetObj::execute(optional_yield y)
       filter = &*decompress;
   }
 
-  attr_iter = attrs.find(RGW_ATTR_MANIFEST);
-  if (attr_iter != attrs.end() && get_type() == RGW_OP_GET_OBJ && get_data) {
-    RGWObjManifest m;
-    try {
-      decode(m, attr_iter->second);
-      if (m.get_tier_type() == "cloud-s3" && !sync_cloudtiered) {
-        /* XXX: Instead send presigned redirect or read-through */
-        op_ret = -ERR_INVALID_OBJECT_STATE;
+  if (get_type() == RGW_OP_GET_OBJ && get_data) {
+    op_ret = handle_cloudtier_obj(attrs, sync_cloudtiered);
+    if (op_ret < 0) {
+      ldpp_dout(this, 4) << "Cannot get cloud tiered object: " << *s->object
+          <<". Failing with " << op_ret << dendl;
+      if (op_ret == -ERR_INVALID_OBJECT_STATE) {
         s->err.message = "This object was transitioned to cloud-s3";
-        ldpp_dout(this, 4) << "Cannot get cloud tiered object. Failing with "
-            << op_ret << dendl;
-        goto done_err;
       }
-    } catch (const buffer::end_of_buffer&) {
-      // ignore empty manifest; it's not cloud-tiered
-    } catch (const std::exception& e) {
-      ldpp_dout(this, 1) << "WARNING: failed to decode object manifest for "
-          << *s->object << ": " << e.what() << dendl;
+      goto done_err;
     }
   }