From d8712e67221d4ca27c024adad4628829df425970 Mon Sep 17 00:00:00 2001 From: JonBailey1993 Date: Mon, 25 Nov 2024 11:40:09 +0000 Subject: [PATCH] src/common/json: Modified JSON structures so they take advantage of ceph_json.h fully. Also moved and renamed JSONStructures files so they structures are more easily identifiable and usable by others if desired. Signed-off-by: Jon Bailey --- src/common/CMakeLists.txt | 1 + src/common/io_exerciser/CMakeLists.txt | 4 +- src/common/io_exerciser/JsonStructures.cc | 453 -------------------- src/common/io_exerciser/JsonStructures.h | 302 ------------- src/common/io_exerciser/RadosIo.cc | 101 +++-- src/common/json/BalancerStructures.cc | 38 ++ src/common/json/BalancerStructures.h | 35 ++ src/common/json/CMakeLists.txt | 4 + src/common/json/ConfigStructures.cc | 20 + src/common/json/ConfigStructures.h | 24 ++ src/common/json/OSDStructures.cc | 150 +++++++ src/common/json/OSDStructures.h | 189 ++++++++ src/test/osd/CMakeLists.txt | 2 +- src/test/osd/ceph_test_rados_io_sequence.cc | 145 ++++--- src/test/osd/ceph_test_rados_io_sequence.h | 4 +- 15 files changed, 609 insertions(+), 863 deletions(-) delete mode 100644 src/common/io_exerciser/JsonStructures.cc delete mode 100644 src/common/io_exerciser/JsonStructures.h create mode 100644 src/common/json/BalancerStructures.cc create mode 100644 src/common/json/BalancerStructures.h create mode 100644 src/common/json/CMakeLists.txt create mode 100644 src/common/json/ConfigStructures.cc create mode 100644 src/common/json/ConfigStructures.h create mode 100644 src/common/json/OSDStructures.cc create mode 100644 src/common/json/OSDStructures.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index ea3cce16609..c607839a8d2 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -13,6 +13,7 @@ if(WIN32) endif() add_subdirectory(io_exerciser) +add_subdirectory(json) add_subdirectory(options) set(common_srcs diff --git a/src/common/io_exerciser/CMakeLists.txt b/src/common/io_exerciser/CMakeLists.txt index ccad61b57a2..ab2e64fc222 100644 --- a/src/common/io_exerciser/CMakeLists.txt +++ b/src/common/io_exerciser/CMakeLists.txt @@ -5,11 +5,11 @@ add_library(object_io_exerciser STATIC Model.cc ObjectModel.cc RadosIo.cc - JsonStructures.cc EcIoSequence.cc ) target_link_libraries(object_io_exerciser - librados + librados global + json_structures ) \ No newline at end of file diff --git a/src/common/io_exerciser/JsonStructures.cc b/src/common/io_exerciser/JsonStructures.cc deleted file mode 100644 index c330484e937..00000000000 --- a/src/common/io_exerciser/JsonStructures.cc +++ /dev/null @@ -1,453 +0,0 @@ -#include "JsonStructures.h" - -#include "OpType.h" -#include "common/ceph_json.h" - -using namespace ceph::io_exerciser::json; - -JSONStructure::JSONStructure(std::shared_ptr formatter) - : formatter(formatter) {} - -std::string JSONStructure::encode_json() { - oss.clear(); - - dump(); - formatter->flush(oss); - return oss.str(); -} - -OSDMapRequest::OSDMapRequest(const std::string& pool_name, - const std::string& object, - const std::string& nspace, - std::shared_ptr formatter) - : JSONStructure(formatter), - pool(pool_name), - object(object), - nspace(nspace) {} - -OSDMapRequest::OSDMapRequest(std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void OSDMapRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("pool", pool, obj); - JSONDecoder::decode_json("object", object, obj); - JSONDecoder::decode_json("nspace", nspace, obj); - JSONDecoder::decode_json("format", format, obj); -} - -void OSDMapRequest::dump() const { - formatter->open_object_section("OSDMapRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("pool", pool, formatter.get()); - ::encode_json("object", object, formatter.get()); - ::encode_json("nspace", nspace, formatter.get()); - ::encode_json("format", format, formatter.get()); - formatter->close_section(); -} - -OSDMapReply::OSDMapReply(std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void OSDMapReply::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("epoch", epoch, obj); - JSONDecoder::decode_json("pool", pool, obj); - JSONDecoder::decode_json("pool_id", pool_id, obj); - JSONDecoder::decode_json("objname", objname, obj); - JSONDecoder::decode_json("raw_pgid", raw_pgid, obj); - JSONDecoder::decode_json("pgid", pgid, obj); - JSONDecoder::decode_json("up", up, obj); - JSONDecoder::decode_json("up_primary", up_primary, obj); - JSONDecoder::decode_json("acting", acting, obj); - JSONDecoder::decode_json("acting_primary", acting_primary, obj); -} - -void OSDMapReply::dump() const { - formatter->open_object_section("OSDMapReply"); - ::encode_json("epoch", epoch, formatter.get()); - ::encode_json("pool", pool, formatter.get()); - ::encode_json("pool_id", pool_id, formatter.get()); - ::encode_json("objname", objname, formatter.get()); - ::encode_json("raw_pgid", raw_pgid, formatter.get()); - ::encode_json("pgid", pgid, formatter.get()); - ::encode_json("up", up, formatter.get()); - ::encode_json("up_primary", up_primary, formatter.get()); - ::encode_json("acting", acting, formatter.get()); - ::encode_json("acting_primary", acting_primary, formatter.get()); - formatter->close_section(); -} - -ceph::io_exerciser::json::OSDPoolGetRequest ::OSDPoolGetRequest( - const std::string& pool_name, std::shared_ptr formatter) - : JSONStructure(formatter), pool(pool_name) {} - -ceph::io_exerciser::json::OSDPoolGetRequest ::OSDPoolGetRequest( - JSONObj* obj, std::shared_ptr formatter) - : JSONStructure(formatter) { - ceph::io_exerciser::json::OSDPoolGetRequest::decode_json(obj); -} - -void ceph::io_exerciser::json::OSDPoolGetRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("pool", pool, obj); - JSONDecoder::decode_json("var", var, obj); - JSONDecoder::decode_json("format", format, obj); -} - -void ceph::io_exerciser::json::OSDPoolGetRequest::dump() const { - formatter->open_object_section("OSDPoolGetRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("pool", pool, formatter.get()); - ::encode_json("var", var, formatter.get()); - ::encode_json("format", format, formatter.get()); - formatter->close_section(); -} - -ceph::io_exerciser::json::OSDPoolGetReply ::OSDPoolGetReply( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void ceph::io_exerciser::json::OSDPoolGetReply::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("erasure_code_profile", erasure_code_profile, obj); -} - -void ceph::io_exerciser::json::OSDPoolGetReply::dump() const { - formatter->open_object_section("OSDPoolGetReply"); - ::encode_json("erasure_code_profile", erasure_code_profile, formatter.get()); - formatter->close_section(); -} - -ceph::io_exerciser::json::OSDECProfileGetRequest ::OSDECProfileGetRequest( - const std::string& profile_name, std::shared_ptr formatter) - : JSONStructure(formatter), name(profile_name) {} - -ceph::io_exerciser::json::OSDECProfileGetRequest ::OSDECProfileGetRequest( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void ceph::io_exerciser::json::OSDECProfileGetRequest::decode_json( - JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("name", name, obj); - JSONDecoder::decode_json("format", format, obj); -} - -void ceph::io_exerciser::json::OSDECProfileGetRequest::dump() const { - formatter->open_object_section("OSDECProfileGetRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("name", name, formatter.get()); - ::encode_json("format", format, formatter.get()); - formatter->close_section(); -} - -ceph::io_exerciser::json::OSDECProfileGetReply ::OSDECProfileGetReply( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void ceph::io_exerciser::json::OSDECProfileGetReply::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("crush-device-class", crush_device_class, obj); - JSONDecoder::decode_json("crush-failure-domain", crush_failure_domain, obj); - JSONDecoder::decode_json("crush-num-failure-domains", - crush_num_failure_domains, obj); - JSONDecoder::decode_json("crush-osds-per-failure-domain", - crush_osds_per_failure_domain, obj); - JSONDecoder::decode_json("crush-root", crush_root, obj); - JSONDecoder::decode_json("jerasure-per-chunk-alignment", - jerasure_per_chunk_alignment, obj); - JSONDecoder::decode_json("k", k, obj); - JSONDecoder::decode_json("m", m, obj); - JSONDecoder::decode_json("plugin", plugin, obj); - JSONDecoder::decode_json("technique", technique, obj); - JSONDecoder::decode_json("w", w, obj); -} - -void ceph::io_exerciser::json::OSDECProfileGetReply::dump() const { - formatter->open_object_section("OSDECProfileGetReply"); - ::encode_json("crush-device-class", crush_device_class, formatter.get()); - ::encode_json("crush-failure-domain", crush_failure_domain, formatter.get()); - ::encode_json("crush-num-failure-domains", crush_num_failure_domains, - formatter.get()); - ::encode_json("crush-osds-per-failure-domain", crush_osds_per_failure_domain, - formatter.get()); - ::encode_json("crush-root", crush_root, formatter.get()); - ::encode_json("jerasure-per-chunk-alignment", jerasure_per_chunk_alignment, - formatter.get()); - ::encode_json("k", k, formatter.get()); - ::encode_json("m", m, formatter.get()); - ::encode_json("plugin", plugin, formatter.get()); - ::encode_json("technique", technique, formatter.get()); - ::encode_json("w", w, formatter.get()); - formatter->close_section(); -} - -ceph::io_exerciser::json::OSDECProfileSetRequest ::OSDECProfileSetRequest( - const std::string& name, const std::vector& profile, - std::shared_ptr formatter) - : JSONStructure(formatter), name(name), profile(profile) {} - -OSDECProfileSetRequest ::OSDECProfileSetRequest( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void OSDECProfileSetRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("name", name, obj); - JSONDecoder::decode_json("profile", profile, obj); -} - -void OSDECProfileSetRequest::dump() const { - formatter->open_object_section("OSDECProfileSetRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("name", name, formatter.get()); - ::encode_json("profile", profile, formatter.get()); - formatter->close_section(); -} - -OSDECPoolCreateRequest::OSDECPoolCreateRequest( - const std::string& pool, const std::string& erasure_code_profile, - std::shared_ptr formatter) - : JSONStructure(formatter), - pool(pool), - erasure_code_profile(erasure_code_profile) {} - -OSDECPoolCreateRequest ::OSDECPoolCreateRequest( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void OSDECPoolCreateRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("pool", pool, obj); - JSONDecoder::decode_json("pool_type", pool_type, obj); - JSONDecoder::decode_json("pg_num", pg_num, obj); - JSONDecoder::decode_json("pgp_num", pgp_num, obj); - JSONDecoder::decode_json("erasure_code_profile", erasure_code_profile, obj); -} - -void OSDECPoolCreateRequest::dump() const { - formatter->open_object_section("OSDECPoolCreateRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("pool", pool, formatter.get()); - ::encode_json("pool_type", pool_type, formatter.get()); - ::encode_json("pg_num", pg_num, formatter.get()); - ::encode_json("pgp_num", pgp_num, formatter.get()); - ::encode_json("erasure_code_profile", erasure_code_profile, formatter.get()); - formatter->close_section(); -} - -OSDSetRequest::OSDSetRequest(const std::string& key, - const std::optional& yes_i_really_mean_it, - std::shared_ptr formatter) - : JSONStructure(formatter), - key(key), - yes_i_really_mean_it(yes_i_really_mean_it) {} - -OSDSetRequest::OSDSetRequest(std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void OSDSetRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("key", key, obj); - JSONDecoder::decode_json("yes_i_really_mean_it", yes_i_really_mean_it, obj); -} - -void OSDSetRequest::dump() const { - formatter->open_object_section("OSDSetRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("key", key, formatter.get()); - ::encode_json("yes_i_really_mean_it", yes_i_really_mean_it, formatter.get()); - formatter->close_section(); -} - -BalancerOffRequest::BalancerOffRequest( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void ceph::io_exerciser::json::BalancerOffRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); -} - -void BalancerOffRequest::dump() const { - formatter->open_object_section("BalancerOffRequest"); - ::encode_json("prefix", prefix, formatter.get()); - formatter->close_section(); -} - -BalancerStatusRequest ::BalancerStatusRequest( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void ceph::io_exerciser::json::BalancerStatusRequest::decode_json( - JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); -} - -void BalancerStatusRequest::dump() const { - formatter->open_object_section("BalancerStatusRequest"); - ::encode_json("prefix", prefix, formatter.get()); - formatter->close_section(); -} - -BalancerStatusReply::BalancerStatusReply( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void BalancerStatusReply::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("active", active, obj); - JSONDecoder::decode_json("last_optimization_duration", - last_optimization_duration, obj); - JSONDecoder::decode_json("last_optimization_started", - last_optimization_started, obj); - JSONDecoder::decode_json("mode", mode, obj); - JSONDecoder::decode_json("no_optimization_needed", no_optimization_needed, - obj); - JSONDecoder::decode_json("optimize_result", optimize_result, obj); -} - -void BalancerStatusReply::dump() const { - formatter->open_object_section("BalancerStatusReply"); - ::encode_json("active", active, formatter.get()); - ::encode_json("last_optimization_duration", last_optimization_duration, - formatter.get()); - ::encode_json("last_optimization_started", last_optimization_started, - formatter.get()); - ::encode_json("mode", mode, formatter.get()); - ::encode_json("no_optimization_needed", no_optimization_needed, - formatter.get()); - ::encode_json("optimize_result", optimize_result, formatter.get()); - formatter->close_section(); -} - -ConfigSetRequest::ConfigSetRequest(const std::string& who, - const std::string& name, - const std::string& value, - const std::optional& force, - std::shared_ptr formatter) - : JSONStructure(formatter), - who(who), - name(name), - value(value), - force(force) {} - -ConfigSetRequest::ConfigSetRequest(std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void ConfigSetRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("who", who, obj); - JSONDecoder::decode_json("name", name, obj); - JSONDecoder::decode_json("value", value, obj); - JSONDecoder::decode_json("force", force, obj); -} - -void ConfigSetRequest::dump() const { - formatter->open_object_section("ConfigSetRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("who", who, formatter.get()); - ::encode_json("name", name, formatter.get()); - ::encode_json("value", value, formatter.get()); - ::encode_json("force", force, formatter.get()); - formatter->close_section(); -} - -InjectECErrorRequest::InjectECErrorRequest( - InjectOpType injectOpType, const std::string& pool, - const std::string& objname, int shardid, - const std::optional& type, const std::optional& when, - const std::optional& duration, - std::shared_ptr formatter) - : JSONStructure(formatter), - pool(pool), - objname(objname), - shardid(shardid), - type(type), - when(when), - duration(duration) { - switch (injectOpType) { - case InjectOpType::ReadEIO: - [[fallthrough]]; - case InjectOpType::ReadMissingShard: - prefix = "injectecreaderr"; - break; - case InjectOpType::WriteFailAndRollback: - [[fallthrough]]; - case InjectOpType::WriteOSDAbort: - prefix = "injectecwriteerr"; - break; - default: - ceph_abort_msg("Invalid OP type to inject"); - } -} - -InjectECErrorRequest ::InjectECErrorRequest( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void InjectECErrorRequest::dump() const { - formatter->open_object_section("InjectECErrorRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("pool", pool, formatter.get()); - ::encode_json("objname", objname, formatter.get()); - ::encode_json("shardid", shardid, formatter.get()); - ::encode_json("type", type, formatter.get()); - ::encode_json("when", when, formatter.get()); - ::encode_json("duration", duration, formatter.get()); - formatter->close_section(); -} - -void InjectECErrorRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("pool", pool, obj); - JSONDecoder::decode_json("objname", objname, obj); - JSONDecoder::decode_json("shardid", shardid, obj); - JSONDecoder::decode_json("type", type, obj); - JSONDecoder::decode_json("when", when, obj); - JSONDecoder::decode_json("duration", duration, obj); -} - -InjectECClearErrorRequest::InjectECClearErrorRequest( - InjectOpType injectOpType, const std::string& pool, - const std::string& objname, int shardid, - const std::optional& type, - std::shared_ptr formatter) - : JSONStructure(formatter), - pool(pool), - objname(objname), - shardid(shardid), - type(type) { - switch (injectOpType) { - case InjectOpType::ReadEIO: - [[fallthrough]]; - case InjectOpType::ReadMissingShard: - prefix = "injectecclearreaderr"; - break; - case InjectOpType::WriteFailAndRollback: - [[fallthrough]]; - case InjectOpType::WriteOSDAbort: - prefix = "injectecclearwriteerr"; - break; - default: - ceph_abort_msg("Invalid OP type to inject"); - } -} - -InjectECClearErrorRequest ::InjectECClearErrorRequest( - std::shared_ptr formatter) - : JSONStructure(formatter) {} - -void InjectECClearErrorRequest::dump() const { - formatter->open_object_section("InjectECErrorRequest"); - ::encode_json("prefix", prefix, formatter.get()); - ::encode_json("pool", pool, formatter.get()); - ::encode_json("objname", objname, formatter.get()); - ::encode_json("shardid", shardid, formatter.get()); - ::encode_json("type", type, formatter.get()); - formatter->close_section(); -} - -void InjectECClearErrorRequest::decode_json(JSONObj* obj) { - JSONDecoder::decode_json("prefix", prefix, obj); - JSONDecoder::decode_json("pool", pool, obj); - JSONDecoder::decode_json("objname", objname, obj); - JSONDecoder::decode_json("shardid", shardid, obj); - JSONDecoder::decode_json("type", type, obj); -} \ No newline at end of file diff --git a/src/common/io_exerciser/JsonStructures.h b/src/common/io_exerciser/JsonStructures.h deleted file mode 100644 index 995b9809146..00000000000 --- a/src/common/io_exerciser/JsonStructures.h +++ /dev/null @@ -1,302 +0,0 @@ -#include -#include -#include - -#include "OpType.h" -#include "include/types.h" - -/* Overview - * - * class JSONStructure - * Stores elements of a JSONStructure in C++ friendly format so they do not - * have to be parsed from strings. Includes encode and decode functions to - * provide easy ways to convert from c++ structures to json structures. - * - */ - -class JSONObj; - -namespace ceph { -namespace io_exerciser { -namespace json { -class JSONStructure { - public: - JSONStructure(std::shared_ptr formatter = - std::make_shared(false)); - - virtual ~JSONStructure() = default; - - std::string encode_json(); - virtual void decode_json(JSONObj* obj) = 0; - virtual void dump() const = 0; - - protected: - std::shared_ptr formatter; - - private: - std::ostringstream oss; -}; - -class OSDMapRequest : public JSONStructure { - public: - OSDMapRequest(const std::string& pool_name, const std::string& object, - const std::string& nspace, - std::shared_ptr formatter = - std::make_shared(false)); - OSDMapRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "osd map"; - std::string pool; - std::string object; - std::string nspace; - std::string format = "json"; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class OSDMapReply : public JSONStructure { - public: - OSDMapReply(std::shared_ptr formatter = - std::make_shared(false)); - - epoch_t epoch; - std::string pool; - uint64_t pool_id; - std::string objname; - std::string raw_pgid; - std::string pgid; - std::vector up; - int up_primary; - std::vector acting; - int acting_primary; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class OSDPoolGetRequest : public JSONStructure { - public: - OSDPoolGetRequest(const std::string& pool_name, - std::shared_ptr formatter = - std::make_shared(false)); - OSDPoolGetRequest(JSONObj* obj, std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "osd pool get"; - std::string pool; - std::string var = "erasure_code_profile"; - std::string format = "json"; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class OSDPoolGetReply : public JSONStructure { - public: - OSDPoolGetReply(std::shared_ptr formatter = - std::make_shared(false)); - - std::string erasure_code_profile; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class OSDECProfileGetRequest : public JSONStructure { - public: - OSDECProfileGetRequest(const std::string& profile_name, - std::shared_ptr formatter = - std::make_shared(false)); - OSDECProfileGetRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "osd pool get"; - std::string name; - std::string format = "json"; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class OSDECProfileGetReply : public JSONStructure { - public: - OSDECProfileGetReply(std::shared_ptr formatter = - std::make_shared(false)); - - std::string crush_device_class; - std::string crush_failure_domain; - int crush_num_failure_domains; - int crush_osds_per_failure_domain; - std::string crush_root; - bool jerasure_per_chunk_alignment; - int k; - int m; - std::string plugin; - std::string technique; - std::string w; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class OSDECProfileSetRequest : public JSONStructure { - public: - OSDECProfileSetRequest(const std::string& name, - const std::vector& profile, - std::shared_ptr formatter = - std::make_shared(false)); - OSDECProfileSetRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "osd erasure-code-profile set"; - std::string name; - std::vector profile; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class OSDECPoolCreateRequest : public JSONStructure { - public: - OSDECPoolCreateRequest(const std::string& pool, - const std::string& erasure_code_profile, - std::shared_ptr formatter = - std::make_shared(false)); - OSDECPoolCreateRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "osd pool create"; - std::string pool; - std::string pool_type = "erasure"; - int pg_num = 8; - int pgp_num = 8; - std::string erasure_code_profile; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class OSDSetRequest : public JSONStructure { - public: - OSDSetRequest(const std::string& key, - const std::optional& yes_i_really_mean_it = std::nullopt, - std::shared_ptr formatter = - std::make_shared(false)); - OSDSetRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "osd set"; - std::string key; - std::optional yes_i_really_mean_it = std::nullopt; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class BalancerOffRequest : public JSONStructure { - public: - BalancerOffRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "balancer off"; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class BalancerStatusRequest : public JSONStructure { - public: - BalancerStatusRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "balancer status"; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class BalancerStatusReply : public JSONStructure { - public: - BalancerStatusReply(std::shared_ptr formatter = - std::make_shared(false)); - - bool active; - std::string last_optimization_duration; - std::string last_optimization_started; - std::string mode; - bool no_optimization_needed; - std::string optimize_result; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class ConfigSetRequest : public JSONStructure { - public: - ConfigSetRequest(const std::string& who, const std::string& name, - const std::string& value, - const std::optional& force = std::nullopt, - std::shared_ptr formatter = - std::make_shared(false)); - ConfigSetRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix = "config set"; - std::string who; - std::string name; - std::string value; - std::optional force; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class InjectECErrorRequest : public JSONStructure { - public: - InjectECErrorRequest(InjectOpType injectOpType, const std::string& pool, - const std::string& objname, int shardid, - const std::optional& type, - const std::optional& when, - const std::optional& duration, - std::shared_ptr formatter = - std::make_shared(false)); - InjectECErrorRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix; - std::string pool; - std::string objname; - int shardid; - std::optional type; - std::optional when; - std::optional duration; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; - -class InjectECClearErrorRequest : public JSONStructure { - public: - InjectECClearErrorRequest(InjectOpType injectOpType, const std::string& pool, - const std::string& objname, int shardid, - const std::optional& type, - std::shared_ptr formatter = - std::make_shared(false)); - - InjectECClearErrorRequest(std::shared_ptr formatter = - std::make_shared(false)); - - std::string prefix; - std::string pool; - std::string objname; - int shardid; - std::optional type; - - void decode_json(JSONObj* obj) override; - void dump() const override; -}; -} // namespace json -} // namespace io_exerciser -} // namespace ceph \ No newline at end of file diff --git a/src/common/io_exerciser/RadosIo.cc b/src/common/io_exerciser/RadosIo.cc index 048622ccde0..4451900b7bb 100644 --- a/src/common/io_exerciser/RadosIo.cc +++ b/src/common/io_exerciser/RadosIo.cc @@ -6,8 +6,8 @@ #include #include "DataGenerator.h" -#include "JsonStructures.h" #include "common/ceph_json.h" +#include "common/json/OSDStructures.h" using RadosIo = ceph::io_exerciser::RadosIo; @@ -292,47 +292,51 @@ void RadosIo::applyReadWriteOp(IoOp& op) { void RadosIo::applyInjectOp(IoOp& op) { bufferlist osdmap_inbl, inject_inbl, osdmap_outbl, inject_outbl; - auto formatter = std::make_shared(false); + auto formatter = std::make_unique(false); + std::ostringstream oss; int osd = -1; std::vector shard_order; - ceph::io_exerciser::json::OSDMapRequest osdMapRequest(pool, get_oid(), "", - formatter); - int rc = rados.mon_command(osdMapRequest.encode_json(), osdmap_inbl, - &osdmap_outbl, nullptr); + ceph::messaging::osd::OSDMapRequest osdMapRequest{pool, get_oid(), ""}; + encode_json("OSDMapRequest", osdMapRequest, formatter.get()); + formatter->flush(oss); + int rc = rados.mon_command(oss.str(), osdmap_inbl, &osdmap_outbl, nullptr); ceph_assert(rc == 0); JSONParser p; bool success = p.parse(osdmap_outbl.c_str(), osdmap_outbl.length()); ceph_assert(success); - ceph::io_exerciser::json::OSDMapReply reply{formatter}; + ceph::messaging::osd::OSDMapReply reply; reply.decode_json(&p); osd = reply.acting_primary; shard_order = reply.acting; - InjectOpType injectOpType; - switch (op.getOpType()) { case OpType::InjectReadError: { InjectReadErrorOp& errorOp = static_cast(op); if (errorOp.type == 0) { - injectOpType = InjectOpType::ReadEIO; + ceph::messaging::osd::InjectECErrorRequest + injectErrorRequest{pool, oid, errorOp.shard, + errorOp.type, errorOp.when, errorOp.duration}; + encode_json("InjectECErrorRequest", injectErrorRequest, + formatter.get()); } else if (errorOp.type == 1) { - injectOpType = InjectOpType::ReadMissingShard; + ceph::messaging::osd::InjectECErrorRequest< + InjectOpType::ReadMissingShard> + injectErrorRequest{pool, oid, errorOp.shard, + errorOp.type, errorOp.when, errorOp.duration}; + encode_json("InjectECErrorRequest", injectErrorRequest, + formatter.get()); } else { ceph_abort_msg("Unsupported inject type"); } - - ceph::io_exerciser::json::InjectECErrorRequest injectErrorRequest( - injectOpType, pool, oid, errorOp.shard, errorOp.type, errorOp.when, - errorOp.duration, formatter); - - int rc = rados.osd_command(osd, injectErrorRequest.encode_json(), - inject_inbl, &inject_outbl, nullptr); + formatter->flush(oss); + int rc = rados.osd_command(osd, oss.str(), inject_inbl, &inject_outbl, + nullptr); ceph_assert(rc == 0); break; } @@ -340,9 +344,18 @@ void RadosIo::applyInjectOp(IoOp& op) { InjectWriteErrorOp& errorOp = static_cast(op); if (errorOp.type == 0) { - injectOpType = InjectOpType::WriteFailAndRollback; + ceph::messaging::osd::InjectECErrorRequest< + InjectOpType::WriteFailAndRollback> + injectErrorRequest{pool, oid, errorOp.shard, + errorOp.type, errorOp.when, errorOp.duration}; + encode_json("InjectECErrorRequest", injectErrorRequest, + formatter.get()); } else if (errorOp.type == 3) { - injectOpType = InjectOpType::WriteOSDAbort; + ceph::messaging::osd::InjectECErrorRequest + injectErrorRequest{pool, oid, errorOp.shard, + errorOp.type, errorOp.when, errorOp.duration}; + encode_json("InjectECErrorRequest", injectErrorRequest, + formatter.get()); // This inject is sent directly to the shard we want to inject the error // on @@ -351,12 +364,9 @@ void RadosIo::applyInjectOp(IoOp& op) { ceph_abort("Unsupported inject type"); } - ceph::io_exerciser::json::InjectECErrorRequest injectErrorRequest( - injectOpType, pool, oid, errorOp.shard, errorOp.type, errorOp.when, - errorOp.duration, formatter); - - int rc = rados.osd_command(osd, injectErrorRequest.encode_json(), - inject_inbl, &inject_outbl, nullptr); + formatter->flush(oss); + int rc = rados.osd_command(osd, oss.str(), inject_inbl, &inject_outbl, + nullptr); ceph_assert(rc == 0); break; } @@ -365,18 +375,23 @@ void RadosIo::applyInjectOp(IoOp& op) { static_cast(op); if (errorOp.type == 0) { - injectOpType = InjectOpType::ReadEIO; + ceph::messaging::osd::InjectECClearErrorRequest + clearErrorInject{pool, oid, errorOp.shard, errorOp.type}; + encode_json("InjectECClearErrorRequest", clearErrorInject, + formatter.get()); } else if (errorOp.type == 1) { - injectOpType = InjectOpType::ReadMissingShard; + ceph::messaging::osd::InjectECClearErrorRequest< + InjectOpType::ReadMissingShard> + clearErrorInject{pool, oid, errorOp.shard, errorOp.type}; + encode_json("InjectECClearErrorRequest", clearErrorInject, + formatter.get()); } else { ceph_abort("Unsupported inject type"); } - ceph::io_exerciser::json::InjectECClearErrorRequest clearErrorInject( - injectOpType, pool, oid, errorOp.shard, errorOp.type); - - int rc = rados.osd_command(osd, clearErrorInject.encode_json(), - inject_inbl, &inject_outbl, nullptr); + formatter->flush(oss); + int rc = rados.osd_command(osd, oss.str(), inject_inbl, &inject_outbl, + nullptr); ceph_assert(rc == 0); break; } @@ -385,18 +400,24 @@ void RadosIo::applyInjectOp(IoOp& op) { static_cast(op); if (errorOp.type == 0) { - injectOpType = InjectOpType::WriteFailAndRollback; + ceph::messaging::osd::InjectECClearErrorRequest< + InjectOpType::WriteFailAndRollback> + clearErrorInject{pool, oid, errorOp.shard, errorOp.type}; + encode_json("InjectECClearErrorRequest", clearErrorInject, + formatter.get()); } else if (errorOp.type == 3) { - injectOpType = InjectOpType::WriteOSDAbort; + ceph::messaging::osd::InjectECClearErrorRequest< + InjectOpType::WriteOSDAbort> + clearErrorInject{pool, oid, errorOp.shard, errorOp.type}; + encode_json("InjectECClearErrorRequest", clearErrorInject, + formatter.get()); } else { ceph_abort("Unsupported inject type"); } - ceph::io_exerciser::json::InjectECClearErrorRequest clearErrorInject( - injectOpType, pool, oid, errorOp.shard, errorOp.type); - - int rc = rados.osd_command(osd, clearErrorInject.encode_json(), - inject_inbl, &inject_outbl, nullptr); + formatter->flush(oss); + int rc = rados.osd_command(osd, oss.str(), inject_inbl, &inject_outbl, + nullptr); ceph_assert(rc == 0); break; } diff --git a/src/common/json/BalancerStructures.cc b/src/common/json/BalancerStructures.cc new file mode 100644 index 00000000000..48dfb843761 --- /dev/null +++ b/src/common/json/BalancerStructures.cc @@ -0,0 +1,38 @@ +#include "BalancerStructures.h" + +#include "common/ceph_json.h" + +using namespace ceph::messaging::balancer; + +void BalancerOffRequest::dump(Formatter* f) const { + encode_json("prefix", "balancer off", f); +} + +void BalancerOffRequest::decode_json(JSONObj* obj) {} + +void BalancerStatusRequest::dump(Formatter* f) const { + encode_json("prefix", "balancer status", f); +} + +void BalancerStatusRequest::decode_json(JSONObj* obj) {} + +void BalancerStatusReply::dump(Formatter* f) const { + encode_json("active", active, f); + encode_json("last_optimization_duration", last_optimization_duration, f); + encode_json("last_optimization_started", last_optimization_started, f); + encode_json("mode", mode, f); + encode_json("no_optimization_needed", no_optimization_needed, f); + encode_json("optimize_result", optimize_result, f); +} + +void BalancerStatusReply::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("active", active, obj); + JSONDecoder::decode_json("last_optimization_duration", + last_optimization_duration, obj); + JSONDecoder::decode_json("last_optimization_started", + last_optimization_started, obj); + JSONDecoder::decode_json("mode", mode, obj); + JSONDecoder::decode_json("no_optimization_needed", no_optimization_needed, + obj); + JSONDecoder::decode_json("optimize_result", optimize_result, obj); +} \ No newline at end of file diff --git a/src/common/json/BalancerStructures.h b/src/common/json/BalancerStructures.h new file mode 100644 index 00000000000..bbf5c748eb3 --- /dev/null +++ b/src/common/json/BalancerStructures.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include "include/types.h" + +class JSONObj; + +namespace ceph { +namespace messaging { +namespace balancer { +struct BalancerOffRequest { + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct BalancerStatusRequest { + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct BalancerStatusReply { + bool active; + std::string last_optimization_duration; + std::string last_optimization_started; + std::string mode; + bool no_optimization_needed; + std::string optimize_result; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; +} // namespace balancer +} // namespace messaging +} // namespace ceph \ No newline at end of file diff --git a/src/common/json/CMakeLists.txt b/src/common/json/CMakeLists.txt new file mode 100644 index 00000000000..1497daf93db --- /dev/null +++ b/src/common/json/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(json_structures STATIC + BalancerStructures.cc ConfigStructures.cc OSDStructures.cc) + + target_link_libraries(json_structures global) \ No newline at end of file diff --git a/src/common/json/ConfigStructures.cc b/src/common/json/ConfigStructures.cc new file mode 100644 index 00000000000..651278d002a --- /dev/null +++ b/src/common/json/ConfigStructures.cc @@ -0,0 +1,20 @@ +#include "ConfigStructures.h" + +#include "common/ceph_json.h" + +using namespace ceph::messaging::config; + +void ConfigSetRequest::dump(Formatter* f) const { + encode_json("prefix", "config set", f); + encode_json("who", who, f); + encode_json("name", name, f); + encode_json("value", value, f); + encode_json("force", force, f); +} + +void ConfigSetRequest::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("who", who, obj); + JSONDecoder::decode_json("name", name, obj); + JSONDecoder::decode_json("value", value, obj); + JSONDecoder::decode_json("force", force, obj); +} \ No newline at end of file diff --git a/src/common/json/ConfigStructures.h b/src/common/json/ConfigStructures.h new file mode 100644 index 00000000000..554229d75f4 --- /dev/null +++ b/src/common/json/ConfigStructures.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include "include/types.h" + +class JSONObj; + +namespace ceph { +namespace messaging { +namespace config { +struct ConfigSetRequest { + std::string who; + std::string name; + std::string value; + std::optional force; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; +} // namespace config +} // namespace messaging +} // namespace ceph \ No newline at end of file diff --git a/src/common/json/OSDStructures.cc b/src/common/json/OSDStructures.cc new file mode 100644 index 00000000000..aaac5f6e169 --- /dev/null +++ b/src/common/json/OSDStructures.cc @@ -0,0 +1,150 @@ +#include "OSDStructures.h" + +#include "common/ceph_json.h" +#include "common/io_exerciser/OpType.h" + +using namespace ceph::messaging::osd; + +void OSDMapRequest::dump(Formatter* f) const { + encode_json("prefix", "osd map", f); + encode_json("pool", pool, f); + encode_json("object", object, f); + encode_json("nspace", nspace, f); + encode_json("format", format, f); +} + +void OSDMapRequest::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("pool", pool, obj); + JSONDecoder::decode_json("object", object, obj); + JSONDecoder::decode_json("nspace", nspace, obj); + JSONDecoder::decode_json("format", format, obj); +} + +void OSDMapReply::dump(Formatter* f) const { + encode_json("epoch", epoch, f); + encode_json("pool", pool, f); + encode_json("pool_id", pool_id, f); + encode_json("objname", objname, f); + encode_json("raw_pgid", raw_pgid, f); + encode_json("pgid", pgid, f); + encode_json("up", up, f); + encode_json("up_primary", up_primary, f); + encode_json("acting", acting, f); + encode_json("acting_primary", acting_primary, f); +} + +void OSDMapReply::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("epoch", epoch, obj); + JSONDecoder::decode_json("pool", pool, obj); + JSONDecoder::decode_json("pool_id", pool_id, obj); + JSONDecoder::decode_json("objname", objname, obj); + JSONDecoder::decode_json("raw_pgid", raw_pgid, obj); + JSONDecoder::decode_json("pgid", pgid, obj); + JSONDecoder::decode_json("up", up, obj); + JSONDecoder::decode_json("up_primary", up_primary, obj); + JSONDecoder::decode_json("acting", acting, obj); + JSONDecoder::decode_json("acting_primary", acting_primary, obj); +} + +void OSDPoolGetRequest::dump(Formatter* f) const { + encode_json("prefix", "osd pool get", f); + encode_json("pool", pool, f); + encode_json("var", var, f); + encode_json("format", format, f); +} + +void OSDPoolGetRequest::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("pool", pool, obj); + JSONDecoder::decode_json("var", var, obj); + JSONDecoder::decode_json("format", format, obj); +} + +void OSDPoolGetReply::dump(Formatter* f) const { + encode_json("erasure_code_profile", erasure_code_profile, f); +} + +void OSDPoolGetReply::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("erasure_code_profile", erasure_code_profile, obj); +} + +void OSDECProfileGetRequest::dump(Formatter* f) const { + encode_json("prefix", "osd pool get", f); + encode_json("name", name, f); + encode_json("format", format, f); +} + +void OSDECProfileGetRequest::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("name", name, obj); + JSONDecoder::decode_json("format", format, obj); +} + +void OSDECProfileGetReply::dump(Formatter* f) const { + encode_json("crush-device-class", crush_device_class, f); + encode_json("crush-failure-domain", crush_failure_domain, f); + encode_json("crush-num-failure-domains", crush_num_failure_domains, f); + encode_json("crush-osds-per-failure-domain", crush_osds_per_failure_domain, + f); + encode_json("crush-root", crush_root, f); + encode_json("jerasure-per-chunk-alignment", jerasure_per_chunk_alignment, f); + encode_json("k", k, f); + encode_json("m", m, f); + encode_json("plugin", plugin, f); + encode_json("technique", technique, f); + encode_json("w", w, f); +} + +void OSDECProfileGetReply::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("crush-device-class", crush_device_class, obj); + JSONDecoder::decode_json("crush-failure-domain", crush_failure_domain, obj); + JSONDecoder::decode_json("crush-num-failure-domains", + crush_num_failure_domains, obj); + JSONDecoder::decode_json("crush-osds-per-failure-domain", + crush_osds_per_failure_domain, obj); + JSONDecoder::decode_json("crush-root", crush_root, obj); + JSONDecoder::decode_json("jerasure-per-chunk-alignment", + jerasure_per_chunk_alignment, obj); + JSONDecoder::decode_json("k", k, obj); + JSONDecoder::decode_json("m", m, obj); + JSONDecoder::decode_json("plugin", plugin, obj); + JSONDecoder::decode_json("technique", technique, obj); + JSONDecoder::decode_json("w", w, obj); +} + +void OSDECProfileSetRequest::dump(Formatter* f) const { + encode_json("prefix", "osd erasure-code-profile set", f); + encode_json("name", name, f); + encode_json("profile", profile, f); +} + +void OSDECProfileSetRequest::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("name", name, obj); + JSONDecoder::decode_json("profile", profile, obj); +} + +void OSDECPoolCreateRequest::dump(Formatter* f) const { + encode_json("prefix", "osd pool create", f); + encode_json("pool", pool, f); + encode_json("pool_type", pool_type, f); + encode_json("pg_num", pg_num, f); + encode_json("pgp_num", pgp_num, f); + encode_json("erasure_code_profile", erasure_code_profile, f); +} + +void OSDECPoolCreateRequest::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("pool", pool, obj); + JSONDecoder::decode_json("pool_type", pool_type, obj); + JSONDecoder::decode_json("pg_num", pg_num, obj); + JSONDecoder::decode_json("pgp_num", pgp_num, obj); + JSONDecoder::decode_json("erasure_code_profile", erasure_code_profile, obj); +} + +void OSDSetRequest::dump(Formatter* f) const { + encode_json("prefix", "osd set", f); + encode_json("key", key, f); + encode_json("yes_i_really_mean_it", yes_i_really_mean_it, f); +} + +void OSDSetRequest::decode_json(JSONObj* obj) { + JSONDecoder::decode_json("key", key, obj); + JSONDecoder::decode_json("yes_i_really_mean_it", yes_i_really_mean_it, obj); +} \ No newline at end of file diff --git a/src/common/json/OSDStructures.h b/src/common/json/OSDStructures.h new file mode 100644 index 00000000000..3e4528a099f --- /dev/null +++ b/src/common/json/OSDStructures.h @@ -0,0 +1,189 @@ +#pragma once + +#include +#include +#include + +#include "common/ceph_json.h" +#include "common/io_exerciser/OpType.h" +#include "include/types.h" + +class JSONObj; + +namespace ceph { +namespace messaging { +namespace osd { +struct OSDMapRequest { + std::string pool; + std::string object; + std::string nspace; + std::string format = "json"; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct OSDMapReply { + epoch_t epoch; + std::string pool; + uint64_t pool_id; + std::string objname; + std::string raw_pgid; + std::string pgid; + std::vector up; + int up_primary; + std::vector acting; + int acting_primary; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct OSDPoolGetRequest { + std::string pool; + std::string var = "erasure_code_profile"; + std::string format = "json"; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct OSDPoolGetReply { + std::string erasure_code_profile; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct OSDECProfileGetRequest { + std::string name; + std::string format = "json"; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct OSDECProfileGetReply { + std::string crush_device_class; + std::string crush_failure_domain; + int crush_num_failure_domains; + int crush_osds_per_failure_domain; + std::string crush_root; + bool jerasure_per_chunk_alignment; + int k; + int m; + std::string plugin; + std::string technique; + std::string w; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct OSDECProfileSetRequest { + std::string name; + std::vector profile; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct OSDECPoolCreateRequest { + std::string pool; + std::string pool_type; + int pg_num; + int pgp_num; + std::string erasure_code_profile; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +struct OSDSetRequest { + std::string key; + std::optional yes_i_really_mean_it = std::nullopt; + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); +}; + +// These structures are sent directly to the relevant OSD +// rather than the monitor +template +struct InjectECErrorRequest { + std::string pool; + std::string objname; + int shardid; + std::optional type; + std::optional when; + std::optional duration; + + void dump(Formatter* f) const { + switch (op_type) { + case io_exerciser::InjectOpType::ReadEIO: + [[fallthrough]]; + case io_exerciser::InjectOpType::ReadMissingShard: + ::encode_json("prefix", "injectecreaderr", f); + break; + case io_exerciser::InjectOpType::WriteFailAndRollback: + [[fallthrough]]; + case io_exerciser::InjectOpType::WriteOSDAbort: + ::encode_json("prefix", "injectecwriteerr", f); + break; + default: + ceph_abort_msg("Unsupported Inject Type"); + } + ::encode_json("pool", pool, f); + ::encode_json("objname", objname, f); + ::encode_json("shardid", shardid, f); + ::encode_json("type", type, f); + ::encode_json("when", when, f); + ::encode_json("duration", duration, f); + } + void decode_json(JSONObj* obj) { + JSONDecoder::decode_json("pool", pool, obj); + JSONDecoder::decode_json("objname", objname, obj); + JSONDecoder::decode_json("shardid", shardid, obj); + JSONDecoder::decode_json("type", type, obj); + JSONDecoder::decode_json("when", when, obj); + JSONDecoder::decode_json("duration", duration, obj); + } +}; + +template +struct InjectECClearErrorRequest { + std::string pool; + std::string objname; + int shardid; + std::optional type; + + void dump(Formatter* f) const { + switch (op_type) { + case io_exerciser::InjectOpType::ReadEIO: + [[fallthrough]]; + case io_exerciser::InjectOpType::ReadMissingShard: + ::encode_json("prefix", "injectecclearreaderr", f); + break; + case io_exerciser::InjectOpType::WriteFailAndRollback: + [[fallthrough]]; + case io_exerciser::InjectOpType::WriteOSDAbort: + ::encode_json("prefix", "injectecclearwriteerr", f); + break; + default: + ceph_abort_msg("Unsupported Inject Type"); + } + ::encode_json("pool", pool, f); + ::encode_json("objname", objname, f); + ::encode_json("shardid", shardid, f); + ::encode_json("type", type, f); + } + void decode_json(JSONObj* obj) { + JSONDecoder::decode_json("pool", pool, obj); + JSONDecoder::decode_json("objname", objname, obj); + JSONDecoder::decode_json("shardid", shardid, obj); + JSONDecoder::decode_json("type", type, obj); + } +}; +} // namespace osd +} // namespace messaging +} // namespace ceph \ No newline at end of file diff --git a/src/test/osd/CMakeLists.txt b/src/test/osd/CMakeLists.txt index f2d1471e22e..798558ebbe0 100644 --- a/src/test/osd/CMakeLists.txt +++ b/src/test/osd/CMakeLists.txt @@ -22,7 +22,7 @@ install(TARGETS add_executable(ceph_test_rados_io_sequence ${CMAKE_CURRENT_SOURCE_DIR}/ceph_test_rados_io_sequence.cc) target_link_libraries(ceph_test_rados_io_sequence - librados global object_io_exerciser) + librados global object_io_exerciser json_structures) install(TARGETS ceph_test_rados_io_sequence DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/src/test/osd/ceph_test_rados_io_sequence.cc b/src/test/osd/ceph_test_rados_io_sequence.cc index da2218a47c2..1dd1e61643d 100644 --- a/src/test/osd/ceph_test_rados_io_sequence.cc +++ b/src/test/osd/ceph_test_rados_io_sequence.cc @@ -19,10 +19,12 @@ #include "common/io_exerciser/EcIoSequence.h" #include "common/io_exerciser/IoOp.h" #include "common/io_exerciser/IoSequence.h" -#include "common/io_exerciser/JsonStructures.h" #include "common/io_exerciser/Model.h" #include "common/io_exerciser/ObjectModel.h" #include "common/io_exerciser/RadosIo.h" +#include "common/json/BalancerStructures.h" +#include "common/json/ConfigStructures.h" +#include "common/json/OSDStructures.h" #include "fmt/format.h" #include "global/global_context.h" #include "global/global_init.h" @@ -212,6 +214,17 @@ int parse_io_seq_options(po::variables_map& vm, int argc, char** argv) { return 0; } + +template +int send_mon_command(S& s, librados::Rados& rados, const char* name, + ceph::buffer::list& inbl, ceph::buffer::list* outbl, Formatter* f) { + std::ostringstream oss; + encode_json(name, s, f); + f->flush(oss); + int rc = rados.mon_command(oss.str(), inbl, outbl, nullptr); + return rc; +} + } // namespace template & Ts> @@ -301,7 +314,7 @@ ceph::io_sequence::tester::SelectECPool::SelectECPool( ceph::util::random_number_generator& rng, po::variables_map vm, librados::Rados& rados, bool dry_run, bool allow_pool_autoscaling, bool allow_pool_balancer, bool allow_pool_deep_scrubbing, - bool allow_pool_scrubbing) + bool allow_pool_scrubbing, bool test_recovery) : ProgramOptionSelector(rng, vm, "pool", false, false), rados(rados), dry_run(dry_run), @@ -309,6 +322,7 @@ ceph::io_sequence::tester::SelectECPool::SelectECPool( allow_pool_balancer(allow_pool_balancer), allow_pool_deep_scrubbing(allow_pool_deep_scrubbing), allow_pool_scrubbing(allow_pool_scrubbing), + test_recovery(test_recovery), skm(SelectErasureKM(rng, vm)), spl(SelectErasurePlugin(rng, vm)), scs(SelectErasureChunkSize(rng, vm)) { @@ -324,31 +338,31 @@ const std::string ceph::io_sequence::tester::SelectECPool::choose() { if (!skm.isForced() && force_value.has_value()) { int rc; bufferlist inbl, outbl; - auto formatter = std::make_shared(false); + auto formatter = std::make_unique(false); - ceph::io_exerciser::json::OSDPoolGetRequest osdPoolGetRequest(*force_value, - formatter); - rc = rados.mon_command(osdPoolGetRequest.encode_json(), inbl, &outbl, - nullptr); + ceph::messaging::osd::OSDPoolGetRequest osdPoolGetRequest{*force_value}; + rc = send_mon_command(osdPoolGetRequest, rados, "OSDPoolGetRequest", inbl, + &outbl, formatter.get()); ceph_assert(rc == 0); JSONParser p; bool success = p.parse(outbl.c_str(), outbl.length()); ceph_assert(success); - ceph::io_exerciser::json::OSDPoolGetReply osdPoolGetReply(formatter); + ceph::messaging::osd::OSDPoolGetReply osdPoolGetReply; osdPoolGetReply.decode_json(&p); - ceph::io_exerciser::json::OSDECProfileGetRequest osdECProfileGetRequest( - osdPoolGetReply.erasure_code_profile, formatter); - rc = rados.mon_command(osdECProfileGetRequest.encode_json(), inbl, &outbl, - nullptr); + ceph::messaging::osd::OSDECProfileGetRequest osdECProfileGetRequest{ + osdPoolGetReply.erasure_code_profile}; + rc = send_mon_command(osdECProfileGetRequest, rados, + "OSDECProfileGetRequest", inbl, &outbl, + formatter.get()); ceph_assert(rc == 0); success = p.parse(outbl.c_str(), outbl.length()); ceph_assert(success); - ceph::io_exerciser::json::OSDECProfileGetReply reply(formatter); + ceph::messaging::osd::OSDECProfileGetReply reply; reply.decode_json(&p); k = reply.k; m = reply.m; @@ -375,81 +389,82 @@ void ceph::io_sequence::tester::SelectECPool::create_pool( const std::string& plugin, uint64_t chunk_size, int k, int m) { int rc; bufferlist inbl, outbl; - auto formatter = std::make_shared(false); + auto formatter = std::make_unique(false); - ceph::io_exerciser::json::OSDECProfileSetRequest ecProfileSetRequest( + ceph::messaging::osd::OSDECProfileSetRequest ecProfileSetRequest{ fmt::format("testprofile-{}", pool_name), {fmt::format("plugin={}", plugin), fmt::format("k={}", k), fmt::format("m={}", m), fmt::format("stripe_unit={}", chunk_size), - fmt::format("crush-failure-domain=osd")}, - formatter); - rc = rados.mon_command(ecProfileSetRequest.encode_json(), inbl, &outbl, - nullptr); + fmt::format("crush-failure-domain=osd")}}; + rc = send_mon_command(ecProfileSetRequest, rados, "OSDECProfileSetRequest", + inbl, &outbl, formatter.get()); ceph_assert(rc == 0); - ceph::io_exerciser::json::OSDECPoolCreateRequest poolCreateRequest( - pool_name, fmt::format("testprofile-{}", pool_name), formatter); - rc = - rados.mon_command(poolCreateRequest.encode_json(), inbl, &outbl, nullptr); + ceph::messaging::osd::OSDECPoolCreateRequest poolCreateRequest{ + pool_name, "erasure", 8, 8, fmt::format("testprofile-{}", pool_name)}; + rc = send_mon_command(poolCreateRequest, rados, "OSDECPoolCreateRequest", + inbl, &outbl, formatter.get()); ceph_assert(rc == 0); if (allow_pool_autoscaling) { - ceph::io_exerciser::json::OSDSetRequest setNoAutoscaleRequest( - "noautoscale", std::nullopt, formatter); - rc = rados.mon_command(setNoAutoscaleRequest.encode_json(), inbl, &outbl, - nullptr); + ceph::messaging::osd::OSDSetRequest setNoAutoscaleRequest{"noautoscale", + std::nullopt}; + rc = send_mon_command(setNoAutoscaleRequest, rados, "OSDSetRequest", inbl, + &outbl, formatter.get()); ceph_assert(rc == 0); } if (allow_pool_balancer) { - ceph::io_exerciser::json::BalancerOffRequest balancerOffRequest(formatter); - rc = rados.mon_command(balancerOffRequest.encode_json(), inbl, &outbl, - nullptr); + ceph::messaging::balancer::BalancerOffRequest balancerOffRequest{}; + rc = send_mon_command(balancerOffRequest, rados, "BalancerOffRequest", inbl, + &outbl, formatter.get()); ceph_assert(rc == 0); - ceph::io_exerciser::json::BalancerStatusRequest balancerStatusRequest( - formatter); - rc = rados.mon_command(balancerStatusRequest.encode_json(), inbl, &outbl, - nullptr); + ceph::messaging::balancer::BalancerStatusRequest balancerStatusRequest{}; + rc = send_mon_command(balancerStatusRequest, rados, "BalancerStatusRequest", + inbl, &outbl, formatter.get()); ceph_assert(rc == 0); JSONParser p; bool success = p.parse(outbl.c_str(), outbl.length()); ceph_assert(success); - ceph::io_exerciser::json::BalancerStatusReply reply{formatter}; + ceph::messaging::balancer::BalancerStatusReply reply; reply.decode_json(&p); ceph_assert(!reply.active); } if (allow_pool_deep_scrubbing) { - ceph::io_exerciser::json::OSDSetRequest setNoDeepScrubRequest( - "nodeep-scrub", std::nullopt, formatter); - rc = rados.mon_command(setNoDeepScrubRequest.encode_json(), inbl, &outbl, - nullptr); + ceph::messaging::osd::OSDSetRequest setNoDeepScrubRequest{"nodeep-scrub", + std::nullopt}; + rc = send_mon_command(setNoDeepScrubRequest, rados, "setNoDeepScrubRequest", + inbl, &outbl, formatter.get()); ceph_assert(rc == 0); } if (allow_pool_scrubbing) { - ceph::io_exerciser::json::OSDSetRequest setNoScrubRequest( - "noscrub", std::nullopt, formatter); - rc = rados.mon_command(setNoScrubRequest.encode_json(), inbl, &outbl, - nullptr); + ceph::messaging::osd::OSDSetRequest setNoScrubRequest{"noscrub", + std::nullopt}; + rc = send_mon_command(setNoScrubRequest, rados, "OSDSetRequest", inbl, + &outbl, formatter.get()); ceph_assert(rc == 0); } - ceph::io_exerciser::json ::ConfigSetRequest configSetBluestoreDebugRequest( - "global", "bluestore_debug_inject_read_err", "true", std::nullopt, - formatter); - rc = rados.mon_command(configSetBluestoreDebugRequest.encode_json(), inbl, - &outbl, nullptr); - ceph_assert(rc == 0); + if (test_recovery) { + ceph::messaging::config::ConfigSetRequest configSetBluestoreDebugRequest{ + "global", "bluestore_debug_inject_read_err", "true", std::nullopt}; + rc = send_mon_command(configSetBluestoreDebugRequest, rados, + "ConfigSetRequest", inbl, &outbl, + formatter.get()); + ceph_assert(rc == 0); - ceph::io_exerciser::json ::ConfigSetRequest configSetMaxMarkdownRequest( - "global", "osd_max_markdown_count", "99999999", std::nullopt, formatter); - rc = rados.mon_command(configSetMaxMarkdownRequest.encode_json(), inbl, - &outbl, nullptr); - ceph_assert(rc == 0); + ceph::messaging::config::ConfigSetRequest configSetMaxMarkdownRequest{ + "global", "osd_max_markdown_count", "99999999", std::nullopt}; + rc = + send_mon_command(configSetMaxMarkdownRequest, rados, "ConfigSetRequest", + inbl, &outbl, formatter.get()); + ceph_assert(rc == 0); + } } ceph::io_sequence::tester::TestObject::TestObject( @@ -471,22 +486,23 @@ ceph::io_sequence::tester::TestObject::TestObject( int threads = snt.choose(); bufferlist inbl, outbl; + auto formatter = std::make_unique(false); std::optional> cached_shard_order = std::nullopt; if (!spo.get_allow_pool_autoscaling() && !spo.get_allow_pool_balancer() && !spo.get_allow_pool_deep_scrubbing() && !spo.get_allow_pool_scrubbing()) { - ceph::io_exerciser::json::OSDMapRequest osdMapRequest(pool, oid, ""); - int rc = - rados.mon_command(osdMapRequest.encode_json(), inbl, &outbl, nullptr); + ceph::messaging::osd::OSDMapRequest osdMapRequest{pool, oid, ""}; + int rc = send_mon_command(osdMapRequest, rados, "OSDMapRequest", inbl, + &outbl, formatter.get()); ceph_assert(rc == 0); JSONParser p; bool success = p.parse(outbl.c_str(), outbl.length()); ceph_assert(success); - ceph::io_exerciser::json::OSDMapReply reply{}; + ceph::messaging::osd::OSDMapReply reply{}; reply.decode_json(&p); cached_shard_order = reply.acting; } @@ -579,7 +595,8 @@ ceph::io_sequence::tester::TestRunner::TestRunner(po::variables_map& vm, vm.contains("allow_pool_autoscaling"), vm.contains("allow_pool_balancer"), vm.contains("allow_pool_deep_scrubbing"), - vm.contains("allow_pool_scrubbing")}, + vm.contains("allow_pool_scrubbing"), + vm.contains("test_recovery")}, snt{rng, vm}, ssr{rng, vm} { dout(0) << "Test using seed " << seed << dendl; @@ -721,18 +738,18 @@ bool ceph::io_sequence::tester::TestRunner::run_interactive_test() { const std::string pool = spo.choose(); bufferlist inbl, outbl; + auto formatter = std::make_unique(false); - ceph::io_exerciser::json::OSDMapRequest osdMapRequest(pool, object_name, - ""); - int rc = - rados.mon_command(osdMapRequest.encode_json(), inbl, &outbl, nullptr); + ceph::messaging::osd::OSDMapRequest osdMapRequest{pool, object_name, ""}; + int rc = send_mon_command(osdMapRequest, rados, "OSDMapRequest", inbl, + &outbl, formatter.get()); ceph_assert(rc == 0); JSONParser p; bool success = p.parse(outbl.c_str(), outbl.length()); ceph_assert(success); - ceph::io_exerciser::json::OSDMapReply reply{}; + ceph::messaging::osd::OSDMapReply reply{}; reply.decode_json(&p); model = std::make_unique( diff --git a/src/test/osd/ceph_test_rados_io_sequence.h b/src/test/osd/ceph_test_rados_io_sequence.h index c06c597f784..9af5f706b2f 100644 --- a/src/test/osd/ceph_test_rados_io_sequence.h +++ b/src/test/osd/ceph_test_rados_io_sequence.h @@ -204,7 +204,8 @@ class SelectECPool SelectECPool(ceph::util::random_number_generator& rng, po::variables_map vm, librados::Rados& rados, bool dry_run, bool allow_pool_autoscaling, bool allow_pool_balancer, - bool allow_pool_deep_scrubbing, bool allow_pool_scrubbing); + bool allow_pool_deep_scrubbing, bool allow_pool_scrubbing, + bool test_recovery); const std::string choose() override; bool get_allow_pool_autoscaling() { return allow_pool_autoscaling; } @@ -226,6 +227,7 @@ class SelectECPool bool allow_pool_balancer; bool allow_pool_deep_scrubbing; bool allow_pool_scrubbing; + bool test_recovery; int k; int m; -- 2.39.5