]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/osd: implement the injectdataerr admin command.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Wed, 19 May 2021 12:30:23 +0000 (12:30 +0000)
committerKefu Chai <kchai@redhat.com>
Wed, 26 May 2021 00:14:59 +0000 (08:14 +0800)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/crimson/admin/osd_admin.cc
src/crimson/admin/osd_admin.h
src/crimson/osd/osd.cc

index 21132b2f2b8f30f06b053177b1fc425ee16c0d8d..cbca5fead7ec5af2ec66da3c954be59d0e12061b 100644 (file)
 using crimson::osd::OSD;
 using namespace crimson::common;
 
+namespace {
+seastar::logger& logger()
+{
+  return crimson::get_logger(ceph_subsys_osd);
+}
+}  // namespace
+
 namespace crimson::admin {
 
 using crimson::common::local_conf;
@@ -265,4 +272,105 @@ private:
 };
 template std::unique_ptr<AdminSocketHook> make_asok_hook<SeastarMetricsHook>();
 
+
+static ghobject_t test_ops_get_object_name(
+  const OSDMap& osdmap,
+  const cmdmap_t& cmdmap)
+{
+  auto pool = [&] {
+    auto pool_arg = cmd_getval<std::string>(cmdmap, "pool");
+    if (!pool_arg) {
+      throw std::invalid_argument{"No 'pool' specified"};
+    }
+    int64_t pool = osdmap.lookup_pg_pool_name(*pool_arg);
+    if (pool < 0 && std::isdigit((*pool_arg)[0])) {
+      pool = std::atoll(pool_arg->c_str());
+    }
+    if (pool < 0) {
+      // the return type of `fmt::format` is `std::string`
+      using namespace fmt::literals;
+      throw std::invalid_argument{
+        "Invalid pool '{}'"_format(*pool_arg)
+      };
+    }
+    return pool;
+  }();
+
+  auto [ objname, nspace, raw_pg ] = [&] {
+    auto obj_arg = cmd_getval<std::string>(cmdmap, "objname");
+    if (!obj_arg) {
+      throw std::invalid_argument{"No 'objname' specified"};
+    }
+    std::string objname, nspace;
+    if (std::size_t sep_pos = obj_arg->find_first_of('/');
+        sep_pos != obj_arg->npos) {
+      nspace = obj_arg->substr(0, sep_pos);
+      objname = obj_arg->substr(sep_pos+1);
+    } else {
+      objname = *obj_arg;
+    }
+    pg_t raw_pg;
+    if (object_locator_t oloc(pool, nspace);
+        osdmap.object_locator_to_pg(object_t(objname), oloc,  raw_pg) < 0) {
+      throw std::invalid_argument{"Invalid namespace/objname"};
+    }
+    return std::make_tuple(std::move(objname),
+                           std::move(nspace),
+                           std::move(raw_pg));
+  }();
+
+  auto shard_id = cmd_getval_or<int64_t>(cmdmap,
+                                        "shardid",
+                                        shard_id_t::NO_SHARD);
+
+  return ghobject_t{
+    hobject_t{
+      object_t{objname}, std::string{}, CEPH_NOSNAP, raw_pg.ps(), pool, nspace
+    },
+    ghobject_t::NO_GEN,
+    shard_id_t{static_cast<int8_t>(shard_id)}
+  };
+}
+
+// Usage:
+//   injectdataerr <pool> [namespace/]<obj-name> [shardid]
+class InjectDataErrorHook : public AdminSocketHook {
+public:
+  InjectDataErrorHook(crimson::osd::ShardServices& shard_services)  :
+   AdminSocketHook("injectdataerr",
+    "name=pool,type=CephString " \
+    "name=objname,type=CephObjectname " \
+    "name=shardid,type=CephInt,req=false,range=0|255",
+    "inject data error to an object"),
+   shard_services(shard_services) {
+  }
+
+  seastar::future<tell_result_t> call(const cmdmap_t& cmdmap,
+                                     std::string_view format,
+                                     ceph::bufferlist&& input) const final
+  {
+    ghobject_t obj;
+    try {
+      obj = test_ops_get_object_name(*shard_services.get_osdmap(), cmdmap);
+    } catch (const std::invalid_argument& e) {
+      logger().info("error during data error injection: {}", e.what());
+      return seastar::make_ready_future<tell_result_t>(-EINVAL,
+                                                      e.what());
+    }
+    return shard_services.get_store().inject_data_error(obj).then([=] {
+      logger().info("successfully injected data error for obj={}", obj);
+      ceph::bufferlist bl;
+      bl.append("ok"sv);
+      return seastar::make_ready_future<tell_result_t>(0,
+                                                      std::string{}, // no err
+                                                      std::move(bl));
+    });
+  }
+
+private:
+  crimson::osd::ShardServices& shard_services;
+};
+template std::unique_ptr<AdminSocketHook> make_asok_hook<InjectDataErrorHook>(
+  crimson::osd::ShardServices&);
+
 } // namespace crimson::admin
index f68bcf9b7389216a73d6a79238ef0feb9152510b..dccbca38d255af94263758a9ff35ed7edb6ed0f0 100644 (file)
@@ -15,6 +15,7 @@ class SendBeaconHook;
 class DumpPGStateHistory;
 class SeastarMetricsHook;
 class DumpPerfCountersHook;
+class InjectDataErrorHook;
 
 template<class Hook, class... Args>
 std::unique_ptr<AdminSocketHook> make_asok_hook(Args&&... args);
index 4a653011396781614cb1722b4db54901f4909f54..9303c6bcf9e4267c738462da5ae9aaac425e5d48 100644 (file)
@@ -443,6 +443,7 @@ seastar::future<> OSD::start_asok_admin()
       asok->register_command(make_asok_hook<DumpPGStateHistory>(std::as_const(*this))),
       asok->register_command(make_asok_hook<SeastarMetricsHook>()),
       asok->register_command(make_asok_hook<DumpPerfCountersHook>()),
+      asok->register_command(make_asok_hook<InjectDataErrorHook>(get_shard_services())),
       // PG commands
       asok->register_command(make_asok_hook<pg::QueryCommand>(*this)),
       asok->register_command(make_asok_hook<pg::MarkUnfoundLostCommand>(*this)));