]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
first wip-leonidc-import-migration-mod-02-16
authorLeonid Chernin <leonidc@il.ibm.com>
Mon, 2 Feb 2026 06:01:14 +0000 (08:01 +0200)
committerLeonid Chernin <leonidc@il.ibm.com>
Mon, 9 Feb 2026 09:55:57 +0000 (11:55 +0200)
Signed-off-by: Leonid Chernin <leonidc@il.ibm.com>
src/librbd/api/Migration.cc
src/librbd/migration/OpenSourceImageRequest.cc
src/mon/MonCommands.h

index 34cd0f1336903cc23ce323c4b8802843fbe4408c..d28f723e88b18bb3526b2a9a2dfc60c9537f0d25 100644 (file)
@@ -39,7 +39,7 @@
 #include "librbd/migration/NativeFormat.h"
 #include "librbd/mirror/DisableRequest.h"
 #include "librbd/mirror/EnableRequest.h"
-
+//#include <rados/librados.hpp>
 #include <boost/scope_exit.hpp>
 
 #include <shared_mutex> // for std::shared_lock
@@ -515,6 +515,107 @@ int Migration<I>::prepare(librados::IoCtx& io_ctx,
   return r;
 }
 
+constexpr const char* SPEC_SECRET_KEY = "secret_key";
+
+static int get_config_key(librados::Rados& rados, const std::string& key,
+                   std::string* value) {
+  std::string cmd =
+    "{"
+      "\"prefix\": \"config-key get\", "
+      "\"key\": \"" + key + "\""
+    "}";
+
+  bufferlist out_bl;
+
+  int r = rados.mon_command(std::move(cmd), {}, &out_bl, nullptr);
+  if (r == -EINVAL) {
+    return -EOPNOTSUPP;
+  } else if (r < 0 && r != -ENOENT) {
+    return r;
+  }
+
+  *value = out_bl.to_str();
+  return 0;
+}
+
+static int set_config_key(librados::Rados& rados, const std::string& key,
+                   const std::string& value) {
+  std::string cmd;
+  if (value.empty()) {
+    cmd = "{"
+            "\"prefix\": \"config-key rm\", "
+            "\"key\": \"" + key + "\""
+          "}";
+  } else {
+    cmd = "{"
+            "\"prefix\": \"config-key set\", "
+            "\"key\": \"" + key + "\", "
+            "\"val\": \"" + value + "\""
+          "}";
+  }
+  bufferlist out_bl;
+
+  int r = rados.mon_command(std::move(cmd), {}, &out_bl, nullptr);
+  if (r == -EINVAL) {
+    return -EOPNOTSUPP;
+  } else if (r < 0) {
+    return r;
+  }
+
+  return 0;
+}
+
+static int try_get_fsid_secret_key(json_spirit::mObject source_spec_object,
+                                  librados::IoCtx& dest_io_ctx) {
+    std::string secret_key;
+    auto cct = reinterpret_cast<CephContext *>(dest_io_ctx.cct());
+    auto it = source_spec_object.find("secret_key");
+    if (it != source_spec_object.end()) {
+      try {
+        secret_key = it->second.get_str();
+        ldout(cct, 5) << "found secret_key in source spec " << secret_key << dendl;
+      } catch (std::runtime_error&) {
+        lderr(cct) << "secret_key must be a string" << dendl;
+        return -EINVAL;
+      }
+
+      std::string fsid;
+      auto it_fsid = source_spec_object.find("source_cluster_fsid");
+      if (it_fsid != source_spec_object.end()) {
+        fsid = it_fsid->second.get_str();
+        ldout(cct, 5) << "found fsid in source spec " << fsid << dendl;
+      } else {
+        lderr(cct) << "source_cluster_fsid missing in spec" << dendl;
+        return -EINVAL;
+      }
+      source_spec_object.erase("secret_key"); // need to remove the key from the spec
+      std::string sanitized_source_spec =
+          json_spirit::write(source_spec_object);
+      ldout(cct, 5) << "sanitized source spec: "
+                     << sanitized_source_spec << dendl;
+      librados::Rados rados(dest_io_ctx);
+      int r = set_config_key(rados,  "migration/fsid/" + fsid, secret_key);
+      if (r < 0) {
+       lderr(reinterpret_cast<CephContext*>(rados.cct()))
+           << "failed to store secret key in monitor: "
+           << cpp_strerror(r) << dendl;
+       return r;
+      }
+      ldout(cct, 5) << "key set " <<  fsid << dendl;
+      std::string value;
+      r = get_config_key(rados, "migration/fsid/" + fsid, &value);
+      if (r < 0) {
+        lderr(reinterpret_cast<CephContext*>(rados.cct()))
+           << "failed to fetch secret key from the monitor: "
+           << cpp_strerror(r) << dendl;
+        return r;
+      }
+      ldout(cct, 5) << " get value by key " <<  fsid <<" got "<< value << dendl;
+    }
+    return 0;
+}
+
+
 template <typename I>
 int Migration<I>::prepare_import(
     const std::string& source_spec, librados::IoCtx& dest_io_ctx,
@@ -529,6 +630,20 @@ int Migration<I>::prepare_import(
                  << dest_io_ctx.get_pool_name() << "/"
                  << dest_image_name << ", opts=" << opts << dendl;
 
+  // use json-spirit to clean-up json formatting
+  json_spirit::mObject source_spec_object;
+  json_spirit::mValue json_root;
+  if(json_spirit::read(source_spec, json_root)) {
+    try {
+      source_spec_object = json_root.get_obj();
+    } catch (std::runtime_error&) {
+      lderr(cct) << "failed to clean source spec" << dendl;
+      return -EINVAL;
+    }
+  }
+
+  try_get_fsid_secret_key(source_spec_object,  dest_io_ctx);
+
   I* src_image_ctx;
   librados::Rados* src_rados;
   C_SaferCond open_ctx;
@@ -561,17 +676,6 @@ int Migration<I>::prepare_import(
 
   ldout(cct, 20) << "updated opts=" << opts << dendl;
 
-  // use json-spirit to clean-up json formatting
-  json_spirit::mObject source_spec_object;
-  json_spirit::mValue json_root;
-  if(json_spirit::read(source_spec, json_root)) {
-    try {
-      source_spec_object = json_root.get_obj();
-    } catch (std::runtime_error&) {
-      lderr(cct) << "failed to clean source spec" << dendl;
-      return -EINVAL;
-    }
-  }
 
   auto dst_image_ctx = I::create(
     dest_image_name, util::generate_image_id(dest_io_ctx), nullptr,
index 3288a813e9f7bd6bf7f70a1c5ed324e679d351ef..161a61a3b9cde1e18122895d273c64b6cffa10c0 100644 (file)
 namespace librbd {
 namespace migration {
 
+  static int get_config_key(librados::Rados& rados, const std::string& key,
+                     std::string* value) {
+  std::string cmd =
+    "{"
+      "\"prefix\": \"config-key get\", "
+      "\"key\": \"" + key + "\""
+    "}";
+
+  bufferlist out_bl;
+
+  int r = rados.mon_command(std::move(cmd), {}, &out_bl, nullptr);
+  if (r == -EINVAL) {
+    return -EOPNOTSUPP;
+  } else if (r < 0 && r != -ENOENT) {
+    return r;
+  }
+
+  *value = out_bl.to_str();
+  return 0;
+}
+
 template <typename I>
 OpenSourceImageRequest<I>::OpenSourceImageRequest(
     librados::IoCtx& dst_io_ctx, I* dst_image_ctx, uint64_t src_snap_id,
@@ -74,7 +95,12 @@ template <typename I>
 void OpenSourceImageRequest<I>::open_native(
     const json_spirit::mObject& source_spec_object, bool import_only) {
   ldout(m_cct, 10) << dendl;
-
+  std::string fsid;
+  auto it_fsid = source_spec_object.find("source_cluster_fsid");
+  if (it_fsid != source_spec_object.end()) {
+    fsid = it_fsid->second.get_str();
+    ldout(m_cct, 5) << "open_native: found fsid in source spec " << fsid << dendl;
+  }
   int r = NativeFormat<I>::create_image_ctx(m_dst_io_ctx, source_spec_object,
                                             import_only, m_src_snap_id,
                                             m_src_image_ctx, m_src_rados);
@@ -84,7 +110,15 @@ void OpenSourceImageRequest<I>::open_native(
     finish(r);
     return;
   }
-
+  std::string value;
+  r = get_config_key(**m_src_rados, "migration/fsid/" + fsid, &value);
+  if (r < 0) {
+    lderr(reinterpret_cast<CephContext*>((*m_src_rados)->cct()))
+       << "failed to fetch secret key from the monitor: "
+       << cpp_strerror(r) << dendl;
+    return ;
+  }
+  ldout(m_cct, 5) << " get value by key " <<  fsid <<" got "<< value << dendl;
   auto src_image_ctx = *m_src_image_ctx;
   src_image_ctx->child = m_dst_image_ctx;
 
index ca9907c51e6d1f068c31cb2b2a22350f372dbcf5..81ffb7010c4e425a702aa871562555f8de45408d 100644 (file)
@@ -1459,6 +1459,28 @@ COMMAND("nvme-gw listeners"
        " show all nvmeof gateways listeners within (pool, group)",
        "mon", "r")
 
+COMMAND("import-migration put-metadata"
+   " name=pool,type=CephString"
+   " name=image,type=CephString"
+   " name=migration_id,type=CephString"
+   " name=key_ref,type=CephString",
+   "Store migration metadata in monitor DB",
+   "mon", "rw")
+
+COMMAND("import-migration get-metadata"
+   " name=pool,type=CephString"
+   " name=image,type=CephString"
+   " name=migration_id,type=CephString",
+   "Retrieve migration metadata from monitor DB",
+   "mon", "r")
+
+COMMAND("import-migration erase-metadata"
+   " name=pool,type=CephString"
+   " name=image,type=CephString"
+   " name=migration_id,type=CephString",
+   "Erase migration metadata from monitor DB",
+   "mon", "rw")
+
 // these are tell commands that were implemented as CLI commands in
 // the broken pre-octopus way that we want to allow to work when a
 // monitor has upgraded to octopus+ but the monmap min_mon_release is