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 <dzafman@redhat.com>
This commit is contained in:
David Zafman 2017-09-08 17:53:07 -07:00
parent 49ca1fff7f
commit 3bb20f6d75
6 changed files with 42 additions and 46 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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())

View File

@ -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())

View File

@ -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())

View File

@ -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;
@ -2529,16 +2529,16 @@ int main(int argc, char **argv)
("journal-path", po::value<string>(&jpath),
"path to journal, use if tool can't find it")
("pgid", po::value<string>(&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<string>(&pool),
"Pool name, mandatory for apply-layout-settings if --pgid is not specified")
("op", po::value<string>(&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<unsigned>(&epoch),
"epoch# for get-osdmap and get-inc-osdmap, the current epoch in use if not specified")
("file", po::value<string>(&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<string>(&mon_store_path),
"path of monstore to update-mon-db")
("fsid", po::value<string>(&fsid),
@ -2592,23 +2592,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;
@ -2616,6 +2608,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<const char *> ceph_options;
@ -2685,7 +2678,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;
@ -2710,7 +2703,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;
}
@ -3017,7 +3010,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);
@ -3123,6 +3116,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;
@ -3215,8 +3213,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);
@ -3490,10 +3488,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);