|
|
|
@ -21,6 +21,11 @@ typedef enum {
|
|
|
|
|
REPORT_IDX_NULL = -1,
|
|
|
|
|
REPORT_IDX_SINGLE,
|
|
|
|
|
REPORT_IDX_LOG,
|
|
|
|
|
REPORT_IDX_FULL_VGS,
|
|
|
|
|
REPORT_IDX_FULL_LVS,
|
|
|
|
|
REPORT_IDX_FULL_PVS,
|
|
|
|
|
REPORT_IDX_FULL_PVSEGS,
|
|
|
|
|
REPORT_IDX_FULL_SEGS,
|
|
|
|
|
REPORT_IDX_COUNT
|
|
|
|
|
} report_idx_t;
|
|
|
|
|
|
|
|
|
@ -48,6 +53,7 @@ struct report_args {
|
|
|
|
|
int quoted;
|
|
|
|
|
int columns_as_rows;
|
|
|
|
|
const char *separator;
|
|
|
|
|
struct volume_group *full_report_vg;
|
|
|
|
|
struct single_report_args single_args[REPORT_IDX_COUNT];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -457,7 +463,9 @@ static int _get_final_report_type(int args_are_pvs,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Change report type if fields specified makes this necessary */
|
|
|
|
|
if ((report_type & PVSEGS) ||
|
|
|
|
|
if (report_type & FULL)
|
|
|
|
|
report_type = FULL;
|
|
|
|
|
else if ((report_type & PVSEGS) ||
|
|
|
|
|
((report_type & (PVS | LABEL)) && (report_type & (LVS | LVSINFO | LVSSTATUS | LVSINFOSTATUS))))
|
|
|
|
|
report_type = PVSEGS;
|
|
|
|
|
else if ((report_type & PVS) ||
|
|
|
|
@ -829,6 +837,12 @@ static int _set_report_prefix_and_name(struct single_report_args *single_args)
|
|
|
|
|
const char *report_prefix;
|
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
|
|
if (single_args->report_type == FULL) {
|
|
|
|
|
single_args->report_prefix[0] = '\0';
|
|
|
|
|
single_args->report_name = single_args->report_prefix;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
report_prefix = report_get_field_prefix(single_args->report_type);
|
|
|
|
|
len = strlen(report_prefix);
|
|
|
|
|
if (report_prefix[len - 1] == '_')
|
|
|
|
@ -850,27 +864,24 @@ static int _set_report_prefix_and_name(struct single_report_args *single_args)
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int _do_report(struct cmd_context *cmd, struct report_args *args, struct single_report_args *single_args)
|
|
|
|
|
static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
|
|
|
|
|
struct report_args *args, struct single_report_args *single_args)
|
|
|
|
|
{
|
|
|
|
|
struct processing_handle *handle = NULL;
|
|
|
|
|
void *orig_custom_handle = handle->custom_handle;
|
|
|
|
|
report_type_t report_type = single_args->report_type;
|
|
|
|
|
void *report_handle = NULL;
|
|
|
|
|
int lock_global = 0;
|
|
|
|
|
int lv_info_needed;
|
|
|
|
|
int lv_segment_status_needed;
|
|
|
|
|
int report_in_group = 0;
|
|
|
|
|
int r = ECMD_FAILED;
|
|
|
|
|
|
|
|
|
|
if (!(handle = init_processing_handle(cmd, NULL)))
|
|
|
|
|
goto_out;
|
|
|
|
|
|
|
|
|
|
if (!(report_handle = report_init(cmd, single_args->options, single_args->keys, &report_type,
|
|
|
|
|
args->separator, args->aligned, args->buffered,
|
|
|
|
|
args->headings, args->field_prefixes, args->quoted,
|
|
|
|
|
args->columns_as_rows, single_args->selection)))
|
|
|
|
|
goto_out;
|
|
|
|
|
|
|
|
|
|
handle->internal_report_for_select = 0;
|
|
|
|
|
handle->include_historical_lvs = cmd->include_historical_lvs;
|
|
|
|
|
handle->custom_handle = report_handle;
|
|
|
|
|
|
|
|
|
|
if (!_get_final_report_type(single_args->args_are_pvs,
|
|
|
|
@ -879,8 +890,11 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args, struct
|
|
|
|
|
&report_type))
|
|
|
|
|
goto_out;
|
|
|
|
|
|
|
|
|
|
if (handle->report_group) {
|
|
|
|
|
if (!dm_report_group_push(handle->report_group, report_handle, (void *) single_args->report_name))
|
|
|
|
|
goto_out;
|
|
|
|
|
report_in_group = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We lock VG_GLOBAL to enable use of metadata cache.
|
|
|
|
@ -906,6 +920,9 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args, struct
|
|
|
|
|
case LVSINFOSTATUS:
|
|
|
|
|
/* fall through */
|
|
|
|
|
case LVS:
|
|
|
|
|
if (args->full_report_vg)
|
|
|
|
|
r = _report_all_in_vg(cmd, handle, args->full_report_vg, LVS, lv_info_needed, lv_segment_status_needed);
|
|
|
|
|
else
|
|
|
|
|
r = process_each_lv(cmd, args->argc, args->argv, NULL, NULL, 0, handle,
|
|
|
|
|
lv_info_needed && !lv_segment_status_needed ? &_lvs_with_info_single :
|
|
|
|
|
!lv_info_needed && lv_segment_status_needed ? &_lvs_with_status_single :
|
|
|
|
@ -913,6 +930,9 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args, struct
|
|
|
|
|
&_lvs_single);
|
|
|
|
|
break;
|
|
|
|
|
case VGS:
|
|
|
|
|
if (args->full_report_vg)
|
|
|
|
|
r = _report_all_in_vg(cmd, handle, args->full_report_vg, VGS, lv_info_needed, lv_segment_status_needed);
|
|
|
|
|
else
|
|
|
|
|
r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL, 0,
|
|
|
|
|
handle, &_vgs_single);
|
|
|
|
|
break;
|
|
|
|
@ -921,6 +941,9 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args, struct
|
|
|
|
|
handle, &_label_single);
|
|
|
|
|
break;
|
|
|
|
|
case PVS:
|
|
|
|
|
if (args->full_report_vg)
|
|
|
|
|
r = _report_all_in_vg(cmd, handle, args->full_report_vg, PVS, lv_info_needed, lv_segment_status_needed);
|
|
|
|
|
else {
|
|
|
|
|
if (single_args->args_are_pvs)
|
|
|
|
|
r = process_each_pv(cmd, args->argc, args->argv, NULL,
|
|
|
|
|
arg_is_set(cmd, all_ARG), 0,
|
|
|
|
@ -928,8 +951,12 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args, struct
|
|
|
|
|
else
|
|
|
|
|
r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL,
|
|
|
|
|
0, handle, &_pvs_in_vg);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SEGS:
|
|
|
|
|
if (args->full_report_vg)
|
|
|
|
|
r = _report_all_in_vg(cmd, handle, args->full_report_vg, SEGS, lv_info_needed, lv_segment_status_needed);
|
|
|
|
|
else
|
|
|
|
|
r = process_each_lv(cmd, args->argc, args->argv, NULL, NULL, 0, handle,
|
|
|
|
|
lv_info_needed && !lv_segment_status_needed ? &_lvsegs_with_info_single :
|
|
|
|
|
!lv_info_needed && lv_segment_status_needed ? &_lvsegs_with_status_single :
|
|
|
|
@ -937,6 +964,9 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args, struct
|
|
|
|
|
&_lvsegs_single);
|
|
|
|
|
break;
|
|
|
|
|
case PVSEGS:
|
|
|
|
|
if (args->full_report_vg)
|
|
|
|
|
r = _report_all_in_vg(cmd, handle, args->full_report_vg, PVSEGS, lv_info_needed, lv_segment_status_needed);
|
|
|
|
|
else {
|
|
|
|
|
if (single_args->args_are_pvs)
|
|
|
|
|
r = process_each_pv(cmd, args->argc, args->argv, NULL,
|
|
|
|
|
arg_is_set(cmd, all_ARG), 0,
|
|
|
|
@ -948,6 +978,14 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args, struct
|
|
|
|
|
else
|
|
|
|
|
r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL,
|
|
|
|
|
0, handle, &_pvsegs_in_vg);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case FULL:
|
|
|
|
|
/*
|
|
|
|
|
* Full report's subreports already covered by combinations above with args->full_report_vg.
|
|
|
|
|
* We shouldn't see report_type == FULL in this function.
|
|
|
|
|
*/
|
|
|
|
|
log_error(INTERNAL_ERROR "_do_report: full report requested at incorrect level");
|
|
|
|
|
break;
|
|
|
|
|
case CMDLOG:
|
|
|
|
|
/* Log is reported throughout the code via report_cmdlog calls. */
|
|
|
|
@ -970,13 +1008,62 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args, struct
|
|
|
|
|
if (lock_global)
|
|
|
|
|
unlock_vg(cmd, VG_GLOBAL);
|
|
|
|
|
out:
|
|
|
|
|
if (handle)
|
|
|
|
|
destroy_processing_handle(cmd, handle);
|
|
|
|
|
if (report_handle)
|
|
|
|
|
if (report_handle) {
|
|
|
|
|
if (report_in_group && !dm_report_group_pop(handle->report_group))
|
|
|
|
|
stack;
|
|
|
|
|
dm_report_free(report_handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handle->custom_handle = orig_custom_handle;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int _full_report_single(struct cmd_context *cmd,
|
|
|
|
|
const char *vg_name,
|
|
|
|
|
struct volume_group *vg,
|
|
|
|
|
struct processing_handle *handle)
|
|
|
|
|
{
|
|
|
|
|
struct report_args *args = (struct report_args *) handle->custom_handle;
|
|
|
|
|
int orphan = is_orphan_vg(vg->name);
|
|
|
|
|
int r = ECMD_FAILED;
|
|
|
|
|
|
|
|
|
|
if (orphan && !dm_list_size(&vg->pvs))
|
|
|
|
|
return ECMD_PROCESSED;
|
|
|
|
|
|
|
|
|
|
args->full_report_vg = vg;
|
|
|
|
|
|
|
|
|
|
if (!dm_report_group_push(handle->report_group, NULL, NULL))
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
if (orphan) {
|
|
|
|
|
if (((r = _do_report(cmd, handle, args, &args->single_args[REPORT_IDX_FULL_PVS])) != ECMD_PROCESSED) ||
|
|
|
|
|
((r = _do_report(cmd, handle, args, &args->single_args[REPORT_IDX_FULL_PVSEGS])) != ECMD_PROCESSED))
|
|
|
|
|
stack;
|
|
|
|
|
} else {
|
|
|
|
|
if (((r = _do_report(cmd, handle, args, &args->single_args[REPORT_IDX_FULL_VGS])) != ECMD_PROCESSED) ||
|
|
|
|
|
((r = _do_report(cmd, handle, args, &args->single_args[REPORT_IDX_FULL_PVS])) != ECMD_PROCESSED) ||
|
|
|
|
|
((r = _do_report(cmd, handle, args, &args->single_args[REPORT_IDX_FULL_LVS])) != ECMD_PROCESSED) ||
|
|
|
|
|
((r = _do_report(cmd, handle, args, &args->single_args[REPORT_IDX_FULL_PVSEGS])) != ECMD_PROCESSED) ||
|
|
|
|
|
((r = _do_report(cmd, handle, args, &args->single_args[REPORT_IDX_FULL_SEGS])) != ECMD_PROCESSED))
|
|
|
|
|
stack;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!dm_report_group_pop(handle->report_group))
|
|
|
|
|
goto_out;
|
|
|
|
|
out:
|
|
|
|
|
args->full_report_vg = NULL;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define _set_full_report_single(args,type,name) \
|
|
|
|
|
do { \
|
|
|
|
|
args->single_args[REPORT_IDX_FULL_ ## type].report_type = type; \
|
|
|
|
|
args->single_args[REPORT_IDX_FULL_ ## type].keys = DEFAULT_ ## type ## _SORT_FULL; \
|
|
|
|
|
args->single_args[REPORT_IDX_FULL_ ## type].options = DEFAULT_ ## type ## _COLS_FULL; \
|
|
|
|
|
if (!_set_report_prefix_and_name(&args->single_args[REPORT_IDX_FULL_ ## type])) \
|
|
|
|
|
return_0; \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
static int _config_report(struct cmd_context *cmd, struct report_args *args, struct single_report_args *single_args)
|
|
|
|
|
{
|
|
|
|
|
args->aligned = find_config_tree_bool(cmd, report_aligned_CFG, NULL);
|
|
|
|
@ -1037,6 +1124,13 @@ static int _config_report(struct cmd_context *cmd, struct report_args *args, str
|
|
|
|
|
else
|
|
|
|
|
single_args->options = find_config_tree_str(cmd, report_pvsegs_cols_verbose_CFG, NULL);
|
|
|
|
|
break;
|
|
|
|
|
case FULL:
|
|
|
|
|
_set_full_report_single(args, VGS, vgs);
|
|
|
|
|
_set_full_report_single(args, LVS, lvs);
|
|
|
|
|
_set_full_report_single(args, PVS, pvs);
|
|
|
|
|
_set_full_report_single(args, PVSEGS, pvsegs);
|
|
|
|
|
_set_full_report_single(args, SEGS, segs);
|
|
|
|
|
break;
|
|
|
|
|
case CMDLOG:
|
|
|
|
|
single_args->keys = find_config_tree_str(cmd, log_command_log_sort_CFG, NULL);
|
|
|
|
|
single_args->options = find_config_tree_str(cmd, log_command_log_cols_CFG, NULL);
|
|
|
|
@ -1046,6 +1140,7 @@ static int _config_report(struct cmd_context *cmd, struct report_args *args, str
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (single_args->report_type != FULL)
|
|
|
|
|
single_args->fields_to_compact = find_config_tree_str_allow_empty(cmd, report_compact_output_cols_CFG, NULL);
|
|
|
|
|
|
|
|
|
|
/* If -o supplied use it, else use default for report_type */
|
|
|
|
@ -1084,6 +1179,9 @@ static int _report(struct cmd_context *cmd, int argc, char **argv, report_type_t
|
|
|
|
|
{
|
|
|
|
|
struct report_args args = {0};
|
|
|
|
|
struct single_report_args *single_args = &args.single_args[REPORT_IDX_SINGLE];
|
|
|
|
|
static char report_name[] = "report";
|
|
|
|
|
struct processing_handle *handle;
|
|
|
|
|
int r = ECMD_FAILED;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Include foreign VGs that contain active LVs.
|
|
|
|
@ -1097,10 +1195,33 @@ static int _report(struct cmd_context *cmd, int argc, char **argv, report_type_t
|
|
|
|
|
args.argv = argv;
|
|
|
|
|
single_args->report_type = report_type;
|
|
|
|
|
|
|
|
|
|
if (!_config_report(cmd, &args, single_args))
|
|
|
|
|
if (!(handle = init_processing_handle(cmd, NULL)))
|
|
|
|
|
return_ECMD_FAILED;
|
|
|
|
|
|
|
|
|
|
return _do_report(cmd, &args, single_args);
|
|
|
|
|
handle->internal_report_for_select = 0;
|
|
|
|
|
handle->include_historical_lvs = cmd->include_historical_lvs;
|
|
|
|
|
|
|
|
|
|
args.report_group_type = handle->report_group_type;
|
|
|
|
|
|
|
|
|
|
if (!_config_report(cmd, &args, single_args)) {
|
|
|
|
|
destroy_processing_handle(cmd, handle);
|
|
|
|
|
return_ECMD_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!dm_report_group_push(handle->report_group, NULL, report_name)) {
|
|
|
|
|
log_error("Failed to add main report section to report group.");
|
|
|
|
|
destroy_processing_handle(cmd, handle);
|
|
|
|
|
return ECMD_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (single_args->report_type == FULL) {
|
|
|
|
|
handle->custom_handle = &args;
|
|
|
|
|
r = process_each_vg(cmd, argc, argv, NULL, NULL, 0, handle, &_full_report_single);
|
|
|
|
|
} else
|
|
|
|
|
r = _do_report(cmd, handle, &args, single_args);
|
|
|
|
|
|
|
|
|
|
destroy_processing_handle(cmd, handle);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int lvs(struct cmd_context *cmd, int argc, char **argv)
|
|
|
|
@ -1132,6 +1253,11 @@ int pvs(struct cmd_context *cmd, int argc, char **argv)
|
|
|
|
|
return _report(cmd, argc, argv, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int fullreport(struct cmd_context *cmd, int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
return _report(cmd, argc, argv, FULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int devtypes(struct cmd_context *cmd, int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
return _report(cmd, argc, argv, DEVTYPES);
|
|
|
|
@ -1143,7 +1269,6 @@ int devtypes(struct cmd_context *cmd, int argc, char **argv)
|
|
|
|
|
int report_format_init(struct cmd_context *cmd, dm_report_group_type_t *report_group_type,
|
|
|
|
|
struct dm_report_group **report_group, struct dm_report **log_rh)
|
|
|
|
|
{
|
|
|
|
|
static char log_report_name[] = "log";
|
|
|
|
|
int config_set = find_config_tree_node(cmd, report_output_format_CFG, NULL) != NULL;
|
|
|
|
|
const char *config_format_str = find_config_tree_str(cmd, report_output_format_CFG, NULL);
|
|
|
|
|
const char *format_str = arg_str_value(cmd, reportformat_ARG, config_set ? config_format_str : NULL);
|
|
|
|
|