From edd4d98fefe63ad31bf96fa61716b4ee079c0498 Mon Sep 17 00:00:00 2001 From: David Zafman Date: Fri, 8 Sep 2017 17:53:07 -0700 Subject: [PATCH] ceph-objectstore-tool: Make pg removal require --force Add new export-remove to combine the 2 operations Fixes: http://tracker.ceph.com/issues/21272 Signed-off-by: David Zafman (cherry picked from commit 3bb20f6d750915d176c7a34367dac966a20faa76) --- .../special/ceph_objectstore_tool.py | 11 ++-- qa/tasks/ceph_manager.py | 3 +- qa/tasks/ceph_objectstore_tool.py | 2 +- qa/tasks/divergent_priors2.py | 8 +-- qa/tasks/reg11184.py | 11 +--- src/tools/ceph_objectstore_tool.cc | 53 ++++++++++--------- 6 files changed, 42 insertions(+), 46 deletions(-) diff --git a/qa/standalone/special/ceph_objectstore_tool.py b/qa/standalone/special/ceph_objectstore_tool.py index 9fdbac90688cb..7c52101e4d677 100755 --- a/qa/standalone/special/ceph_objectstore_tool.py +++ b/qa/standalone/special/ceph_objectstore_tool.py @@ -1018,7 +1018,10 @@ def main(argv): cmd = "{path}/ceph-objectstore-tool --type memstore --op list --pgid {pg}".format(dir=OSDDIR, osd=ONEOSD, pg=ONEPG, path=CEPH_BIN) ERRORS += test_failure(cmd, "Must provide --data-path") - cmd = (CFSD_PREFIX + "--op remove").format(osd=ONEOSD) + cmd = (CFSD_PREFIX + "--op remove --pgid 2.0").format(osd=ONEOSD) + ERRORS += test_failure(cmd, "Please use export-remove or you must use --force option") + + cmd = (CFSD_PREFIX + "--force --op remove").format(osd=ONEOSD) ERRORS += test_failure(cmd, "Must provide pgid") # Don't secify a --op nor object command @@ -1027,7 +1030,7 @@ def main(argv): # Specify a bad --op command cmd = (CFSD_PREFIX + "--op oops").format(osd=ONEOSD) - ERRORS += test_failure(cmd, "Must provide --op (info, log, remove, mkfs, fsck, export, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, get-osdmap, set-osdmap, get-inc-osdmap, set-inc-osdmap, mark-complete)") + ERRORS += test_failure(cmd, "Must provide --op (info, log, remove, mkfs, fsck, export, export-remove, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, get-osdmap, set-osdmap, get-inc-osdmap, set-inc-osdmap, mark-complete)") # Provide just the object param not a command cmd = (CFSD_PREFIX + "object").format(osd=ONEOSD) @@ -1732,7 +1735,7 @@ def main(argv): if ret != 0: logging.error("Removing --dry-run failed for pg {pg} on {osd} with {ret}".format(pg=pg, osd=osd, ret=ret)) RM_ERRORS += 1 - cmd = (CFSD_PREFIX + "--op remove --pgid {pg}").format(pg=pg, osd=osd) + cmd = (CFSD_PREFIX + "--force --op remove --pgid {pg}").format(pg=pg, osd=osd) logging.debug(cmd) ret = call(cmd, shell=True, stdout=nullfd) if ret != 0: @@ -1935,7 +1938,7 @@ def main(argv): which = 0 for osd in get_osds(pg, OSDDIR): - cmd = (CFSD_PREFIX + "--op remove --pgid {pg}").format(pg=pg, osd=osd) + cmd = (CFSD_PREFIX + "--force --op remove --pgid {pg}").format(pg=pg, osd=osd) logging.debug(cmd) ret = call(cmd, shell=True, stdout=nullfd) diff --git a/qa/tasks/ceph_manager.py b/qa/tasks/ceph_manager.py index 9da03bdd90823..bdc0fdf405e8f 100644 --- a/qa/tasks/ceph_manager.py +++ b/qa/tasks/ceph_manager.py @@ -286,6 +286,7 @@ class Thrasher: pg=pg, id=exp_osd)) # export + # Can't use new export-remove op since this is part of upgrade testing cmd = prefix + "--op export --pgid {pg} --file {file}" cmd = cmd.format(id=exp_osd, pg=pg, file=exp_path) proc = exp_remote.run(args=cmd) @@ -294,7 +295,7 @@ class Thrasher: "export failure with status {ret}". format(ret=proc.exitstatus)) # remove - cmd = prefix + "--op remove --pgid {pg}" + cmd = prefix + "--force --op remove --pgid {pg}" cmd = cmd.format(id=exp_osd, pg=pg) proc = exp_remote.run(args=cmd) if proc.exitstatus: diff --git a/qa/tasks/ceph_objectstore_tool.py b/qa/tasks/ceph_objectstore_tool.py index 3dc49624c2cb6..912577317b402 100644 --- a/qa/tasks/ceph_objectstore_tool.py +++ b/qa/tasks/ceph_objectstore_tool.py @@ -591,7 +591,7 @@ def test_objectstore(ctx, config, cli_remote, REP_POOL, REP_NAME, ec=False): continue for pg in pgs[osdid]: - cmd = ((prefix + "--op remove --pgid {pg}"). + cmd = ((prefix + "--force --op remove --pgid {pg}"). format(pg=pg, id=osdid)) proc = remote.run(args=cmd, check_status=False, stdout=StringIO()) diff --git a/qa/tasks/divergent_priors2.py b/qa/tasks/divergent_priors2.py index 0e645c7c4c35b..0ed753278b411 100644 --- a/qa/tasks/divergent_priors2.py +++ b/qa/tasks/divergent_priors2.py @@ -156,13 +156,7 @@ def task(ctx, config): format(fpath=FSPATH, jpath=JPATH)) pid = os.getpid() expfile = os.path.join(testdir, "exp.{pid}.out".format(pid=pid)) - cmd = ((prefix + "--op export --pgid 2.0 --file {file}"). - format(id=divergent, file=expfile)) - proc = exp_remote.run(args=cmd, wait=True, - check_status=False, stdout=StringIO()) - assert proc.exitstatus == 0 - - cmd = ((prefix + "--op remove --pgid 2.0"). + cmd = ((prefix + "--op export-remove --pgid 2.0 --file {file}"). format(id=divergent, file=expfile)) proc = exp_remote.run(args=cmd, wait=True, check_status=False, stdout=StringIO()) diff --git a/qa/tasks/reg11184.py b/qa/tasks/reg11184.py index 50e3a8b33d54a..f248623844954 100644 --- a/qa/tasks/reg11184.py +++ b/qa/tasks/reg11184.py @@ -174,19 +174,12 @@ def task(ctx, config): format(fpath=FSPATH, jpath=JPATH)) pid = os.getpid() expfile = os.path.join(testdir, "exp.{pid}.out".format(pid=pid)) - cmd = ((prefix + "--op export --pgid 2.0 --file {file}"). + cmd = ((prefix + "--op export-remove --pgid 2.0 --file {file}"). format(id=divergent, file=expfile)) proc = exp_remote.run(args=cmd, wait=True, check_status=False, stdout=StringIO()) assert proc.exitstatus == 0 - # Remove the same pg that was exported - cmd = ((prefix + "--op remove --pgid 2.0"). - format(id=divergent)) - proc = exp_remote.run(args=cmd, wait=True, - check_status=False, stdout=StringIO()) - assert proc.exitstatus == 0 - # Kill one of non-divergent OSDs log.info('killing osd.%d' % non_divergent[0]) manager.kill_osd(non_divergent[0]) @@ -194,7 +187,7 @@ def task(ctx, config): # manager.mark_out_osd(non_divergent[0]) # An empty collection for pg 2.0 might need to be cleaned up - cmd = ((prefix + "--op remove --pgid 2.0"). + cmd = ((prefix + "--force --op remove --pgid 2.0"). format(id=non_divergent[0])) proc = exp_remote.run(args=cmd, wait=True, check_status=False, stdout=StringIO()) diff --git a/src/tools/ceph_objectstore_tool.cc b/src/tools/ceph_objectstore_tool.cc index de41195e565fa..f5fe6e5290d68 100644 --- a/src/tools/ceph_objectstore_tool.cc +++ b/src/tools/ceph_objectstore_tool.cc @@ -73,7 +73,7 @@ CompatSet get_test_compat_set() { const ssize_t max_read = 1024 * 1024; const int fd_none = INT_MIN; bool outistty; -bool dry_run = false; +bool dry_run; struct action_on_object_t { virtual ~action_on_object_t() {} @@ -294,7 +294,7 @@ ghobject_t log_oid; ghobject_t biginfo_oid; int file_fd = fd_none; -bool debug = false; +bool debug; super_header sh; uint64_t testalign; @@ -2534,16 +2534,16 @@ int main(int argc, char **argv) ("journal-path", po::value(&jpath), "path to journal, use if tool can't find it") ("pgid", po::value(&pgidstr), - "PG id, mandatory for info, log, remove, export, rm-past-intervals, mark-complete, and mandatory for apply-layout-settings if --pool is not specified") + "PG id, mandatory for info, log, remove, export, export-remove, rm-past-intervals, mark-complete, and mandatory for apply-layout-settings if --pool is not specified") ("pool", po::value(&pool), "Pool name, mandatory for apply-layout-settings if --pgid is not specified") ("op", po::value(&op), - "Arg is one of [info, log, remove, mkfs, fsck, fuse, dup, export, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, " + "Arg is one of [info, log, remove, mkfs, fsck, fuse, dup, export, export-remove, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, " "get-osdmap, set-osdmap, get-inc-osdmap, set-inc-osdmap, mark-complete, apply-layout-settings, update-mon-db]") ("epoch", po::value(&epoch), "epoch# for get-osdmap and get-inc-osdmap, the current epoch in use if not specified") ("file", po::value(&file), - "path of file to export, import, get-osdmap, set-osdmap, get-inc-osdmap or set-inc-osdmap") + "path of file to export, export-remove, import, get-osdmap, set-osdmap, get-inc-osdmap or set-inc-osdmap") ("mon-store-path", po::value(&mon_store_path), "path of monstore to update-mon-db") ("fsid", po::value(&fsid), @@ -2597,23 +2597,15 @@ int main(int argc, char **argv) return 1; } - if (!vm.count("debug")) { - debug = false; - } else { - debug = true; - } + debug = (vm.count("debug") > 0); - if (!vm.count("force")) { - force = false; - } else { - force = true; - } + force = (vm.count("force") > 0); if (vm.count("namespace")) nspace = argnspace; - if (vm.count("dry-run")) - dry_run = true; + dry_run = (vm.count("dry-run") > 0); + osflagbits_t flags = 0; if (dry_run || vm.count("skip-journal-replay")) flags |= SKIP_JOURNAL_REPLAY; @@ -2621,6 +2613,7 @@ int main(int argc, char **argv) flags |= SKIP_MOUNT_OMAP; if (op == "update-mon-db") flags |= SKIP_JOURNAL_REPLAY; + head = (vm.count("head") > 0); vector ceph_options; @@ -2690,7 +2683,7 @@ int main(int argc, char **argv) outistty = isatty(STDOUT_FILENO); file_fd = fd_none; - if ((op == "export" || op == "get-osdmap" || op == "get-inc-osdmap") && !dry_run) { + if ((op == "export" || op == "export-remove" || op == "get-osdmap" || op == "get-inc-osdmap") && !dry_run) { if (!vm.count("file") || file == "-") { if (outistty) { cerr << "stdout is a tty and no --file filename specified" << std::endl; @@ -2715,7 +2708,7 @@ int main(int argc, char **argv) ObjectStoreTool tool = ObjectStoreTool(file_fd, dry_run); if (vm.count("file") && file_fd == fd_none && !dry_run) { - cerr << "--file option only applies to import, export, " + cerr << "--file option only applies to import, export, export-remove, " << "get-osdmap, set-osdmap, get-inc-osdmap or set-inc-osdmap" << std::endl; return 1; } @@ -3022,7 +3015,7 @@ int main(int argc, char **argv) // The ops which require --pgid option are checked here and // mentioned in the usage for --pgid. if ((op == "info" || op == "log" || op == "remove" || op == "export" - || op == "rm-past-intervals" || op == "mark-complete") && + || op == "export-remove" || op == "rm-past-intervals" || op == "mark-complete") && pgidstr.length() == 0) { cerr << "Must provide pgid" << std::endl; usage(desc); @@ -3128,6 +3121,11 @@ int main(int argc, char **argv) biginfo_oid = OSD::make_pg_biginfo_oid(pgid); if (op == "remove") { + if (!force && !dry_run) { + cerr << "Please use export-remove or you must use --force option" << std::endl; + ret = -EINVAL; + goto out; + } ret = initiate_new_remove_pg(fs, pgid, *osr); if (ret < 0) { cerr << "PG '" << pgid << "' not found" << std::endl; @@ -3220,8 +3218,8 @@ int main(int argc, char **argv) // If not an object command nor any of the ops handled below, then output this usage // before complaining about a bad pgid - if (!vm.count("objcmd") && op != "export" && op != "info" && op != "log" && op != "rm-past-intervals" && op != "mark-complete") { - cerr << "Must provide --op (info, log, remove, mkfs, fsck, export, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, " + if (!vm.count("objcmd") && op != "export" && op != "export-remove" && op != "info" && op != "log" && op != "rm-past-intervals" && op != "mark-complete") { + cerr << "Must provide --op (info, log, remove, mkfs, fsck, export, export-remove, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, " "get-osdmap, set-osdmap, get-inc-osdmap, set-inc-osdmap, mark-complete)" << std::endl; usage(desc); @@ -3495,10 +3493,17 @@ int main(int argc, char **argv) if (debug) cerr << "struct_v " << (int)struct_ver << std::endl; - if (op == "export") { + if (op == "export" || op == "export-remove") { ret = tool.do_export(fs, coll, pgid, info, map_epoch, struct_ver, superblock, past_intervals); - if (ret == 0) + if (ret == 0) { cerr << "Export successful" << std::endl; + if (op == "export-remove") { + ret = initiate_new_remove_pg(fs, pgid, *osr); + // Export succeeded, so pgid is there + assert(ret == 0); + cerr << "Remove successful" << std::endl; + } + } } else if (op == "info") { formatter->open_object_section("info"); info.dump(formatter); -- 2.39.5