diff --git a/src/cmd/cli.cpp b/src/cmd/cli.cpp index e1fb578b..cc6c6b05 100644 --- a/src/cmd/cli.cpp +++ b/src/cmd/cli.cpp @@ -37,6 +37,7 @@ static const char* help_text = " --sort FIELD Sort by specified field (name, size, used_size, _)\n" " -r|--reverse Sort in descending order\n" " -n|--count N Only list first N items\n" + " --ids ID1,ID2 Only list images with specified full IDs\n" " --tree Show image snapshot/clone tree\n" "\n" "vitastor-cli create -s|--size [-p|--pool ] [--parent [@]] \n" @@ -217,7 +218,7 @@ static const char* help_text = "vitastor-cli rm-pool|pool-rm [--force] \n" " Remove a pool. Refuses to remove pools with images without --force.\n" "\n" - "vitastor-cli ls-pools|pool-ls|ls-pool|pools [-l] [--detail] [--sort FIELD] [-r] [-n N] [--stats] [ ...]\n" + "vitastor-cli ls-pools|pool-ls|ls-pool|pools [-l] [--detail] [--sort FIELD] [-r] [-n N] [ ...]\n" " List pools (only matching patterns if passed).\n" " -l|--long Also report I/O statistics\n" " --detail Use list format (not table), show all details\n" @@ -442,7 +443,22 @@ std::function cli_tool_t::start(json11::Json::object cfg, else if (cmd[0] == "rm") { // Remove multiple snapshots and rebase their children - if (cfg["exact"].bool_value() || cfg["matching"].bool_value()) + if (cfg["names"].is_array()) + { + cfg["globs"] = cfg["names"]; + cfg.erase("names"); + cfg["exact"] = true; + cfg["matching"] = false; + action_cb = start_rm_wildcard(cfg); + } + else if (cfg["matching"].is_array()) + { + cfg["globs"] = cfg["matching"]; + cfg["exact"] = false; + cfg["matching"] = true; + action_cb = start_rm_wildcard(cfg); + } + else if (cfg["exact"].bool_value() || cfg["matching"].bool_value()) { cmd.erase(cmd.begin(), cmd.begin()+1); cfg["globs"] = cmd; @@ -477,12 +493,12 @@ std::function cli_tool_t::start(json11::Json::object cfg, else if (cmd[0] == "osd-tree") { // Print OSD tree + cfg["as_tree"] = true; action_cb = start_osd_tree(cfg); } else if (cmd[0] == "osds" || cmd[0] == "ls-osds" || cmd[0] == "ls-osd" || cmd[0] == "osd-ls") { // Print OSD list - cfg["flat"] = true; action_cb = start_osd_tree(cfg); } else if (cmd[0] == "modify-osd") @@ -516,7 +532,7 @@ std::function cli_tool_t::start(json11::Json::object cfg, // Modify existing pool if (cmd.size() > 1) { - cfg["old_name"] = cmd[1]; + cfg["pool"] = cmd[1]; } action_cb = start_pool_modify(cfg); } diff --git a/src/cmd/cli_create.cpp b/src/cmd/cli_create.cpp index e9e94719..fc7f5d20 100644 --- a/src/cmd/cli_create.cpp +++ b/src/cmd/cli_create.cpp @@ -64,7 +64,8 @@ struct image_creator_t } if (new_pool_id) { - if (pools.find(new_pool_id) == pools.end()) + auto pool_it = pools.find(new_pool_id); + if (pool_it == pools.end()) { result = (cli_result_t){ .err = ENOENT, .text = "Pool "+std::to_string(new_pool_id)+" does not exist" }; state = 100; @@ -194,15 +195,31 @@ resume_3: // Save into inode_config for library users to be able to take it from there immediately new_cfg.mod_revision = parent->etcd_result["header"]["revision"].uint64_value(); parent->cli->st_cli.insert_inode_config(new_cfg); + auto img = json11::Json::object { + { "inode_id", INODE_WITH_POOL(new_pool_id, new_id) }, + { "inode_num", new_id }, + { "name", image_name }, + { "pool_id", (uint64_t)new_pool_id }, + { "size", size }, + }; + { + auto new_pool_it = parent->cli->st_cli.pool_config.find(new_pool_id); + if (new_pool_it != parent->cli->st_cli.pool_config.end()) + { + img["pool_name"] = new_pool_it->second.name; + } + } + if (new_parent_id) + { + img["parent_name"] = new_parent; + img["parent_inode_id"] = new_parent_id; + img["parent_inode_num"] = INODE_NO_POOL(new_parent_id); + img["parent_pool_id"] = (uint64_t)INODE_POOL(new_parent_id); + } result = (cli_result_t){ .err = 0, .text = "Image "+image_name+" created", - .data = json11::Json::object { - { "name", image_name }, - { "pool", new_pool_name }, - { "parent", new_parent }, - { "size", size }, - } + .data = img, }; state = 100; } @@ -272,13 +289,23 @@ resume_4: // Save into inode_config for library users to be able to take it from there immediately new_cfg.mod_revision = parent->etcd_result["header"]["revision"].uint64_value(); parent->cli->st_cli.insert_inode_config(new_cfg); + { + auto new_pool_it = parent->cli->st_cli.pool_config.find(new_pool_id); + new_pool_name = new_pool_it != parent->cli->st_cli.pool_config.end() ? new_pool_it->second.name : ""; + } result = (cli_result_t){ .err = 0, .text = "Snapshot "+image_name+"@"+new_snap+" created", .data = json11::Json::object { - { "name", image_name+"@"+new_snap }, - { "pool", (uint64_t)new_pool_id }, - { "parent", new_parent }, + { "inode_id", INODE_WITH_POOL(new_pool_id, new_id) }, + { "inode_num", new_id }, + { "name", image_name }, + { "pool_id", (uint64_t)new_pool_id }, + { "pool_name", new_pool_name }, + { "parent_name", image_name+"@"+new_snap }, + { "parent_inode_id", INODE_WITH_POOL(old_pool_id, old_id) }, + { "parent_inode_num", old_id }, + { "parent_pool_id", (uint64_t)old_pool_id }, { "size", size }, } }; @@ -554,8 +581,16 @@ std::function cli_tool_t::start_create(json11::Json cfg) auto image_creator = new image_creator_t(); image_creator->parent = this; image_creator->image_name = cfg["image"].string_value(); - image_creator->new_pool_id = cfg["pool"].uint64_value(); - image_creator->new_pool_name = cfg["pool"].string_value(); + if (!cfg["pool"].is_null()) + { + image_creator->new_pool_id = cfg["pool"].uint64_value(); + image_creator->new_pool_name = cfg["pool"].string_value(); + } + else + { + image_creator->new_pool_id = cfg["pool_id"].uint64_value(); + image_creator->new_pool_name = cfg["pool_name"].string_value(); + } image_creator->force = cfg["force"].bool_value(); image_creator->force_size = cfg["force_size"].bool_value(); if (cfg["image_meta"].is_object()) diff --git a/src/cmd/cli_dd.cpp b/src/cmd/cli_dd.cpp index 26e9d09b..7b64fe54 100644 --- a/src/cmd/cli_dd.cpp +++ b/src/cmd/cli_dd.cpp @@ -864,7 +864,7 @@ resume_2: // Copy data if (iinfo.in_seekable && iseek >= iinfo.in_size) { - result = (cli_result_t){ .err = -EINVAL, .text = "Input seek position is beyond end of input" }; + result = (cli_result_t){ .err = EINVAL, .text = "Input seek position is beyond end of input" }; goto close_end; } if (!iinfo.iwatch && !iinfo.in_seekable && iseek) diff --git a/src/cmd/cli_describe.cpp b/src/cmd/cli_describe.cpp index 7f489d47..58f0da38 100644 --- a/src/cmd/cli_describe.cpp +++ b/src/cmd/cli_describe.cpp @@ -57,12 +57,24 @@ struct cli_describe_t void parse_options(json11::Json cfg) { - only_pool = cfg["pool"].uint64_value(); - if (!only_pool && cfg["pool"].is_string()) + uint64_t pool_id; + std::string pool_name; + if (!cfg["pool"].is_null()) + { + pool_id = cfg["pool"].uint64_value(); + pool_name = pool_id ? "" : cfg["pool"].string_value(); + } + else + { + pool_id = cfg["pool_id"].uint64_value(); + pool_name = pool_id ? "" : cfg["pool_name"].string_value(); + } + only_pool = pool_id; + if (!only_pool && pool_name != "") { for (auto & pp: parent->cli->st_cli.pool_config) { - if (pp.second.name == cfg["pool"].string_value()) + if (pp.second.name == pool_name) { only_pool = pp.first; break; @@ -106,6 +118,22 @@ struct cli_describe_t if (cfg["object_state"].string_value().find("misplaced") != std::string::npos) object_state |= OBJ_MISPLACED; } + else if (!object_state && cfg["object_state"].is_array()) + { + for (auto & st: cfg["object_state"].array_items()) + { + if (st == "inconsistent") + object_state |= OBJ_INCONSISTENT; + else if (st == "corrupted") + object_state |= OBJ_CORRUPTED; + else if (st == "incomplete") + object_state |= OBJ_INCOMPLETE; + else if (st == "degraded") + object_state |= OBJ_DEGRADED; + else if (st == "misplaced") + object_state |= OBJ_MISPLACED; + } + } } void loop() diff --git a/src/cmd/cli_ls.cpp b/src/cmd/cli_ls.cpp index d23def32..9a7bcdd8 100644 --- a/src/cmd/cli_ls.cpp +++ b/src/cmd/cli_ls.cpp @@ -17,6 +17,7 @@ struct image_lister_t std::string list_pool_name; std::string sort_field; std::set only_names; + std::vector only_ids; bool reverse = false; bool exact = false; bool tree = false; @@ -63,7 +64,6 @@ struct image_lister_t auto item = json11::Json::object { { "name", ic.second.name }, { "size", ic.second.size }, - { "used_size", 0 }, { "readonly", ic.second.readonly }, { "pool_id", (uint64_t)INODE_POOL(ic.second.num) }, { "pool_name", good_pool ? pool_it->second.name : "? (ID:"+std::to_string(INODE_POOL(ic.second.num))+")" }, @@ -202,20 +202,33 @@ resume_1: json11::Json::array to_list() { json11::Json::array list; - for (auto & kv: stats) + if (only_ids.size()) { - if (!only_names.size()) + for (auto & id: only_ids) { - list.push_back(kv.second); - } - else - { - for (auto & glob: only_names) + if (stats.find(id) != stats.end()) { - if (exact ? (kv.second["name"].string_value() == glob) : stupid_glob(kv.second["name"].string_value(), glob)) + list.push_back(stats[id]); + } + } + } + else + { + for (auto & kv: stats) + { + if (!only_names.size()) + { + list.push_back(kv.second); + } + else + { + for (auto & glob: only_names) { - list.push_back(kv.second); - break; + if (exact ? (kv.second["name"].string_value() == glob) : stupid_glob(kv.second["name"].string_value(), glob)) + { + list.push_back(kv.second); + break; + } } } } @@ -570,17 +583,30 @@ std::function cli_tool_t::start_ls(json11::Json cfg) lister->parent = this; lister->exact = cfg["exact"].bool_value(); lister->tree = cfg["tree"].bool_value(); - lister->list_pool_id = cfg["pool"].uint64_value(); - lister->list_pool_name = lister->list_pool_id ? "" : cfg["pool"].as_string(); + if (!cfg["pool"].is_null()) + { + lister->list_pool_id = cfg["pool"].uint64_value(); + lister->list_pool_name = lister->list_pool_id ? "" : cfg["pool"].as_string(); + } + else + { + lister->list_pool_id = cfg["pool_id"].uint64_value(); + lister->list_pool_name = lister->list_pool_id ? "" : cfg["pool_name"].string_value(); + } lister->show_stats = cfg["long"].bool_value(); lister->show_delete = cfg["del"].bool_value(); lister->sort_field = cfg["sort"].string_value() != "" ? cfg["sort"].string_value() : "name"; lister->reverse = cfg["reverse"].bool_value(); lister->max_count = cfg["count"].uint64_value(); + if (cfg["names"].is_string()) + lister->only_names.insert(cfg["names"].string_value()); for (auto & item: cfg["names"].array_items()) - { lister->only_names.insert(item.string_value()); - } + if (cfg["ids"].is_string()) + for (auto & item: explode(",", cfg["ids"].string_value(), true)) + lister->only_ids.push_back(stoull_full(item)); + for (auto & item: cfg["ids"].array_items()) + lister->only_ids.push_back(item.uint64_value()); return [lister](cli_result_t & result) { lister->loop(); diff --git a/src/cmd/cli_merge.cpp b/src/cmd/cli_merge.cpp index 8081ce3b..497e83b4 100644 --- a/src/cmd/cli_merge.cpp +++ b/src/cmd/cli_merge.cpp @@ -374,7 +374,7 @@ struct snap_merger_t result = (cli_result_t){ .text = "Done, layers from "+from_name+" to "+to_name+" merged into "+target_name, .data = json11::Json::object { { "from", from_name }, { "to", to_name }, - { "into", target_name }, + { "target", target_name }, }}; state = 100; resume_100: diff --git a/src/cmd/cli_modify.cpp b/src/cmd/cli_modify.cpp index d1e265e4..3402e43f 100644 --- a/src/cmd/cli_modify.cpp +++ b/src/cmd/cli_modify.cpp @@ -88,10 +88,7 @@ struct image_changer_t (!new_size && !force_size || cfg.size == new_size || cfg.size >= new_size && inc_size) && (new_name == "" || new_name == image_name)) { - result = (cli_result_t){ .err = 0, .text = "No change", .data = json11::Json::object { - { "error_code", 0 }, - { "error_text", "No change" }, - }}; + result = (cli_result_t){ .err = 0, .text = "No change", .data = fill_img(cfg) }; state = 100; return; } @@ -235,15 +232,42 @@ resume_2: result = (cli_result_t){ .err = 0, .text = "Image "+image_name+" modified", - .data = json11::Json::object { - { "name", image_name }, - { "inode", INODE_NO_POOL(inode_num) }, - { "pool", (uint64_t)INODE_POOL(inode_num) }, - { "size", new_size }, - } + .data = fill_img(cfg) }; state = 100; } + + json11::Json fill_img(inode_config_t & cfg) + { + auto img = json11::Json::object { + { "inode_id", inode_num }, + { "inode_num", INODE_NO_POOL(inode_num) }, + { "name", cfg.name }, + { "pool_id", (uint64_t)INODE_POOL(inode_num) }, + { "size", cfg.size }, + { "readonly", cfg.readonly }, + { "deleted", cfg.deleted }, + }; + { + auto pool_it = parent->cli->st_cli.pool_config.find(INODE_POOL(inode_num)); + if (pool_it != parent->cli->st_cli.pool_config.end()) + { + img["pool_name"] = pool_it->second.name; + } + } + if (cfg.parent_id) + { + auto parent_it = parent->cli->st_cli.inode_config.find(cfg.parent_id); + if (parent_it != parent->cli->st_cli.inode_config.end()) + { + img["parent_name"] = parent_it->second.name; + } + img["parent_inode_id"] = cfg.parent_id; + img["parent_inode_num"] = INODE_NO_POOL(cfg.parent_id); + img["parent_pool_id"] = (uint64_t)INODE_POOL(cfg.parent_id); + } + return img; + } }; std::function cli_tool_t::start_modify(json11::Json cfg) diff --git a/src/cmd/cli_osd_tree.cpp b/src/cmd/cli_osd_tree.cpp index d3ccc43d..9352199f 100644 --- a/src/cmd/cli_osd_tree.cpp +++ b/src/cmd/cli_osd_tree.cpp @@ -41,7 +41,7 @@ struct osd_tree_printer_t { cli_tool_t *parent; json11::Json cfg; - bool flat = false; + bool as_tree = false; bool show_stats = false; int state = 0; @@ -209,11 +209,14 @@ resume_1: for (int i = 1; i < node_seq.size(); i++) { auto & node = placement_tree->nodes.at(node_seq[i]); - fmt_items.push_back(json11::Json::object{ - { "type", node.level }, - { "name", node.name }, - { "parent", node.parent }, - }); + if (as_tree) + { + fmt_items.push_back(json11::Json::object{ + { "type", node.level }, + { "name", node.name }, + { "parent", node.parent }, + }); + } for (uint64_t osd_num: node.child_osds) { auto & osd = placement_tree->osds.at(osd_num); @@ -221,17 +224,22 @@ resume_1: { "type", "osd" }, { "name", osd.num }, { "parent", node.name }, - { "up", osd.up ? "up" : "down" }, + { "up", osd.up }, { "size", osd.size }, { "free", osd.free }, { "reweight", osd.reweight }, { "noout", osd.noout }, { "tags", osd.tags }, - { "block", (uint64_t)osd.block_size }, - { "bitmap", (uint64_t)osd.bitmap_granularity }, - { "commit", osd.immediate_commit == IMMEDIATE_NONE ? "none" : (osd.immediate_commit == IMMEDIATE_ALL ? "all" : "small") }, - { "op_stats", osd_stats[osd_num]["op_stats"] }, + { "data_block_size", (uint64_t)osd.block_size }, + { "bitmap_granularity", (uint64_t)osd.bitmap_granularity }, + { "immediate_commit", osd.immediate_commit == IMMEDIATE_NONE ? "none" : (osd.immediate_commit == IMMEDIATE_ALL ? "all" : "small") }, }; + if (show_stats) + { + json_osd["op_stats"] = osd_stats[osd_num]["op_stats"]; + json_osd["subop_stats"] = osd_stats[osd_num]["subop_stats"]; + json_osd["recovery_stats"] = osd_stats[osd_num]["recovery_stats"]; + } if (osd_stats[osd_num]["slow_ops_primary"].uint64_value() > 0) { json_osd["slow_ops_primary"] = osd_stats[osd_num]["slow_ops_primary"]; @@ -249,7 +257,7 @@ resume_1: for (int i = 1; i < node_seq.size(); i++) { auto & node = placement_tree->nodes.at(node_seq[i]); - if (!flat) + if (as_tree) { fmt_items.push_back(json11::Json::object{ { "type", str_repeat(" ", indents[i]) + node.level }, @@ -257,7 +265,7 @@ resume_1: }); } std::string parent = node.name; - if (flat) + if (!as_tree) { auto cur = &placement_tree->nodes.at(node.name); while (cur->parent != "" && cur->parent != node.name) @@ -270,7 +278,7 @@ resume_1: { auto & osd = placement_tree->osds.at(osd_num); auto fmt = json11::Json::object{ - { "type", (flat ? "osd" : str_repeat(" ", indents[i]+1) + "osd") }, + { "type", (!as_tree ? "osd" : str_repeat(" ", indents[i]+1) + "osd") }, { "name", osd.num }, { "parent", parent }, { "up", osd.up ? "up" : "down" }, @@ -300,7 +308,7 @@ resume_1: } } json11::Json::array cols; - if (!flat) + if (as_tree) { cols.push_back(json11::Json::object{ { "key", "type" }, @@ -309,9 +317,9 @@ resume_1: } cols.push_back(json11::Json::object{ { "key", "name" }, - { "title", flat ? "OSD" : "NAME" }, + { "title", !as_tree ? "OSD" : "NAME" }, }); - if (flat) + if (!as_tree) { cols.push_back(json11::Json::object{ { "key", "parent" }, @@ -414,7 +422,7 @@ std::function cli_tool_t::start_osd_tree(json11::Json cfg) auto osd_tree_printer = new osd_tree_printer_t(); osd_tree_printer->parent = this; osd_tree_printer->cfg = cfg; - osd_tree_printer->flat = cfg["flat"].bool_value(); + osd_tree_printer->as_tree = cfg["as_tree"].bool_value(); osd_tree_printer->show_stats = cfg["long"].bool_value(); return [osd_tree_printer](cli_result_t & result) { diff --git a/src/cmd/cli_pg_ls.cpp b/src/cmd/cli_pg_ls.cpp index ce03fe16..a8f59d61 100644 --- a/src/cmd/cli_pg_ls.cpp +++ b/src/cmd/cli_pg_ls.cpp @@ -282,10 +282,16 @@ std::function cli_tool_t::start_pg_list(json11::Json cfg) { auto pg_lister = new pg_lister_t(); pg_lister->parent = this; - if (cfg["pool"].uint64_value()) + if (!cfg["pool"].is_null()) + { pg_lister->pool_id = cfg["pool"].uint64_value(); + pg_lister->pool_name = pg_lister->pool_id ? "" : cfg["pool"].string_value(); + } else - pg_lister->pool_name = cfg["pool"].string_value(); + { + pg_lister->pool_id = cfg["pool_id"].uint64_value(); + pg_lister->pool_name = pg_lister->pool_id ? "" : cfg["pool_name"].string_value(); + } for (auto & st: cfg["pg_state"].array_items()) pg_lister->pg_state.push_back(st.string_value()); if (cfg["pg_state"].is_string()) diff --git a/src/cmd/cli_pool_create.cpp b/src/cmd/cli_pool_create.cpp index 52641479..d47283dc 100644 --- a/src/cmd/cli_pool_create.cpp +++ b/src/cmd/cli_pool_create.cpp @@ -213,7 +213,7 @@ resume_3: if (failure_domain != "osd") pool_err += "\n- different parent '"+failure_domain+"' nodes"; result = (cli_result_t){ - .err = EINVAL, + .err = EBUSY, .text = pool_err, }; state = 100; diff --git a/src/cmd/cli_pool_ls.cpp b/src/cmd/cli_pool_ls.cpp index 64bb66ff..10960f10 100644 --- a/src/cmd/cli_pool_ls.cpp +++ b/src/cmd/cli_pool_ls.cpp @@ -206,7 +206,7 @@ resume_1: { "space_efficiency", pool_stats[pool_cfg.id]["space_efficiency"].number_value() }, { "pg_real_size", pool_stats[pool_cfg.id]["pg_real_size"].uint64_value() }, { "osd_count", (uint64_t)pg_per_osd.size() }, - { "backfillfull", pool_cfg.backfillfull }, + { "backfillfull", !!pool_cfg.backfillfull }, }; } // Include full pool config @@ -546,6 +546,10 @@ resume_3: { "write_fmt", "Write" }, { "delete_fmt", "Delete" }, }; + if (sort_field == "osd_tags" || sort_field == "primary_affinity_tags") + { + sort_field += "_fmt"; + } auto list = to_list(); size_t title_len = 0; for (auto & item: list) @@ -666,15 +670,12 @@ std::function cli_tool_t::start_pool_ls(json11::Json cfg) lister->show_stats = cfg["long"].bool_value(); lister->detailed = cfg["detail"].bool_value(); lister->sort_field = cfg["sort"].string_value(); - if ((lister->sort_field == "osd_tags") || - (lister->sort_field == "primary_affinity_tags" )) - lister->sort_field = lister->sort_field + "_fmt"; lister->reverse = cfg["reverse"].bool_value(); lister->max_count = cfg["count"].uint64_value(); + if (cfg["names"].is_string()) + lister->only_names.insert(cfg["names"].string_value()); for (auto & item: cfg["names"].array_items()) - { lister->only_names.insert(item.string_value()); - } return [lister](cli_result_t & result) { lister->loop(); diff --git a/src/cmd/cli_pool_modify.cpp b/src/cmd/cli_pool_modify.cpp index f810b1c0..04c944da 100644 --- a/src/cmd/cli_pool_modify.cpp +++ b/src/cmd/cli_pool_modify.cpp @@ -39,16 +39,21 @@ struct pool_changer_t goto resume_1; else if (state == 2) goto resume_2; - pool_id = stoull_full(cfg["old_name"].string_value()); - if (!pool_id) + if (!cfg["pool"].is_null()) { - pool_name = cfg["old_name"].string_value(); - if (pool_name == "") - { - result = (cli_result_t){ .err = ENOENT, .text = "Pool ID or name is required to modify it" }; - state = 100; - return; - } + pool_id = cfg["pool"].uint64_value(); + pool_name = pool_id ? "" : cfg["pool"].string_value(); + } + else + { + pool_id = cfg["id"].uint64_value(); + pool_name = pool_id ? "" : cfg["old_name"].string_value(); + } + if (!pool_id && pool_name == "") + { + result = (cli_result_t){ .err = ENOENT, .text = "Pool ID or name is required to modify it" }; + state = 100; + return; } resume_0: // Get pools from etcd @@ -179,7 +184,7 @@ resume_2: result = (cli_result_t){ .err = 0, .text = "Pool "+pool_name+" updated", - .data = new_pools, + .data = new_pools[std::to_string(pool_id)], }; state = 100; } diff --git a/src/cmd/cli_pool_rm.cpp b/src/cmd/cli_pool_rm.cpp index 58776053..4ce63d2d 100644 --- a/src/cmd/cli_pool_rm.cpp +++ b/src/cmd/cli_pool_rm.cpp @@ -196,7 +196,9 @@ resume_3: result = (cli_result_t){ .err = 0, .text = "Pool "+pool_name+" deleted", - .data = new_pools + .data = json11::Json::object{ + {"ok", true}, + }, }; state = 100; } @@ -207,8 +209,16 @@ std::function cli_tool_t::start_pool_rm(json11::Json cfg) auto pool_remover = new pool_remover_t(); pool_remover->parent = this; - pool_remover->pool_id = cfg["pool"].uint64_value(); - pool_remover->pool_name = pool_remover->pool_id ? "" : cfg["pool"].as_string(); + if (!cfg["pool"].is_null()) + { + pool_remover->pool_id = cfg["pool"].uint64_value(); + pool_remover->pool_name = pool_remover->pool_id ? "" : cfg["pool"].as_string(); + } + else + { + pool_remover->pool_id = cfg["pool_id"].uint64_value(); + pool_remover->pool_name = pool_remover->pool_id ? "" : cfg["pool_name"].as_string(); + } pool_remover->force = !cfg["force"].is_null(); diff --git a/src/cmd/cli_rm_data.cpp b/src/cmd/cli_rm_data.cpp index 41d26cf0..e98cc83e 100644 --- a/src/cmd/cli_rm_data.cpp +++ b/src/cmd/cli_rm_data.cpp @@ -264,7 +264,7 @@ struct rm_inode_t { // Error result = (cli_result_t){ - .err = EIO, + .err = EBUSY, .text = "Failed: some blocks were not removed", .data = data, }; diff --git a/src/cmd/cli_rm_osd.cpp b/src/cmd/cli_rm_osd.cpp index 790c7e38..84ab722a 100644 --- a/src/cmd/cli_rm_osd.cpp +++ b/src/cmd/cli_rm_osd.cpp @@ -181,6 +181,7 @@ struct rm_osd_t if (dry_run || is_dataloss && !force_dataloss || is_warning && !force_warning) { result.err = is_dataloss && !force_dataloss || is_warning && !force_warning ? EBUSY : 0; + result.data = json11::Json::object{ { "pool_effects", pool_effects } }; state = 100; return; } @@ -332,6 +333,9 @@ struct rm_osd_t ids = (osd_ids.size() > 1 ? "OSDs " : "OSD ")+ids+(osd_ids.size() > 1 ? " are" : " is")+" removed from etcd"; state = 100; result.text = (result.text != "" ? ids+"\n"+result.text : ids); + result.data = json11::Json::object { + {"deleted_osds", osd_ids}, + }; result.err = 0; } diff --git a/src/cmd/cli_rm_wildcard.cpp b/src/cmd/cli_rm_wildcard.cpp index 872bae26..7f9df940 100644 --- a/src/cmd/cli_rm_wildcard.cpp +++ b/src/cmd/cli_rm_wildcard.cpp @@ -195,6 +195,8 @@ std::function cli_tool_t::start_rm_wildcard(json11::Json c auto wildcard_remover = new wildcard_remover_t(); wildcard_remover->parent = this; wildcard_remover->cfg = cfg; + if (cfg["globs"].is_string()) + wildcard_remover->globs.push_back(cfg["globs"].string_value()); for (auto & glob: cfg["globs"].array_items()) wildcard_remover->globs.push_back(glob.string_value()); wildcard_remover->exact = cfg["exact"].bool_value(); diff --git a/src/cmd/cli_status.cpp b/src/cmd/cli_status.cpp index 2c902587..f812a8cc 100644 --- a/src/cmd/cli_status.cpp +++ b/src/cmd/cli_status.cpp @@ -18,6 +18,7 @@ struct status_printer_t { cli_tool_t *parent; + cli_result_t result; int state = 0; json11::Json::array mon_members; json11::Json agg_stats; @@ -89,7 +90,7 @@ resume_2: return; if (parent->etcd_err.err) { - fprintf(stderr, "%s\n", parent->etcd_err.text.c_str()); + result = parent->etcd_err; state = 100; return; } @@ -107,7 +108,8 @@ resume_2: if (etcd_states[i]["error"].is_null()) { etcd_alive++; - etcd_db_size = etcd_states[i]["dbSize"].uint64_value(); + uint64_t db_size = etcd_states[i]["dbSize"].uint64_value(); + etcd_db_size = db_size > etcd_db_size ? db_size : etcd_db_size; } } int mon_count = 0; @@ -265,7 +267,7 @@ resume_2: obj_n = agg_stats["object_counts"][str].uint64_value() * parent->cli->st_cli.global_block_size; json_status[str+"_data"] = obj_n; } - printf("%s\n", json11::Json(json_status).dump().c_str()); + result.data = json11::Json(json_status); state = 100; return; } @@ -406,7 +408,7 @@ std::function cli_tool_t::start_status(json11::Json cfg) printer->loop(); if (printer->is_done()) { - result = { .err = 0 }; + result = printer->result; delete printer; return true; }