]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/CloudTransition: Update object metadata and bi post cloud tranistion
authorSoumya Koduri <skoduri@redhat.com>
Tue, 28 Jul 2020 20:27:04 +0000 (01:57 +0530)
committerSoumya Koduri <skoduri@redhat.com>
Thu, 18 Nov 2021 07:22:47 +0000 (12:52 +0530)
After transitioning the object to cloud, following updates are done
to the existing object.

* In bi entry, change object category to CloudTiered
* Update cloud-tier details (like endpoint, keys etc) in Object Manifest
* Mark the tail objects expired to be deleted by gc

TODO:
* Update all the cloud config details including multiparts
* Check if any other object metadata needs to be changed
* Optimize to avoid using read_op again to read attrs.
* Check for mtime to resolve conflicts when multiple zones try to transition obj

Signed-off-by: Soumya Koduri <skoduri@redhat.com>
src/cls/rgw/cls_rgw_types.h
src/rgw/rgw_common.h
src/rgw/rgw_json_enc.cc
src/rgw/rgw_lc.cc
src/rgw/rgw_obj_manifest.h

index 7314ad8e21cd17b30f850a0aad0ee6c17e29d166..b19c46266eeaa76a6e3791a54ce4b1f09cf6866f 100644 (file)
@@ -172,6 +172,8 @@ enum class RGWObjCategory : uint8_t {
                   // uploads; not currently used in the codebase
 
   MultiMeta = 3,  // b-i entries for multipart upload metadata objs
+
+  CloudTiered = 4, // b-i entries which are tiered to external cloud
 };
 
 
index c86d3dd793d954e55aa3539ab90fa074e5cd8a25..17faa4638445fa2e690452bab8d7edb4c78bee2c 100644 (file)
@@ -1983,6 +1983,8 @@ static inline const char *rgw_obj_category_name(RGWObjCategory category)
     return "rgw.shadow";
   case RGWObjCategory::MultiMeta:
     return "rgw.multimeta";
+  case RGWObjCategory::CloudTiered:
+    return "rgw.cloudtiered";
   }
 
   return "unknown";
index 879f0f9164505951f3a7c621947447d2c3bca17a..c37f7098e39375add8210a926b9193e022669c64 100644 (file)
@@ -99,6 +99,12 @@ void RGWObjManifestRule::dump(Formatter *f) const
   encode_json("override_prefix", override_prefix, f);
 }
 
+void RGWObjTier::dump(Formatter *f) const
+{
+  f->dump_string("name", name);
+  f->dump_object("tier_placement", tier_placement);
+}
+
 void rgw_bucket_placement::dump(Formatter *f) const
 {
   encode_json("bucket", bucket, f);
@@ -144,6 +150,11 @@ void RGWObjManifest::dump(Formatter *f) const
   ::encode_json("rules", rules, f);
   ::encode_json("tail_instance", tail_instance, f);
   ::encode_json("tail_placement", tail_placement, f);
+  ::encode_json("tier_type", tier_type, f);
+  
+  if (tier_type == "cloud") {
+    ::encode_json("tier_config", tier_config, f);
+  }
 
   // nullptr being passed into iterators since there
   // is no cct and we aren't doing anything with these
index 83f1ae4c65683fe9436a60e0d1ffb189045ab2c7..bbeef3c4f257553a9ed21a362cd275a305f48582 100644 (file)
@@ -1273,6 +1273,78 @@ public:
 
    return 0;
  }
+
+  int update_tier_obj(lc_op_ctx& oc, RGWLCCloudTierCtx& tier_ctx) {
+
+    map<string, bufferlist> attrs;
+    RGWRados::Object op_target(tier_ctx.store->getRados(),
+                               tier_ctx.bucket_info,
+                                tier_ctx.rctx, tier_ctx.obj);
+
+    RGWRados::Object::Read read_op(&op_target);
+
+    read_op.params.attrs = &attrs;
+
+    int r = read_op.prepare(null_yield);
+    if (r < 0) {
+      return r;
+    }
+
+    tier_ctx.rctx.set_atomic(tier_ctx.obj);
+    
+    RGWRados::Object::Write obj_op(&op_target);
+    RGWObjState *s = tier_ctx.rctx.get_state(tier_ctx.obj);
+
+    obj_op.meta.modify_tail = true;
+    obj_op.meta.category = RGWObjCategory::CloudTiered;
+    obj_op.meta.delete_at = real_time();
+    obj_op.meta.data = NULL;
+    obj_op.meta.if_match = NULL;
+    obj_op.meta.if_nomatch = NULL;
+    obj_op.meta.user_data = NULL;
+    obj_op.meta.zones_trace = NULL;
+    
+    RGWObjManifest *pmanifest; 
+
+    pmanifest = &(*s->manifest);
+    RGWObjTier tier_config;
+    tier_config.name = oc.tier.storage_class;
+    tier_config.tier_placement = oc.tier;
+
+    pmanifest->set_tier_type("cloud");
+    pmanifest->set_tier_config(tier_config);
+
+    /* check if its necessary */
+    rgw_placement_rule target_placement;
+    target_placement.inherit_from(tier_ctx.bucket_info.placement_rule);
+    target_placement.storage_class = oc.tier.storage_class;
+    pmanifest->set_head(target_placement, tier_ctx.obj, 0);
+
+    pmanifest->set_tail_placement(target_placement, tier_ctx.obj.bucket);
+
+    /* should the obj_size also be set to '0' or is it needed
+     * to keep track of original size before transition. 
+     * But unless obj_size is set to '0', obj_iters cannot
+     * be reset I guess
+     */
+    //pmanifest->set_obj_size(0);
+
+    obj_op.meta.manifest = pmanifest;
+
+    /* update storage class */
+    bufferlist bl;
+    bl.append(oc.tier.storage_class);
+    attrs[RGW_ATTR_STORAGE_CLASS] = bl;
+
+
+    obj_op.write_meta(tier_ctx.o.meta.size, 0, attrs, null_yield);
+    if (r < 0) {
+      return r;
+    }
+
+    return 0;
+  }
+
   int transition_obj_to_cloud(lc_op_ctx& oc) {
     std::shared_ptr<RGWRESTConn> conn;
 
@@ -1315,6 +1387,12 @@ public:
       return ret;
     }
 
