From: Peter Rajnoha (@prajnoha) <gitlab@mg.gitlab.com>
To: lvm-devel@redhat.com
Subject: [Git][lvmteam/lvm2][main] 6 commits: libdm: report: support reporting field IDs in headings
Date: Wed, 30 Aug 2023 10:07:51 +0000 [thread overview]
Message-ID: <64ef14f7b4d19_28a85985948@gitlab-sidekiq-low-urgency-cpu-bound-v2-5d49b59bf-67mgj.mail> (raw)
Peter Rajnoha pushed to branch main at LVM team / lvm2
Commits:
12b60e7c by Peter Rajnoha at 2023-08-28T15:44:57+02:00
libdm: report: support reporting field IDs in headings
Add new DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS report output flag.
If enabled, column IDs are reported instead of column names in report
headings.
The 'column IDs' are IDs as found in 'const struct dm_report_field_type *fields'
array that is passed during report initialization (that is, a call to
dm_report_init/dm_report_init_with_selection). In this case, the 'id'
dm_report_field_type member is used instead of the 'heading' member.
- - - - -
14d0a9ee by Peter Rajnoha at 2023-08-28T15:44:57+02:00
report: support printing full column names in report headings
Reuse existing report/headings config setting to make it possible to
change the type of headings to display:
0 - no headings
1 - column name abbreviations (default and original functionality)
2 - full column names (column names are equal to exact names that
-o|--options also accepts to set report output)
Also, add '--headings none|abbrev|full|0|1|2' command line option
so we are able to select the heading type for each LVM reporting
command directly.
- - - - -
5a1248f1 by Peter Rajnoha at 2023-08-28T15:44:57+02:00
dmsetup: support printing full column names in report headings
Add '--headings none|abbrev|full|0|1|2' command line option to select
the heading type.
none|0 - no headings
abbrev|1 - column name abbreviations
full|2 - full column names (column names are equal to exact names
that -o|--options also accepts to set report output)
- - - - -
5a6d1369 by Peter Rajnoha at 2023-08-28T15:44:58+02:00
make: generate
- - - - -
2ab2da5e by Peter Rajnoha at 2023-08-28T15:44:58+02:00
man: update lvmreport man page about report/headings and --headings
- - - - -
1f02c5f2 by Peter Rajnoha at 2023-08-28T15:44:58+02:00
tests: add shell/report-headings.sh
- - - - -
25 changed files:
- WHATS_NEW
- WHATS_NEW_DM
- conf/example.conf.in
- device_mapper/all.h
- device_mapper/libdm-report.c
- lib/config/config_settings.h
- lib/report/report.c
- lib/report/report.h
- libdm/dm-tools/dmsetup.c
- libdm/libdevmapper.h
- libdm/libdm-report.c
- man/dmsetup.8_main
- man/lvm-fullreport.8_pregen
- man/lvmreport.7_main
- man/lvs.8_pregen
- man/pvs.8_pregen
- man/vgs.8_pregen
- + test/shell/report-headings.sh
- tools/args.h
- tools/command-lines.in
- tools/command.c
- tools/lvmcmdline.c
- tools/reporter.c
- tools/tools.h
- tools/vals.h
Changes:
=====================================
WHATS_NEW
=====================================
@@ -1,5 +1,7 @@
version 2.03.23 -
==================================
+ Recognize lvm.conf report/headings=2 for full column names in report headings.
+ Add --headings none|abbrev|full cmd line option to set report headings type.
Require writable LV for convertion to vdo pool.
Fix return value from lvconvert integrity remove.
Preserve UUID for pool metadata spare.
=====================================
WHATS_NEW_DM
=====================================
@@ -1,5 +1,7 @@
Version 1.02.197 -
===================================
+ Add dmsetup --headings none|abbrev|full to set report headings type.
+ Add DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS to provide alternative headings.
Version 1.02.196 - 02nd August 2023
===================================
=====================================
conf/example.conf.in
=====================================
@@ -2017,7 +2017,11 @@ activation {
# buffered = 1
# Configuration option report/headings.
- # Show headings for columns on report.
+ # Format of LVM command's report output headings.
+ # Accepted values:
+ # 0 no headings,
+ # 1 headings with column abbreviations,
+ # 2 headings with full column names.
# This configuration option has an automatic default value.
# headings = 1
=====================================
device_mapper/all.h
=====================================
@@ -1875,6 +1875,7 @@ const void *dm_report_value_cache_get(struct dm_report *rh, const char *name);
#define DM_REPORT_OUTPUT_FIELD_UNQUOTED 0x00000010
#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS 0x00000020
#define DM_REPORT_OUTPUT_MULTIPLE_TIMES 0x00000040
+#define DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS 0x00000080
struct dm_report *dm_report_init(uint32_t *report_types,
const struct dm_report_object_type *types,
=====================================
device_mapper/libdm-report.c
=====================================
@@ -4263,7 +4263,9 @@ static int _report_headings(struct dm_report *rh)
fields = fp->implicit ? _implicit_report_fields : rh->fields;
- heading = fields[fp->field_num].heading;
+ heading = rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS ?
+ fields[fp->field_num].id : fields[fp->field_num].heading;
+
if (rh->flags & DM_REPORT_OUTPUT_ALIGNED) {
if (dm_snprintf(buf, buf_size, "%-*.*s",
fp->width, fp->width, heading) < 0) {
@@ -4315,6 +4317,7 @@ static void _recalculate_fields(struct dm_report *rh)
struct row *row;
struct dm_report_field *field;
int len;
+ size_t id_len;
dm_list_iterate_items(row, &rh->rows) {
dm_list_iterate_items(field, &row->fields) {
@@ -4329,6 +4332,12 @@ static void _recalculate_fields(struct dm_report *rh)
field->props->width = len;
}
+
+ if (rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS) {
+ id_len = strlen(rh->fields[field->props->field_num].id);
+ if (field->props->width < id_len)
+ field->props->width = id_len;
+ }
}
}
@@ -4740,6 +4749,7 @@ static int _output_as_rows(struct dm_report *rh)
struct field_properties *fp;
struct dm_report_field *field;
struct row *row;
+ const char *heading;
dm_list_iterate_items(fp, &rh->field_props) {
if (fp->flags & FLD_HIDDEN) {
@@ -4758,7 +4768,10 @@ static int _output_as_rows(struct dm_report *rh)
}
if ((rh->flags & DM_REPORT_OUTPUT_HEADINGS)) {
- if (!dm_pool_grow_object(rh->mem, fields[fp->field_num].heading, 0)) {
+ heading = rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS ?
+ fields[fp->field_num].id : fields[fp->field_num].heading;
+
+ if (!dm_pool_grow_object(rh->mem, heading, 0)) {
log_error("dm_report: Failed to extend row for field name");
goto bad;
}
=====================================
lib/config/config_settings.h
=====================================
@@ -1863,8 +1863,12 @@ cfg(report_buffered_CFG, "buffered", report_CFG_SECTION, CFG_PROFILABLE | CFG_DE
"execution. Otherwise, if buffering is not used, each object is\n"
"reported as soon as its processing is finished.\n")
-cfg(report_headings_CFG, "headings", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REP_HEADINGS, vsn(1, 0, 0), NULL, 0, NULL,
- "Show headings for columns on report.\n")
+cfg(report_headings_CFG, "headings", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_REP_HEADINGS, vsn(1, 0, 0), NULL, 0, NULL,
+ "Format of LVM command's report output headings.\n"
+ "Accepted values:\n"
+ " 0 no headings,\n"
+ " 1 headings with column abbreviations,\n"
+ " 2 headings with full column names.\n")
cfg(report_separator_CFG, "separator", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_REP_SEPARATOR, vsn(1, 0, 0), NULL, 0, NULL,
"A separator to use on report after each field.\n")
=====================================
lib/report/report.c
=====================================
@@ -4421,11 +4421,28 @@ static const struct dm_report_field_type _log_fields[] = {
#undef SNUM
#undef FIELD
+report_headings_t report_headings_str_to_type(const char *str)
+{
+ if (!str || !*str)
+ return REPORT_HEADINGS_UNKNOWN;
+
+ if (!strcmp(str, "none") || !strcmp(str, "0"))
+ return REPORT_HEADINGS_NONE;
+
+ if (!strcmp(str, "abbrev") || !strcmp(str, "1"))
+ return REPORT_HEADINGS_ABBREV;
+
+ if (!strcmp(str, "full") || !strcmp(str, "2"))
+ return REPORT_HEADINGS_FULL;
+
+ return REPORT_HEADINGS_UNKNOWN;
+}
+
void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
report_type_t *report_type, const char *separator,
- int aligned, int buffered, int headings, int field_prefixes,
- int quoted, int columns_as_rows, const char *selection,
- int multiple_output)
+ int aligned, int buffered, report_headings_t headings,
+ int field_prefixes, int quoted, int columns_as_rows,
+ const char *selection, int multiple_output)
{
uint32_t report_flags = 0;
const struct dm_report_object_type *types;
@@ -4439,8 +4456,12 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
if (buffered)
report_flags |= DM_REPORT_OUTPUT_BUFFERED;
- if (headings)
+ if (headings) {
+ /* any out of bound headings type value maps to REPORT_HEADINGS_ABBREV */
report_flags |= DM_REPORT_OUTPUT_HEADINGS;
+ if (headings == REPORT_HEADINGS_FULL)
+ report_flags |= DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS;
+ }
if (field_prefixes)
report_flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
=====================================
lib/report/report.h
=====================================
@@ -35,6 +35,13 @@ typedef enum {
DEVTYPES = 2048
} report_type_t;
+typedef enum {
+ REPORT_HEADINGS_UNKNOWN = -1,
+ REPORT_HEADINGS_NONE = 0,
+ REPORT_HEADINGS_ABBREV = 1,
+ REPORT_HEADINGS_FULL = 2
+} report_headings_t;
+
/*
* The "struct selection_handle" is used only for selection
* of items that should be processed further (not for display!).
@@ -81,13 +88,15 @@ struct processing_handle;
typedef int (*field_report_fn) (struct report_handle * dh, struct field * field,
const void *data);
+report_headings_t report_headings_str_to_type(const char *str);
+
int report_format_init(struct cmd_context *cmd);
void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
report_type_t *report_type, const char *separator,
- int aligned, int buffered, int headings, int field_prefixes,
- int quoted, int columns_as_rows, const char *selection,
- int multiple_output);
+ int aligned, int buffered, report_headings_t headings,
+ int field_prefixes, int quoted, int columns_as_rows,
+ const char *selection, int multiple_output);
int report_get_single_selection(struct cmd_context *cmd, report_type_t report_type, const char **selection);
void *report_init_for_selection(struct cmd_context *cmd, report_type_t *report_type,
const char *selection);
=====================================
libdm/dm-tools/dmsetup.c
=====================================
@@ -178,6 +178,7 @@ enum {
GID_ARG,
GROUP_ARG,
GROUP_ID_ARG,
+ HEADINGS_ARG,
HELP_ARG,
HISTOGRAM_ARG,
INACTIVE_ARG,
@@ -4775,6 +4776,11 @@ static int _report_init(const struct command *cmd, const char *subcommand)
_report_type |= DR_STATS_META;
}
+ if (_switches[NOHEADINGS_ARG] && _switches[HEADINGS_ARG]) {
+ log_error("Only one of --headings and --noheadings permitted.");
+ return 0;
+ }
+
/* emulate old dmsetup behaviour */
if (_switches[NOHEADINGS_ARG]) {
separator = ":";
@@ -4782,6 +4788,9 @@ static int _report_init(const struct command *cmd, const char *subcommand)
headings = 0;
}
+ if (_switches[HEADINGS_ARG])
+ headings = _int_args[HEADINGS_ARG];
+
if (_switches[UNBUFFERED_ARG])
buffered = 0;
@@ -4848,8 +4857,11 @@ static int _report_init(const struct command *cmd, const char *subcommand)
if (buffered)
flags |= DM_REPORT_OUTPUT_BUFFERED;
- if (headings)
+ if (headings) {
flags |= DM_REPORT_OUTPUT_HEADINGS;
+ if (headings == 2)
+ flags |= DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS;
+ }
if (field_prefixes)
flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
@@ -6166,7 +6178,8 @@ static int _stats_help(CMD_ARGS);
* [--units <u>] [--programid <id>] [--regionid <id>]
* [-o <fields>] [-O|--sort <sort_fields>]
* [-S|--select <selection>] [--nameprefixes]
- * [--noheadings] [--separator <separator>]
+ * [--noheadings|--headings none|abbrev|full|0|1|2]
+ * [--separator <separator>]
* [--allprograms|--programid id] [<device>...]
* ungroup --groupid <id> [--allprograms|--programid id]
* [--alldevices|<device>...]
@@ -6336,7 +6349,8 @@ static void _dmsetup_usage(FILE *out)
" [--udevcookie <cookie>] [--noudevrules] [--noudevsync] [--verifyudev]\n"
" [-y|--yes] [--readahead {[+]<sectors>|auto|none}] [--retry]\n"
" [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>]\n"
- " [-S|--select <selection>] [--nameprefixes] [--noheadings]\n"
+ " [-S|--select <selection>] [--nameprefixes]\n"
+ " [--noheadings|--headings none|abbrev|full|0|1|2]\n"
" [--separator <separator>]\n\n",
_base_commands[_base_command].name);
@@ -6866,6 +6880,7 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
{"gid", 1, &ind, GID_ARG},
{"group", 0, &ind, GROUP_ARG},
{"groupid", 1, &ind, GROUP_ID_ARG},
+ {"headings", 1, &ind, HEADINGS_ARG},
{"help", 0, &ind, HELP_ARG},
{"histogram", 0, &ind, HISTOGRAM_ARG},
{"inactive", 0, &ind, INACTIVE_ARG},
@@ -7170,6 +7185,19 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
_switches[EXEC_ARG]++;
_command_to_exec = optarg;
}
+ if (ind == HEADINGS_ARG) {
+ _switches[HEADINGS_ARG]++;
+ if (!strcasecmp(optarg, "none") || !strcmp(optarg, "0"))
+ _int_args[HEADINGS_ARG] = 0;
+ else if (!strcasecmp(optarg, "abbrev") || !strcmp(optarg, "1"))
+ _int_args[HEADINGS_ARG] = 1;
+ else if (!strcasecmp(optarg, "full") || !strcmp(optarg, "2"))
+ _int_args[HEADINGS_ARG] = 2;
+ else {
+ log_error("Unknown headings type.");
+ return 0;
+ }
+ }
if (ind == TARGET_ARG) {
_switches[TARGET_ARG]++;
_target = optarg;
=====================================
libdm/libdevmapper.h
=====================================
@@ -3058,6 +3058,7 @@ const void *dm_report_value_cache_get(struct dm_report *rh, const char *name);
#define DM_REPORT_OUTPUT_FIELD_UNQUOTED 0x00000010
#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS 0x00000020
#define DM_REPORT_OUTPUT_MULTIPLE_TIMES 0x00000040
+#define DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS 0x00000080
struct dm_report *dm_report_init(uint32_t *report_types,
const struct dm_report_object_type *types,
=====================================
libdm/libdm-report.c
=====================================
@@ -4262,7 +4262,9 @@ static int _report_headings(struct dm_report *rh)
fields = fp->implicit ? _implicit_report_fields : rh->fields;
- heading = fields[fp->field_num].heading;
+ heading = rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS ?
+ fields[fp->field_num].id : fields[fp->field_num].heading;
+
if (rh->flags & DM_REPORT_OUTPUT_ALIGNED) {
if (dm_snprintf(buf, buf_size, "%-*.*s",
fp->width, fp->width, heading) < 0) {
@@ -4314,6 +4316,7 @@ static void _recalculate_fields(struct dm_report *rh)
struct row *row;
struct dm_report_field *field;
int len;
+ size_t id_len;
dm_list_iterate_items(row, &rh->rows) {
dm_list_iterate_items(field, &row->fields) {
@@ -4328,6 +4331,12 @@ static void _recalculate_fields(struct dm_report *rh)
field->props->width = len;
}
+
+ if (rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS) {
+ id_len = strlen(rh->fields[field->props->field_num].id);
+ if (field->props->width < id_len)
+ field->props->width = id_len;
+ }
}
}
@@ -4739,6 +4748,7 @@ static int _output_as_rows(struct dm_report *rh)
struct field_properties *fp;
struct dm_report_field *field;
struct row *row;
+ const char *heading;
dm_list_iterate_items(fp, &rh->field_props) {
if (fp->flags & FLD_HIDDEN) {
@@ -4757,7 +4767,10 @@ static int _output_as_rows(struct dm_report *rh)
}
if ((rh->flags & DM_REPORT_OUTPUT_HEADINGS)) {
- if (!dm_pool_grow_object(rh->mem, fields[fp->field_num].heading, 0)) {
+ heading = rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS ?
+ fields[fp->field_num].id : fields[fp->field_num].heading;
+
+ if (!dm_pool_grow_object(rh->mem, heading, 0)) {
log_error("dm_report: Failed to extend row for field name");
goto bad;
}
=====================================
man/dmsetup.8_main
=====================================
@@ -91,6 +91,7 @@ dmsetup \(em low level logical volume management
. IR fields ]
. RB [ -O | --sort
. IR sort_fields ]
+. RB [ --idsinheadings ]
. RB [ --nameprefixes ]
. RB [ --separator
. IR separator ]
@@ -502,6 +503,10 @@ Specify the minor number.
When creating a device, don't load any table.
.
.TP
+.B --idsinheadings
+Show column identifiers instead of names in report output headings.
+.
+.TP
.B --nameprefixes
Add a "DM_" prefix plus the field name to the output. Useful with
\fB--noheadings\fP to produce a list of
=====================================
man/lvm-fullreport.8_pregen
=====================================
@@ -43,6 +43,8 @@ if information changes between commands.
.br
[ \fB--foreign\fP ]
.br
+[ \fB--headings\fP \fBnone\fP|\fBabbrev\fP|\fBfull\fP|\fB0\fP|\fB1\fP|\fB2\fP ]
+.br
[ \fB--ignorelockingfailure\fP ]
.br
[ \fB--logonly\fP ]
@@ -196,6 +198,14 @@ Report/display foreign VGs that would otherwise be skipped.
See \fBlvmsystemid\fP(7) for more information about foreign VGs.
.
.HP
+\fB--headings\fP \fBnone\fP|\fBabbrev\fP|\fBfull\fP|\fB0\fP|\fB1\fP|\fB2\fP
+.br
+Type of headings to use in report output.
+\fBnone\fP or \fB0\fP: No headings.
+\fBabbrev\fP or \fB1\fP: Column name abbreviations.
+\fBfull\fP or \fB2\fP: Full column names.
+.
+.HP
\fB-h\fP|\fB--help\fP
.br
Display help text.
=====================================
man/lvmreport.7_main
=====================================
@@ -181,12 +181,15 @@ Overrides report/aligned configuration setting.
.TP
.B --binary
Overrides report/binary_values_as_numeric configuration setting.
+TP
+.B --headings
+Overrides report/headings congiguration settings.
.TP
.B --nameprefixes
Overrides report/prefixes configuration setting.
.TP
.B --noheadings
-Overrides report/noheadings configuration setting.
+Overrides report/headings configuration setting.
.TP
.B --nosuffix
Overrides global/suffix configuration setting.
@@ -1298,6 +1301,26 @@ binary_values_as_numeric=1
lvol1 4.00m 100.00 1
lvol0 4.00m 1
.fi
+.P
+In certain cases, you may find it more useful to report full column names
+instead of abbreviated column names in report headings. To do this, use
+\fBreport/headings=2\fP configuration setting (or \fB--headings full\fP
+or \fB--headings 2\fP command line option). The full column names are
+the exact names that you also use in \fIFieldSet\fP for \fB-o|--options\fP.
+These names are unambiguous, without spaces (one word only) and they also
+make it easier to match the output with requested \fIFieldSet\fP:
+.P
+.nf
+# lvs -o+seg_start,seg_start_pe
+ LV VG LSize Cpy%Sync Start Start
+ lvol0 vg 4.00m 0 0
+ lvol1 vg 4.00m 100.00 0 0
+
+# lvs --headings full -o+seg_start,seg_start_pe
+ lv_name vg_name lv_size copy_percent seg_start seg_start_pe
+ lvol0 vg 4.00m 0 0
+ lvol1 vg 4.00m 100.00 0 0
+.fi
.
.SS Changing output format
.
=====================================
man/lvs.8_pregen
=====================================
@@ -43,6 +43,8 @@ lvs produces formatted output about LVs.
.br
[ \fB--foreign\fP ]
.br
+[ \fB--headings\fP \fBnone\fP|\fBabbrev\fP|\fBfull\fP|\fB0\fP|\fB1\fP|\fB2\fP ]
+.br
[ \fB--ignorelockingfailure\fP ]
.br
[ \fB--logonly\fP ]
@@ -199,6 +201,14 @@ Report/display foreign VGs that would otherwise be skipped.
See \fBlvmsystemid\fP(7) for more information about foreign VGs.
.
.HP
+\fB--headings\fP \fBnone\fP|\fBabbrev\fP|\fBfull\fP|\fB0\fP|\fB1\fP|\fB2\fP
+.br
+Type of headings to use in report output.
+\fBnone\fP or \fB0\fP: No headings.
+\fBabbrev\fP or \fB1\fP: Column name abbreviations.
+\fBfull\fP or \fB2\fP: Full column names.
+.
+.HP
\fB-h\fP|\fB--help\fP
.br
Display help text.
=====================================
man/pvs.8_pregen
=====================================
@@ -41,6 +41,8 @@ pvs produces formatted output about PVs.
.br
[ \fB--foreign\fP ]
.br
+[ \fB--headings\fP \fBnone\fP|\fBabbrev\fP|\fBfull\fP|\fB0\fP|\fB1\fP|\fB2\fP ]
+.br
[ \fB--ignorelockingfailure\fP ]
.br
[ \fB--logonly\fP ]
@@ -196,6 +198,14 @@ Report/display foreign VGs that would otherwise be skipped.
See \fBlvmsystemid\fP(7) for more information about foreign VGs.
.
.HP
+\fB--headings\fP \fBnone\fP|\fBabbrev\fP|\fBfull\fP|\fB0\fP|\fB1\fP|\fB2\fP
+.br
+Type of headings to use in report output.
+\fBnone\fP or \fB0\fP: No headings.
+\fBabbrev\fP or \fB1\fP: Column name abbreviations.
+\fBfull\fP or \fB2\fP: Full column names.
+.
+.HP
\fB-h\fP|\fB--help\fP
.br
Display help text.
=====================================
man/vgs.8_pregen
=====================================
@@ -39,6 +39,8 @@ vgs produces formatted output about VGs.
.br
[ \fB--foreign\fP ]
.br
+[ \fB--headings\fP \fBnone\fP|\fBabbrev\fP|\fBfull\fP|\fB0\fP|\fB1\fP|\fB2\fP ]
+.br
[ \fB--ignorelockingfailure\fP ]
.br
[ \fB--logonly\fP ]
@@ -193,6 +195,14 @@ Report/display foreign VGs that would otherwise be skipped.
See \fBlvmsystemid\fP(7) for more information about foreign VGs.
.
.HP
+\fB--headings\fP \fBnone\fP|\fBabbrev\fP|\fBfull\fP|\fB0\fP|\fB1\fP|\fB2\fP
+.br
+Type of headings to use in report output.
+\fBnone\fP or \fB0\fP: No headings.
+\fBabbrev\fP or \fB1\fP: Column name abbreviations.
+\fBfull\fP or \fB2\fP: Full column names.
+.
+.HP
\fB-h\fP|\fB--help\fP
.br
Display help text.
=====================================
test/shell/report-headings.sh
=====================================
@@ -0,0 +1,130 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2023 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux prepare_pvs 1
+
+aux lvmconf 'log/prefix=""'
+aux lvmconf 'report/compact_output=0'
+aux lvmconf 'report/compact_output_cols=""'
+
+OPTS="ba_start,seg_start,seg_start_pe"
+
+aux lvmconf 'report/headings=0'
+
+pvs -o $OPTS > out
+not grep "BA Start Start Start" out
+not grep "pv_ba_start seg_start seg_start_pe" out
+
+
+aux lvmconf 'report/headings=1'
+
+pvs -o $OPTS > out
+grep "BA Start Start Start" out
+
+pvs --headings 1 -o $OPTS > out
+grep "BA Start Start Start" out
+
+pvs --headings abbrev -o $OPTS > out
+grep "BA Start Start Start" out
+
+pvs --headings 2 -o $OPTS > out
+grep "pv_ba_start seg_start seg_start_pe" out
+
+pvs --headings full -o $OPTS > out
+grep "pv_ba_start seg_start seg_start_pe" out
+
+pvs --headings none -o $OPTS > out
+not grep "BA Start Start Start" out
+not grep "pv_ba_start seg_start seg_start_pe" out
+
+pvs --rows -o $OPTS > out
+grep "BA Start 0" out
+grep "Start 0" out
+
+pvs --rows --headings 1 -o $OPTS > out
+grep "BA Start" out
+grep "Start 0" out;
+
+pvs --rows --headings abbrev -o $OPTS > out
+grep "BA Start" out
+grep "Start 0" out;
+
+pvs --rows --headings 2 -o $OPTS > out
+grep "pv_ba_start 0" out
+grep "seg_start 0" out
+grep "seg_start_pe 0" out
+
+pvs --rows --headings full -o $OPTS > out
+grep "pv_ba_start 0" out
+grep "seg_start 0" out
+grep "seg_start_pe 0" out
+
+
+aux lvmconf 'report/headings=2'
+
+pvs -o $OPTS > out
+grep "pv_ba_start seg_start seg_start_pe" out
+
+pvs --headings 1 -o $OPTS > out
+grep "BA Start Start Start" out
+
+pvs --headings abbrev -o $OPTS > out
+grep "BA Start Start Start" out
+
+pvs --headings 2 -o $OPTS > out
+grep "pv_ba_start seg_start seg_start_pe" out
+
+pvs --headings full -o $OPTS > out
+grep "pv_ba_start seg_start seg_start_pe" out
+
+pvs --rows -o $OPTS > out
+grep "pv_ba_start 0" out
+grep "seg_start 0" out
+grep "seg_start_pe 0" out
+
+pvs --rows --headings 1 -o $OPTS > out
+grep "BA Start" out
+grep "Start 0" out;
+
+pvs --rows --headings abbrev -o $OPTS > out
+grep "BA Start" out
+grep "Start 0" out;
+
+pvs --rows --headings 2 -o $OPTS > out
+grep "pv_ba_start 0" out
+grep "seg_start 0" out
+grep "seg_start_pe 0" out
+
+pvs --rows --headings full -o $OPTS > out
+grep "pv_ba_start 0" out
+grep "seg_start 0" out
+grep "seg_start_pe 0" out
+
+
+# if report/headings=100 (out of bound value), then it is as if "1" was used
+aux lvmconf 'report/headings=100'
+
+pvs -o $OPTS > out
+grep "BA Start Start Start" out
+
+
+# if using --nameprefixes, the report/headings=2 is ignored
+pvs --headings 2 --nameprefixes -o $OPTS > out
+grep "LVM2_PV_BA_START='0 ' LVM2_SEG_START='0 ' LVM2_SEG_START_PE='0'" out
+
+# --noheadings and --headings not allowed
+not pvs --headings 1 --noheadings
=====================================
tools/args.h
=====================================
@@ -334,6 +334,12 @@ arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", 0, 0, 0,
"Allows a polling operation to continue when PVs are missing,\n"
"e.g. for repairs due to faulty devices.\n")
+arg(headings_ARG, '\0', "headings", headings_VAL, 0, 0,
+ "Type of headings to use in report output.\n"
+ "\\fBnone\\fP or \\fB0\\fP: No headings.\n"
+ "\\fBabbrev\\fP or \\fB1\\fP: Column name abbreviations.\n"
+ "\\fBfull\\fP or \\fB2\\fP: Full column names.\n")
+
arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", 0, 0, 0,
"Exclude advanced configuration settings from the output.\n")
=====================================
tools/command-lines.in
=====================================
@@ -210,7 +210,7 @@ OO_ALL: --commandprofile String, --config String, --debug,
# options for pvs, lvs, vgs, fullreport
#
OO_REPORT: --aligned, --all, --binary, --configreport ConfigReport, --foreign,
---ignorelockingfailure, --logonly,
+--headings HeadingsType --ignorelockingfailure, --logonly,
--nameprefixes, --noheadings, --nosuffix,
--options String, --readonly, --reportformat ReportFmt, --rows,
--select String, --separator String, --shared, --sort String,
@@ -1531,6 +1531,7 @@ OO: --history, --segments, OO_REPORT
OP: VG|LV|Tag ...
IO: --partial, --ignoreskippedcluster, --trustcache
ID: lvs_general
+RULE: --noheadings not --headings
---
@@ -1644,6 +1645,7 @@ OO: --segments, OO_REPORT
OP: PV|Tag ...
IO: --partial, --ignoreskippedcluster, --trustcache
ID: pvs_general
+RULE: --noheadings not --headings
---
@@ -1952,6 +1954,7 @@ OO: OO_REPORT
OP: VG|Tag ...
IO: --partial, --ignoreskippedcluster, --trustcache
ID: vgs_general
+RULE: --noheadings not --headings
---
@@ -2007,6 +2010,7 @@ OO: OO_REPORT
OP: VG ...
IO: --partial, --ignoreskippedcluster, --trustcache
ID: fullreport_general
+RULE: --noheadings not --headings
lastlog
OO: --reportformat ReportFmt, --select String
=====================================
tools/command.c
=====================================
@@ -126,6 +126,7 @@ static inline int configreport_arg(struct cmd_context *cmd __attribute__((unused
static inline int configtype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
static inline int repairtype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
static inline int dumptype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int headings_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
/* needed to include commands.h when building man page generator */
#define CACHE_VGMETADATA 0x00000001
=====================================
tools/lvmcmdline.c
=====================================
@@ -1136,6 +1136,11 @@ int dumptype_arg(struct cmd_context *cmd, struct arg_values *av)
return 0;
}
+int headings_arg(struct cmd_context *cmd, struct arg_values *av)
+{
+ return report_headings_str_to_type(av->value) != REPORT_HEADINGS_UNKNOWN;
+}
+
/*
* FIXME: there's been a confusing mixup among:
* resizeable, resizable, allocatable, allocation.
=====================================
tools/reporter.c
=====================================
@@ -48,9 +48,9 @@ struct report_args {
char **argv;
dm_report_group_type_t report_group_type;
report_type_t report_type;
+ report_headings_t headings;
int aligned;
int buffered;
- int headings;
int field_prefixes;
int quoted;
int columns_as_rows;
@@ -1247,9 +1247,11 @@ out:
static int _config_report(struct cmd_context *cmd, struct report_args *args, struct single_report_args *single_args)
{
+ const char *str;
+
args->aligned = find_config_tree_bool(cmd, report_aligned_CFG, NULL);
args->buffered = find_config_tree_bool(cmd, report_buffered_CFG, NULL);
- args->headings = find_config_tree_bool(cmd, report_headings_CFG, NULL);
+ args->headings = find_config_tree_int(cmd, report_headings_CFG, NULL);
args->separator = find_config_tree_str(cmd, report_separator_CFG, NULL);
args->field_prefixes = find_config_tree_bool(cmd, report_prefixes_CFG, NULL);
args->quoted = find_config_tree_bool(cmd, report_quoted_CFG, NULL);
@@ -1344,7 +1346,13 @@ static int _config_report(struct cmd_context *cmd, struct report_args *args, str
if (arg_is_set(cmd, unbuffered_ARG) && !arg_is_set(cmd, sort_ARG))
args->buffered = 0;
if (arg_is_set(cmd, noheadings_ARG))
- args->headings = 0;
+ args->headings = REPORT_HEADINGS_NONE;
+ if ((str = arg_str_value(cmd, headings_ARG, NULL))) {
+ if ((args->headings = report_headings_str_to_type(str)) == REPORT_HEADINGS_UNKNOWN) {
+ log_error("Unknown --headings value.");
+ return 0;
+ }
+ }
if (arg_is_set(cmd, nameprefixes_ARG)) {
args->aligned = 0;
args->field_prefixes = 1;
=====================================
tools/tools.h
=====================================
@@ -191,6 +191,7 @@ int configreport_arg(struct cmd_context *cmd __attribute__((unused)), struct arg
int configtype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
int repairtype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
int dumptype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
+int headings_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
/* we use the enums to access the switches */
int arg_is_valid_for_command(const struct cmd_context *cmd, int a);
=====================================
tools/vals.h
=====================================
@@ -143,6 +143,7 @@ val(configreport_VAL, configreport_arg, "ConfigReport", "log|vg|lv|pv|pvseg|seg"
val(configtype_VAL, configtype_arg, "ConfigType", "current|default|diff|full|list|missing|new|profilable|profilable-command|profilable-metadata")
val(repairtype_VAL, repairtype_arg, "RepairType", "pv_header|metadata|label_header")
val(dumptype_VAL, dumptype_arg, "DumpType", "headers|metadata|metadata_all|metadata_search")
+val(headings_VAL, headings_arg, "HeadingsType", "none|abbrev|full|0|1|2")
/* this should always be last */
val(VAL_COUNT, NULL, NULL, NULL)
View it on GitLab: https://gitlab.com/lvmteam/lvm2/-/compare/c4b42e9f59c93c75c96d4e31cb87d3a29d1c005f...1f02c5f2e4bc1c8871d1a0943a6e859fa86c02fa
--
View it on GitLab: https://gitlab.com/lvmteam/lvm2/-/compare/c4b42e9f59c93c75c96d4e31cb87d3a29d1c005f...1f02c5f2e4bc1c8871d1a0943a6e859fa86c02fa
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/lvm-devel/attachments/20230830/706d4971/attachment-0001.htm>
reply other threads:[~2023-08-30 10:07 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=64ef14f7b4d19_28a85985948@gitlab-sidekiq-low-urgency-cpu-bound-v2-5d49b59bf-67mgj.mail \
--to=gitlab@mg.gitlab.com \
--cc=lvm-devel@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).