diff --git a/src/disk_tool/disk_tool.cpp b/src/disk_tool/disk_tool.cpp index f98f2b5e..6141ee4d 100644 --- a/src/disk_tool/disk_tool.cpp +++ b/src/disk_tool/disk_tool.cpp @@ -68,6 +68,7 @@ static const char *help_text = " --data_device_block 4k Override data device block size\n" " --meta_device_block 4k Override metadata device block size\n" " --journal_device_block 4k Override journal device block size\n" + " --json Enable JSON output\n" " \n" " immediate_commit setting is automatically derived from \"disable fsync\" options.\n" " It's set to \"all\" when fsync is disabled on all devices, and to \"small\" if fsync\n" @@ -102,6 +103,7 @@ static const char *help_text = " --move-meta TARGET move metadata to TARGET\n" " --journal-size NEW_SIZE resize journal to NEW_SIZE\n" " --data-size NEW_SIZE resize data device to NEW_SIZE\n" + " --json enable JSON output\n" " --dry-run only show new layout, do not apply it\n" " \n" " NEW_SIZE may include k/m/g/t suffixes.\n" @@ -131,10 +133,11 @@ static const char *help_text = " Commands are passed to systemctl with vitastor-osd@ units as arguments.\n" " When --now is added to enable/disable, OSDs are also immediately started/stopped.\n" "\n" - "vitastor-disk purge [--force] [--allow-data-loss] [device2 device3 ...]\n" + "vitastor-disk purge [--json] [--force] [--allow-data-loss] [device2 device3 ...]\n" " Purge Vitastor OSD(s) on specified device(s). Uses vitastor-cli rm-osd to check\n" " if deletion is possible without data loss and to actually remove metadata from etcd.\n" " --force and --allow-data-loss options may be used to ignore safety check results.\n" + " --json enables JSON output.\n" " \n" " Requires `vitastor-cli`, `sfdisk` and `partprobe` (from parted) utilities.\n" "\n" diff --git a/src/disk_tool/disk_tool.h b/src/disk_tool/disk_tool.h index 1a2e26cc..8d83c133 100644 --- a/src/disk_tool/disk_tool.h +++ b/src/disk_tool/disk_tool.h @@ -42,7 +42,7 @@ struct disk_tool_t std::map options; bool test_mode = false; - bool all, json, now; + bool all = false, json = false, now = false; bool dump_with_blocks, dump_with_data; blockstore_disk_t dsk; @@ -127,7 +127,7 @@ struct disk_tool_t json11::Json read_osd_superblock(std::string device, bool expect_exist = true, bool ignore_nonref = false); uint32_t write_osd_superblock(std::string device, json11::Json params); - int prepare_one(std::map options, int is_hdd = -1); + int prepare_one(std::map options, int is_hdd, json11::Json::object & result); int check_existing_partition(std::string & dev_by_uuid); int fix_partition_type(std::string & dev_by_uuid); int prepare(std::vector devices); diff --git a/src/disk_tool/disk_tool_prepare.cpp b/src/disk_tool/disk_tool_prepare.cpp index 3ea2c5d1..6fc936fa 100644 --- a/src/disk_tool/disk_tool_prepare.cpp +++ b/src/disk_tool/disk_tool_prepare.cpp @@ -6,7 +6,7 @@ #include "json_util.h" #include "osd_id.h" -int disk_tool_t::prepare_one(std::map options, int is_hdd) +int disk_tool_t::prepare_one(std::map options, int is_hdd, json11::Json::object & result) { static const char *allow_additional_params[] = { "autosync_writes", @@ -203,12 +203,14 @@ int disk_tool_t::prepare_one(std::map options, int is_ fprintf(stderr, "Initialized OSD %ju on %s\n", osd_num, desc.c_str()); if (!test_mode || options.find("no_init") == options.end()) { - if (shell_exec({ "systemctl", "enable", "--now", "vitastor-osd@"+std::to_string(osd_num) }, "", NULL, NULL) != 0) + std::string out; + if (shell_exec({ "systemctl", "enable", "--now", "vitastor-osd@"+std::to_string(osd_num) }, "", json ? &out : NULL, NULL) != 0) { fprintf(stderr, "Failed to enable systemd unit vitastor-osd@%ju\n", osd_num); return 1; } } + result = sb; return 0; } @@ -578,7 +580,13 @@ int disk_tool_t::prepare(std::vector devices) fprintf(stderr, "Device list (positional arguments), --osd_per_disk, --hybrid and --fast-devices are incompatible with --data_device\n"); return 1; } - return prepare_one(options, options.find("hdd") != options.end() ? 1 : 0); + json11::Json::object result; + int r = prepare_one(options, options.find("hdd") != options.end() ? 1 : 0, result); + if (r) + return r; + if (json) + printf("%s\n", json11::Json(result).dump().c_str()); + return 0; } if (!devices.size()) { @@ -669,6 +677,7 @@ int disk_tool_t::prepare(std::vector devices) options.erase("disable_meta_fsync"); options.erase("disable_journal_fsync"); } + json11::Json::array all_results, errors; auto journal_size = options["journal_size"]; for (auto & dev: devinfo) { @@ -688,7 +697,15 @@ int disk_tool_t::prepare(std::vector devices) options.erase("journal_size"); } // Treat all disks as SSDs if not in the hybrid mode - prepare_one(options, dev.is_hdd ? 1 : 0); + json11::Json::object result; + int r = prepare_one(options, dev.is_hdd ? 1 : 0, result); + if (json) + { + if (!r) + all_results.push_back(std::move(result)); + else + errors.push_back(options); + } if (hybrid) { options["journal_size"] = journal_size; @@ -697,5 +714,9 @@ int disk_tool_t::prepare(std::vector devices) } } } + if (json) + { + printf("%s\n", json11::Json(json11::Json::object{ { "osds", all_results }, { "errors", errors } }).dump().c_str()); + } return 0; } diff --git a/src/disk_tool/disk_tool_udev.cpp b/src/disk_tool/disk_tool_udev.cpp index 701e125a..09e02367 100644 --- a/src/disk_tool/disk_tool_udev.cpp +++ b/src/disk_tool/disk_tool_udev.cpp @@ -427,8 +427,12 @@ int disk_tool_t::purge_devices(const std::vector & devices) } } } + json11::Json::object result; + result["removed_osds"] = std::vector(osd_numbers.begin(), osd_numbers.end()); if (!osd_numbers.size()) { + if (json) + printf("%s\n", json11::Json(result).dump().c_str()); return 0; } std::vector rm_osd_cli = { "vitastor-cli", "rm-osd" }; @@ -457,17 +461,18 @@ int disk_tool_t::purge_devices(const std::vector & devices) { systemctl_cli.push_back("vitastor-osd@"+std::to_string(osd_num)); } - if (shell_exec(systemctl_cli, "", NULL, NULL) != 0) + if (shell_exec(systemctl_cli, "", json ? &dry_run_ignore_stdout : NULL, NULL) != 0) { return 1; } // Remove OSD metadata rm_osd_cli.pop_back(); - if (shell_exec(rm_osd_cli, "", NULL, NULL) != 0) + if (shell_exec(rm_osd_cli, "", json ? &dry_run_ignore_stdout : NULL, NULL) != 0) { return 1; } // Destroy OSD superblocks + json11::Json::array removed_devices; for (auto & sb: superblocks) { for (auto dev_type: std::vector{ "data", "meta", "journal" }) @@ -521,9 +526,15 @@ int disk_tool_t::purge_devices(const std::vector & devices) break; } } + removed_devices.push_back(dev); } } } } + if (json) + { + result["removed_devices"] = removed_devices; + printf("%s\n", json11::Json(result).dump().c_str()); + } return 0; }