+    ret = update_tier_obj(oc, tier_ctx);
+    if (ret < 0) {
+      ldpp_dout(oc.dpp, 0) << "Updating tier object failed ret=" << ret << dendl;
+      return ret;
+    }
+
     return 0;
   }
 
index 45f3ac8adf7e01903f3b72cbc2cb59540ab8f6cd..9cb7fec8216b73ad0d65a194fba690b2577b2ad8 100644 (file)
@@ -18,6 +18,7 @@
 #include "rgw_common.h"
 #include "rgw_compression_types.h"
 #include "rgw_sal.h"
+#include "rgw_zone.h"
 
 class RGWSI_Zone;
 struct RGWZoneGroup;
@@ -147,6 +148,30 @@ struct RGWObjManifestRule {
 };
 WRITE_CLASS_ENCODER(RGWObjManifestRule)
 
+struct RGWObjTier {
+    string name;
+    RGWZoneGroupPlacementTier tier_placement;
+    /* XXX: Add multipart upload details */
+
+    RGWObjTier(): name("none") {}
+
+    void encode(bufferlist& bl) const {
+      ENCODE_START(2, 2, bl);
+      encode(name, bl);
+      encode(tier_placement, bl);
+      ENCODE_FINISH(bl);
+    }
+
+    void decode(bufferlist::const_iterator& bl) {
+      DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl);
+      decode(name, bl);
+      decode(tier_placement, bl);
+      DECODE_FINISH(bl);
+    }
+    void dump(Formatter *f) const;
+};
+WRITE_CLASS_ENCODER(RGWObjTier)
+
 class RGWObjManifest {
 protected:
   bool explicit_objs{false}; /* really old manifest? */
@@ -166,6 +191,9 @@ protected:
 
   std::string tail_instance; /* tail object's instance */
 
+  string tier_type;
+  RGWObjTier tier_config;
+
   void convert_to_explicit(const DoutPrefixProvider *dpp, const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params);
   int append_explicit(const DoutPrefixProvider *dpp, RGWObjManifest& m, const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params);
   void append_rules(RGWObjManifest& m, std::map<uint64_t, RGWObjManifestRule>::iterator& iter, std::string *override_prefix);
@@ -187,6 +215,8 @@ public:
     tail_placement = rhs.tail_placement;
     rules = rhs.rules;
     tail_instance = rhs.tail_instance;
+    tier_type = rhs.tier_type;
+    tier_config = rhs.tier_config;
     return *this;
   }
 
@@ -218,7 +248,7 @@ public:
   }
 
   void encode(bufferlist& bl) const {
-    ENCODE_START(7, 6, bl);
+    ENCODE_START(8, 6, bl);
     encode(obj_size, bl);
     encode(objs, bl);
     encode(explicit_objs, bl);
@@ -239,6 +269,8 @@ public:
     }
     encode(head_placement_rule, bl);
     encode(tail_placement.placement_rule, bl);
+    encode(tier_type, bl);
+    encode(tier_config, bl);
     ENCODE_FINISH(bl);
   }
 
@@ -311,6 +343,11 @@ public:
       decode(tail_placement.placement_rule, bl);
     }
 
+    if (struct_v >= 8) {
+      decode(tier_type, bl);
+      decode(tier_config, bl);
+    }
+
     DECODE_FINISH(bl);
   }
 
@@ -409,6 +446,36 @@ public:
     return max_head_size;
   }
 
+  string get_tier_type() {
+      return tier_type;
+  }
+
+  void set_tier_type(string value) {
+      /* Only "cloud" tier-type is supported for now */
+      if (value == "cloud") {
+        tier_type = value;
+      } else {
+        tier_type = "none";
+      }
+  }
+
+  void set_tier_config(RGWObjTier t) {
+      /* Set only if tier_type set to "cloud" */
+      if (tier_type != "cloud")
+        return;
+
+      tier_config.name = t.name;
+      tier_config.tier_placement = t.tier_placement;
+  }
+
+  void get_tier_config(RGWObjTier* t) {
+      if (tier_type != "cloud")
+        return;
+
+      t->name = tier_config.name;
+      t->tier_placement = tier_config.tier_placement;
+  }
+
   class obj_iterator {
     const DoutPrefixProvider *dpp;
     const RGWObjManifest *manifest = nullptr;