diff --git a/WHATS_NEW b/WHATS_NEW index f800ecac3..6f6e9e843 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.158 - ================================= + Add lvm lastlog command for query and display of last cmd's log in lvm shell. Report per-object return codes via cmd log while processing multiple objects. Annotate processing code with log report hooks for per-object command log. Also pass common printed messages (besides warnings and errors) to log report. diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 076f48ddb..75f19c9f4 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -2247,6 +2247,9 @@ void destroy_toolcontext(struct cmd_context *cmd) if (cmd->cft_def_hash) dm_hash_destroy(cmd->cft_def_hash); + if (cmd->log_rh) + dm_report_free(cmd->log_rh); + if (cmd->libmem) dm_pool_destroy(cmd->libmem); diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index c04455c9f..ee849b5e4 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -185,6 +185,11 @@ struct cmd_context { char dev_dir[PATH_MAX]; char proc_dir[PATH_MAX]; + /* + * Command log reporting. + */ + struct dm_report *log_rh; /* keep log report of last cmd for further queries if cmd line is interactive (e.g. lvm shell) */ + /* * Buffers. */ diff --git a/tools/Makefile.in b/tools/Makefile.in index bb2917602..8dfac7fd7 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -168,7 +168,7 @@ liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION): liblvm2cmd.$(LIB_SUFFIX) .commands: $(srcdir)/commands.h $(srcdir)/cmdnames.h Makefile $(CC) -E -P $(srcdir)/cmdnames.h 2> /dev/null | \ - egrep -v '^ *(|#.*|config|devtypes|dumpconfig|formats|fullreport|help|lvpoll|pvdata|segtypes|systemid|tags|version) *$$' > .commands + egrep -v '^ *(|#.*|config|devtypes|dumpconfig|formats|fullreport|help|lastlog|lvpoll|pvdata|segtypes|systemid|tags|version) *$$' > .commands ifneq ("$(CFLOW_CMD)", "") CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) diff --git a/tools/commands.h b/tools/commands.h index 3f0fff56b..d54a50c15 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -174,6 +174,15 @@ xx(fullreport, rows_ARG, select_ARG, separator_ARG, shared_ARG, sort_ARG, trustcache_ARG, unbuffered_ARG, units_ARG, unquoted_ARG) +xx(lastlog, + "Display last command's log report", + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, + "log\n" + "\t[--reportformat {json}]\n" + "\t[-S|--select Selection]\n", + + reportformat_ARG, select_ARG) + xx(lvchange, "Change the attributes of logical volume(s)", CACHE_VGMETADATA | PERMITTED_READ_ONLY, diff --git a/tools/lvm.c b/tools/lvm.c index 18e349068..62cc14190 100644 --- a/tools/lvm.c +++ b/tools/lvm.c @@ -235,6 +235,12 @@ int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline) break; } + if (cmd->log_rh && strcmp(argv[0], "lastlog")) { + /* drop old log report */ + dm_report_free(cmd->log_rh); + cmd->log_rh = NULL; + } + ret = lvm_run_command(cmd, argc, argv); if (ret == ENO_SUCH_CMD) log_error("No such command '%s'. Try 'help'.", diff --git a/tools/reporter.c b/tools/reporter.c index 3df4baca5..c732d0ef9 100644 --- a/tools/reporter.c +++ b/tools/reporter.c @@ -1497,3 +1497,38 @@ bad: dm_report_free(tmp_log_rh); return 0; } + +int lastlog(struct cmd_context *cmd, int argc, char **argv) +{ + static report_idx_t expected_idxs[] = {REPORT_IDX_SINGLE, REPORT_IDX_LOG, REPORT_IDX_NULL}; + struct dm_report_group *report_group = NULL; + const char *selection = NULL; + int r = ECMD_FAILED; + + if (!cmd->log_rh) { + log_error("No log report stored."); + goto out; + } + + if (!report_format_init(cmd, NULL, &report_group, &cmd->log_rh, NULL)) + goto_out; + + if (arg_count(cmd, select_ARG) && + !_do_report_get_selection(cmd, NULL, NULL, expected_idxs, &selection)) + goto_out; + + if (!dm_report_set_selection(cmd->log_rh, selection)) { + log_error("Failed to set selection for log report."); + goto out; + } + + if (!dm_report_output(cmd->log_rh) || + !dm_report_group_pop(report_group)) + goto_out; + + r = ECMD_PROCESSED; +out: + if (!dm_report_group_destroy(report_group)) + stack; + return r; +} diff --git a/tools/toollib.c b/tools/toollib.c index e044cb42d..41ef5499c 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -1778,8 +1778,16 @@ void destroy_processing_handle(struct cmd_context *cmd, struct processing_handle if (!dm_report_group_destroy(handle->report_group)) stack; - if (handle->log_rh) - dm_report_free(handle->log_rh); + if (handle->log_rh) { + if (cmd->is_interactive) { + /* + * Keep log report if we're interactive so + * we can do further queries on this report. + */ + cmd->log_rh = handle->log_rh; + } else + dm_report_free(handle->log_rh); + } /* * TODO: think about better alternatives: * handle mempool, dm_alloc for handle memory...