Colorize zpool status output
If the ZFS_COLOR env variable is set, then use ANSI color output in zpool status: - Column headers are bold - Degraded or offline pools/vdevs are yellow - Non-zero error counters and faulted vdevs/pools are red - The 'status:' and 'action:' sections are yellow if they're displaying a warning. This also includes a new 'faketty' function in libtest.shlib that is compatible with FreeBSD (code provided by @freqlabs). Reviewed-by: Jorgen Lundman <lundman@lundman.net> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Ryan Moeller <ryan@ixsystems.com> Signed-off-by: Tony Hutter <hutter2@llnl.gov> Closes #9340
This commit is contained in:
parent
5e8ac05590
commit
9fb2771aa5
cmd/zpool
include
lib/libzfs
man/man8
tests
runfiles
zfs-tests
|
@ -2033,6 +2033,28 @@ print_status_trim(vdev_stat_t *vs, boolean_t verbose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the color associated with a health string. This includes returning
|
||||||
|
* NULL for no color change.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
health_str_to_color(const char *health)
|
||||||
|
{
|
||||||
|
if (strcmp(health, gettext("FAULTED")) == 0 ||
|
||||||
|
strcmp(health, gettext("SUSPENDED")) == 0 ||
|
||||||
|
strcmp(health, gettext("UNAVAIL")) == 0) {
|
||||||
|
return (ANSI_RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(health, gettext("OFFLINE")) == 0 ||
|
||||||
|
strcmp(health, gettext("DEGRADED")) == 0 ||
|
||||||
|
strcmp(health, gettext("REMOVED")) == 0) {
|
||||||
|
return (ANSI_YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print out configuration state as requested by status_callback.
|
* Print out configuration state as requested by status_callback.
|
||||||
*/
|
*/
|
||||||
|
@ -2051,6 +2073,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
|
||||||
const char *state;
|
const char *state;
|
||||||
char *type;
|
char *type;
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
char *rcolor = NULL, *wcolor = NULL, *ccolor = NULL;
|
||||||
|
|
||||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||||
&child, &children) != 0)
|
&child, &children) != 0)
|
||||||
|
@ -2065,34 +2088,54 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
|
state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
|
||||||
|
|
||||||
if (isspare) {
|
if (isspare) {
|
||||||
/*
|
/*
|
||||||
* For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
|
* For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
|
||||||
* online drives.
|
* online drives.
|
||||||
*/
|
*/
|
||||||
if (vs->vs_aux == VDEV_AUX_SPARED)
|
if (vs->vs_aux == VDEV_AUX_SPARED)
|
||||||
state = "INUSE";
|
state = gettext("INUSE");
|
||||||
else if (vs->vs_state == VDEV_STATE_HEALTHY)
|
else if (vs->vs_state == VDEV_STATE_HEALTHY)
|
||||||
state = "AVAIL";
|
state = gettext("AVAIL");
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
|
printf_color(health_str_to_color(state),
|
||||||
|
"\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
|
||||||
name, state);
|
name, state);
|
||||||
|
|
||||||
if (!isspare) {
|
if (!isspare) {
|
||||||
|
if (vs->vs_read_errors)
|
||||||
|
rcolor = ANSI_RED;
|
||||||
|
|
||||||
|
if (vs->vs_write_errors)
|
||||||
|
wcolor = ANSI_RED;
|
||||||
|
|
||||||
|
if (vs->vs_checksum_errors)
|
||||||
|
ccolor = ANSI_RED;
|
||||||
|
|
||||||
if (cb->cb_literal) {
|
if (cb->cb_literal) {
|
||||||
printf(" %5llu %5llu %5llu",
|
printf(" ");
|
||||||
(u_longlong_t)vs->vs_read_errors,
|
printf_color(rcolor, "%5llu",
|
||||||
(u_longlong_t)vs->vs_write_errors,
|
(u_longlong_t)vs->vs_read_errors);
|
||||||
|
printf(" ");
|
||||||
|
printf_color(wcolor, "%5llu",
|
||||||
|
(u_longlong_t)vs->vs_write_errors);
|
||||||
|
printf(" ");
|
||||||
|
printf_color(ccolor, "%5llu",
|
||||||
(u_longlong_t)vs->vs_checksum_errors);
|
(u_longlong_t)vs->vs_checksum_errors);
|
||||||
} else {
|
} else {
|
||||||
zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
|
zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
|
||||||
zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
|
zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
|
||||||
zfs_nicenum(vs->vs_checksum_errors, cbuf,
|
zfs_nicenum(vs->vs_checksum_errors, cbuf,
|
||||||
sizeof (cbuf));
|
sizeof (cbuf));
|
||||||
printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
|
printf(" ");
|
||||||
|
printf_color(rcolor, "%5s", rbuf);
|
||||||
|
printf(" ");
|
||||||
|
printf_color(wcolor, "%5s", wbuf);
|
||||||
|
printf(" ");
|
||||||
|
printf_color(ccolor, "%5s", cbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb->cb_print_slow_ios) {
|
if (cb->cb_print_slow_ios) {
|
||||||
if (children == 0) {
|
if (children == 0) {
|
||||||
/* Only leafs vdevs have slow IOs */
|
/* Only leafs vdevs have slow IOs */
|
||||||
|
@ -2107,16 +2150,15 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
|
||||||
else
|
else
|
||||||
printf(" %5s", rbuf);
|
printf(" %5s", rbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
|
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
|
||||||
¬present) == 0) {
|
¬present) == 0) {
|
||||||
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
|
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
|
||||||
(void) printf(" was %s", path);
|
(void) printf(" %s %s", gettext("was"), path);
|
||||||
} else if (vs->vs_aux != 0) {
|
} else if (vs->vs_aux != 0) {
|
||||||
(void) printf(" ");
|
(void) printf(" ");
|
||||||
|
color_start(ANSI_RED);
|
||||||
switch (vs->vs_aux) {
|
switch (vs->vs_aux) {
|
||||||
case VDEV_AUX_OPEN_FAILED:
|
case VDEV_AUX_OPEN_FAILED:
|
||||||
(void) printf(gettext("cannot open"));
|
(void) printf(gettext("cannot open"));
|
||||||
|
@ -2188,6 +2230,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
|
||||||
(void) printf(gettext("corrupted data"));
|
(void) printf(gettext("corrupted data"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
color_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The root vdev has the scrub/resilver stats */
|
/* The root vdev has the scrub/resilver stats */
|
||||||
|
@ -2462,14 +2505,16 @@ show_import(nvlist_t *config)
|
||||||
case ZPOOL_STATUS_MISSING_DEV_R:
|
case ZPOOL_STATUS_MISSING_DEV_R:
|
||||||
case ZPOOL_STATUS_MISSING_DEV_NR:
|
case ZPOOL_STATUS_MISSING_DEV_NR:
|
||||||
case ZPOOL_STATUS_BAD_GUID_SUM:
|
case ZPOOL_STATUS_BAD_GUID_SUM:
|
||||||
(void) printf(gettext(" status: One or more devices are "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices are "
|
||||||
"missing from the system.\n"));
|
"missing from the system.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_CORRUPT_LABEL_R:
|
case ZPOOL_STATUS_CORRUPT_LABEL_R:
|
||||||
case ZPOOL_STATUS_CORRUPT_LABEL_NR:
|
case ZPOOL_STATUS_CORRUPT_LABEL_NR:
|
||||||
(void) printf(gettext(" status: One or more devices contains "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"corrupted data.\n"));
|
printf_color(ANSI_YELLOW, gettext("One or more devices contains"
|
||||||
|
" corrupted data.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_CORRUPT_DATA:
|
case ZPOOL_STATUS_CORRUPT_DATA:
|
||||||
|
@ -2478,78 +2523,96 @@ show_import(nvlist_t *config)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_OFFLINE_DEV:
|
case ZPOOL_STATUS_OFFLINE_DEV:
|
||||||
(void) printf(gettext(" status: One or more devices "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices "
|
||||||
"are offlined.\n"));
|
"are offlined.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_CORRUPT_POOL:
|
case ZPOOL_STATUS_CORRUPT_POOL:
|
||||||
(void) printf(gettext(" status: The pool metadata is "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("The pool metadata is "
|
||||||
"corrupted.\n"));
|
"corrupted.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_VERSION_OLDER:
|
case ZPOOL_STATUS_VERSION_OLDER:
|
||||||
(void) printf(gettext(" status: The pool is formatted using a "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"legacy on-disk version.\n"));
|
printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
|
||||||
|
"a legacy on-disk version.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_VERSION_NEWER:
|
case ZPOOL_STATUS_VERSION_NEWER:
|
||||||
(void) printf(gettext(" status: The pool is formatted using an "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"incompatible version.\n"));
|
printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
|
||||||
|
"an incompatible version.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_FEAT_DISABLED:
|
case ZPOOL_STATUS_FEAT_DISABLED:
|
||||||
(void) printf(gettext(" status: Some supported features are "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Some supported features are "
|
||||||
"not enabled on the pool.\n"));
|
"not enabled on the pool.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_UNSUP_FEAT_READ:
|
case ZPOOL_STATUS_UNSUP_FEAT_READ:
|
||||||
(void) printf(gettext("status: The pool uses the following "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("The pool uses the following "
|
||||||
"feature(s) not supported on this system:\n"));
|
"feature(s) not supported on this system:\n"));
|
||||||
|
color_start(ANSI_YELLOW);
|
||||||
zpool_print_unsup_feat(config);
|
zpool_print_unsup_feat(config);
|
||||||
|
color_end();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
|
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
|
||||||
(void) printf(gettext("status: The pool can only be accessed "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"in read-only mode on this system. It\n\tcannot be "
|
printf_color(ANSI_YELLOW, gettext("The pool can only be "
|
||||||
"accessed in read-write mode because it uses the "
|
"accessed in read-only mode on this system. It\n\tcannot be"
|
||||||
|
" accessed in read-write mode because it uses the "
|
||||||
"following\n\tfeature(s) not supported on this system:\n"));
|
"following\n\tfeature(s) not supported on this system:\n"));
|
||||||
|
color_start(ANSI_YELLOW);
|
||||||
zpool_print_unsup_feat(config);
|
zpool_print_unsup_feat(config);
|
||||||
|
color_end();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_HOSTID_ACTIVE:
|
case ZPOOL_STATUS_HOSTID_ACTIVE:
|
||||||
(void) printf(gettext(" status: The pool is currently "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("The pool is currently "
|
||||||
"imported by another system.\n"));
|
"imported by another system.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_HOSTID_REQUIRED:
|
case ZPOOL_STATUS_HOSTID_REQUIRED:
|
||||||
(void) printf(gettext(" status: The pool has the "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("The pool has the "
|
||||||
"multihost property on. It cannot\n\tbe safely imported "
|
"multihost property on. It cannot\n\tbe safely imported "
|
||||||
"when the system hostid is not set.\n"));
|
"when the system hostid is not set.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_HOSTID_MISMATCH:
|
case ZPOOL_STATUS_HOSTID_MISMATCH:
|
||||||
(void) printf(gettext(" status: The pool was last accessed by "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"another system.\n"));
|
printf_color(ANSI_YELLOW, gettext("The pool was last accessed "
|
||||||
|
"by another system.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_FAULTED_DEV_R:
|
case ZPOOL_STATUS_FAULTED_DEV_R:
|
||||||
case ZPOOL_STATUS_FAULTED_DEV_NR:
|
case ZPOOL_STATUS_FAULTED_DEV_NR:
|
||||||
(void) printf(gettext(" status: One or more devices are "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices are "
|
||||||
"faulted.\n"));
|
"faulted.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_BAD_LOG:
|
case ZPOOL_STATUS_BAD_LOG:
|
||||||
(void) printf(gettext(" status: An intent log record cannot be "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"read.\n"));
|
printf_color(ANSI_YELLOW, gettext("An intent log record cannot "
|
||||||
|
"be read.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_RESILVERING:
|
case ZPOOL_STATUS_RESILVERING:
|
||||||
(void) printf(gettext(" status: One or more devices were being "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"resilvered.\n"));
|
printf_color(ANSI_YELLOW, gettext("One or more devices were "
|
||||||
|
"being resilvered.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_ERRATA:
|
case ZPOOL_STATUS_ERRATA:
|
||||||
(void) printf(gettext(" status: Errata #%d detected.\n"),
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"),
|
||||||
errata);
|
errata);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2644,13 +2707,15 @@ show_import(nvlist_t *config)
|
||||||
"backup.\n"));
|
"backup.\n"));
|
||||||
break;
|
break;
|
||||||
case ZPOOL_STATUS_UNSUP_FEAT_READ:
|
case ZPOOL_STATUS_UNSUP_FEAT_READ:
|
||||||
(void) printf(gettext("action: The pool cannot be "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("The pool cannot be "
|
||||||
"imported. Access the pool on a system that "
|
"imported. Access the pool on a system that "
|
||||||
"supports\n\tthe required feature(s), or recreate "
|
"supports\n\tthe required feature(s), or recreate "
|
||||||
"the pool from backup.\n"));
|
"the pool from backup.\n"));
|
||||||
break;
|
break;
|
||||||
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
|
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
|
||||||
(void) printf(gettext("action: The pool cannot be "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("The pool cannot be "
|
||||||
"imported in read-write mode. Import the pool "
|
"imported in read-write mode. Import the pool "
|
||||||
"with\n"
|
"with\n"
|
||||||
"\t\"-o readonly=on\", access the pool on a system "
|
"\t\"-o readonly=on\", access the pool on a system "
|
||||||
|
@ -3720,7 +3785,7 @@ print_cmd_columns(vdev_cmd_data_list_t *vcdl, int use_dashes)
|
||||||
for (j = 0; j < vcdl->uniq_cols_width[i]; j++)
|
for (j = 0; j < vcdl->uniq_cols_width[i]; j++)
|
||||||
printf("-");
|
printf("-");
|
||||||
} else {
|
} else {
|
||||||
printf("%*s", vcdl->uniq_cols_width[i],
|
printf_color(ANSI_BOLD, "%*s", vcdl->uniq_cols_width[i],
|
||||||
vcdl->uniq_cols[i]);
|
vcdl->uniq_cols[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7024,7 +7089,9 @@ print_scan_status(pool_scan_stat_t *ps)
|
||||||
char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
|
char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
|
||||||
char srate_buf[7], irate_buf[7];
|
char srate_buf[7], irate_buf[7];
|
||||||
|
|
||||||
(void) printf(gettext(" scan: "));
|
printf(" ");
|
||||||
|
printf_color(ANSI_BOLD, gettext("scan:"));
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
/* If there's never been a scan, there's not much to say. */
|
/* If there's never been a scan, there's not much to say. */
|
||||||
if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
|
if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
|
||||||
|
@ -7503,38 +7570,52 @@ status_callback(zpool_handle_t *zhp, void *data)
|
||||||
|
|
||||||
health = zpool_get_state_str(zhp);
|
health = zpool_get_state_str(zhp);
|
||||||
|
|
||||||
(void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
|
printf(" ");
|
||||||
(void) printf(gettext(" state: %s\n"), health);
|
printf_color(ANSI_BOLD, gettext("pool:"));
|
||||||
|
printf(" %s\n", zpool_get_name(zhp));
|
||||||
|
printf(" ");
|
||||||
|
printf_color(ANSI_BOLD, gettext("state: "));
|
||||||
|
|
||||||
|
printf_color(health_str_to_color(health), "%s", health);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case ZPOOL_STATUS_MISSING_DEV_R:
|
case ZPOOL_STATUS_MISSING_DEV_R:
|
||||||
(void) printf(gettext("status: One or more devices could not "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"be opened. Sufficient replicas exist for\n\tthe pool to "
|
printf_color(ANSI_YELLOW, gettext("One or more devices could "
|
||||||
"continue functioning in a degraded state.\n"));
|
"not be opened. Sufficient replicas exist for\n\tthe pool "
|
||||||
(void) printf(gettext("action: Attach the missing device and "
|
"to continue functioning in a degraded state.\n"));
|
||||||
"online it using 'zpool online'.\n"));
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Attach the missing device "
|
||||||
|
"and online it using 'zpool online'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_MISSING_DEV_NR:
|
case ZPOOL_STATUS_MISSING_DEV_NR:
|
||||||
(void) printf(gettext("status: One or more devices could not "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"be opened. There are insufficient\n\treplicas for the "
|
printf_color(ANSI_YELLOW, gettext("One or more devices could "
|
||||||
"pool to continue functioning.\n"));
|
"not be opened. There are insufficient\n\treplicas for the"
|
||||||
(void) printf(gettext("action: Attach the missing device and "
|
" pool to continue functioning.\n"));
|
||||||
"online it using 'zpool online'.\n"));
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Attach the missing device "
|
||||||
|
"and online it using 'zpool online'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_CORRUPT_LABEL_R:
|
case ZPOOL_STATUS_CORRUPT_LABEL_R:
|
||||||
(void) printf(gettext("status: One or more devices could not "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"be used because the label is missing or\n\tinvalid. "
|
printf_color(ANSI_YELLOW, gettext("One or more devices could "
|
||||||
|
"not be used because the label is missing or\n\tinvalid. "
|
||||||
"Sufficient replicas exist for the pool to continue\n\t"
|
"Sufficient replicas exist for the pool to continue\n\t"
|
||||||
"functioning in a degraded state.\n"));
|
"functioning in a degraded state.\n"));
|
||||||
(void) printf(gettext("action: Replace the device using "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Replace the device using "
|
||||||
"'zpool replace'.\n"));
|
"'zpool replace'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_CORRUPT_LABEL_NR:
|
case ZPOOL_STATUS_CORRUPT_LABEL_NR:
|
||||||
(void) printf(gettext("status: One or more devices could not "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"be used because the label is missing \n\tor invalid. "
|
printf_color(ANSI_YELLOW, gettext("One or more devices could "
|
||||||
|
"not be used because the label is missing \n\tor invalid. "
|
||||||
"There are insufficient replicas for the pool to "
|
"There are insufficient replicas for the pool to "
|
||||||
"continue\n\tfunctioning.\n"));
|
"continue\n\tfunctioning.\n"));
|
||||||
zpool_explain_recover(zpool_get_handle(zhp),
|
zpool_explain_recover(zpool_get_handle(zhp),
|
||||||
|
@ -7542,175 +7623,209 @@ status_callback(zpool_handle_t *zhp, void *data)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_FAILING_DEV:
|
case ZPOOL_STATUS_FAILING_DEV:
|
||||||
(void) printf(gettext("status: One or more devices has "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices has "
|
||||||
"experienced an unrecoverable error. An\n\tattempt was "
|
"experienced an unrecoverable error. An\n\tattempt was "
|
||||||
"made to correct the error. Applications are "
|
"made to correct the error. Applications are "
|
||||||
"unaffected.\n"));
|
"unaffected.\n"));
|
||||||
(void) printf(gettext("action: Determine if the device needs "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"to be replaced, and clear the errors\n\tusing "
|
printf_color(ANSI_YELLOW, gettext("Determine if the "
|
||||||
"'zpool clear' or replace the device with 'zpool "
|
"device needs to be replaced, and clear the errors\n\tusing"
|
||||||
|
" 'zpool clear' or replace the device with 'zpool "
|
||||||
"replace'.\n"));
|
"replace'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_OFFLINE_DEV:
|
case ZPOOL_STATUS_OFFLINE_DEV:
|
||||||
(void) printf(gettext("status: One or more devices has "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices has "
|
||||||
"been taken offline by the administrator.\n\tSufficient "
|
"been taken offline by the administrator.\n\tSufficient "
|
||||||
"replicas exist for the pool to continue functioning in "
|
"replicas exist for the pool to continue functioning in "
|
||||||
"a\n\tdegraded state.\n"));
|
"a\n\tdegraded state.\n"));
|
||||||
(void) printf(gettext("action: Online the device using "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"'zpool online' or replace the device with\n\t'zpool "
|
printf_color(ANSI_YELLOW, gettext("Online the device "
|
||||||
|
"using 'zpool online' or replace the device with\n\t'zpool "
|
||||||
"replace'.\n"));
|
"replace'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_REMOVED_DEV:
|
case ZPOOL_STATUS_REMOVED_DEV:
|
||||||
(void) printf(gettext("status: One or more devices has "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices has "
|
||||||
"been removed by the administrator.\n\tSufficient "
|
"been removed by the administrator.\n\tSufficient "
|
||||||
"replicas exist for the pool to continue functioning in "
|
"replicas exist for the pool to continue functioning in "
|
||||||
"a\n\tdegraded state.\n"));
|
"a\n\tdegraded state.\n"));
|
||||||
(void) printf(gettext("action: Online the device using "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"'zpool online' or replace the device with\n\t'zpool "
|
printf_color(ANSI_YELLOW, gettext("Online the device "
|
||||||
|
"using zpool online' or replace the device with\n\t'zpool "
|
||||||
"replace'.\n"));
|
"replace'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_RESILVERING:
|
case ZPOOL_STATUS_RESILVERING:
|
||||||
(void) printf(gettext("status: One or more devices is "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices is "
|
||||||
"currently being resilvered. The pool will\n\tcontinue "
|
"currently being resilvered. The pool will\n\tcontinue "
|
||||||
"to function, possibly in a degraded state.\n"));
|
"to function, possibly in a degraded state.\n"));
|
||||||
(void) printf(gettext("action: Wait for the resilver to "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Wait for the resilver to "
|
||||||
"complete.\n"));
|
"complete.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_CORRUPT_DATA:
|
case ZPOOL_STATUS_CORRUPT_DATA:
|
||||||
(void) printf(gettext("status: One or more devices has "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices has "
|
||||||
"experienced an error resulting in data\n\tcorruption. "
|
"experienced an error resulting in data\n\tcorruption. "
|
||||||
"Applications may be affected.\n"));
|
"Applications may be affected.\n"));
|
||||||
(void) printf(gettext("action: Restore the file in question "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"if possible. Otherwise restore the\n\tentire pool from "
|
printf_color(ANSI_YELLOW, gettext("Restore the file in question"
|
||||||
|
" if possible. Otherwise restore the\n\tentire pool from "
|
||||||
"backup.\n"));
|
"backup.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_CORRUPT_POOL:
|
case ZPOOL_STATUS_CORRUPT_POOL:
|
||||||
(void) printf(gettext("status: The pool metadata is corrupted "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"and the pool cannot be opened.\n"));
|
printf_color(ANSI_YELLOW, gettext("The pool metadata is "
|
||||||
|
"corrupted and the pool cannot be opened.\n"));
|
||||||
zpool_explain_recover(zpool_get_handle(zhp),
|
zpool_explain_recover(zpool_get_handle(zhp),
|
||||||
zpool_get_name(zhp), reason, config);
|
zpool_get_name(zhp), reason, config);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_VERSION_OLDER:
|
case ZPOOL_STATUS_VERSION_OLDER:
|
||||||
(void) printf(gettext("status: The pool is formatted using a "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"legacy on-disk format. The pool can\n\tstill be used, "
|
printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
|
||||||
|
"a legacy on-disk format. The pool can\n\tstill be used, "
|
||||||
"but some features are unavailable.\n"));
|
"but some features are unavailable.\n"));
|
||||||
(void) printf(gettext("action: Upgrade the pool using 'zpool "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"upgrade'. Once this is done, the\n\tpool will no longer "
|
printf_color(ANSI_YELLOW, gettext("Upgrade the pool using "
|
||||||
"be accessible on software that does not support\n\t"
|
"'zpool upgrade'. Once this is done, the\n\tpool will no "
|
||||||
|
"longer be accessible on software that does not support\n\t"
|
||||||
"feature flags.\n"));
|
"feature flags.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_VERSION_NEWER:
|
case ZPOOL_STATUS_VERSION_NEWER:
|
||||||
(void) printf(gettext("status: The pool has been upgraded to a "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"newer, incompatible on-disk version.\n\tThe pool cannot "
|
printf_color(ANSI_YELLOW, gettext("The pool has been upgraded "
|
||||||
"be accessed on this system.\n"));
|
"to a newer, incompatible on-disk version.\n\tThe pool "
|
||||||
(void) printf(gettext("action: Access the pool from a system "
|
"cannot be accessed on this system.\n"));
|
||||||
"running more recent software, or\n\trestore the pool from "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"backup.\n"));
|
printf_color(ANSI_YELLOW, gettext("Access the pool from a "
|
||||||
|
"system running more recent software, or\n\trestore the "
|
||||||
|
"pool from backup.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_FEAT_DISABLED:
|
case ZPOOL_STATUS_FEAT_DISABLED:
|
||||||
(void) printf(gettext("status: Some supported features are not "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"enabled on the pool. The pool can\n\tstill be used, but "
|
printf_color(ANSI_YELLOW, gettext("Some supported features are "
|
||||||
"some features are unavailable.\n"));
|
"not enabled on the pool. The pool can\n\tstill be used, "
|
||||||
(void) printf(gettext("action: Enable all features using "
|
"but some features are unavailable.\n"));
|
||||||
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Enable all features using "
|
||||||
"'zpool upgrade'. Once this is done,\n\tthe pool may no "
|
"'zpool upgrade'. Once this is done,\n\tthe pool may no "
|
||||||
"longer be accessible by software that does not support\n\t"
|
"longer be accessible by software that does not support\n\t"
|
||||||
"the features. See zpool-features(5) for details.\n"));
|
"the features. See zpool-features(5) for details.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_UNSUP_FEAT_READ:
|
case ZPOOL_STATUS_UNSUP_FEAT_READ:
|
||||||
(void) printf(gettext("status: The pool cannot be accessed on "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"this system because it uses the\n\tfollowing feature(s) "
|
printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed "
|
||||||
"not supported on this system:\n"));
|
"on this system because it uses the\n\tfollowing feature(s)"
|
||||||
|
" not supported on this system:\n"));
|
||||||
zpool_print_unsup_feat(config);
|
zpool_print_unsup_feat(config);
|
||||||
(void) printf("\n");
|
(void) printf("\n");
|
||||||
(void) printf(gettext("action: Access the pool from a system "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"that supports the required feature(s),\n\tor restore the "
|
printf_color(ANSI_YELLOW, gettext("Access the pool from a "
|
||||||
"pool from backup.\n"));
|
"system that supports the required feature(s),\n\tor "
|
||||||
|
"restore the pool from backup.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
|
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
|
||||||
(void) printf(gettext("status: The pool can only be accessed "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"in read-only mode on this system. It\n\tcannot be "
|
printf_color(ANSI_YELLOW, gettext("The pool can only be "
|
||||||
"accessed in read-write mode because it uses the "
|
"accessed in read-only mode on this system. It\n\tcannot be"
|
||||||
|
" accessed in read-write mode because it uses the "
|
||||||
"following\n\tfeature(s) not supported on this system:\n"));
|
"following\n\tfeature(s) not supported on this system:\n"));
|
||||||
zpool_print_unsup_feat(config);
|
zpool_print_unsup_feat(config);
|
||||||
(void) printf("\n");
|
(void) printf("\n");
|
||||||
(void) printf(gettext("action: The pool cannot be accessed in "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"read-write mode. Import the pool with\n"
|
printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed "
|
||||||
|
"in read-write mode. Import the pool with\n"
|
||||||
"\t\"-o readonly=on\", access the pool from a system that "
|
"\t\"-o readonly=on\", access the pool from a system that "
|
||||||
"supports the\n\trequired feature(s), or restore the "
|
"supports the\n\trequired feature(s), or restore the "
|
||||||
"pool from backup.\n"));
|
"pool from backup.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_FAULTED_DEV_R:
|
case ZPOOL_STATUS_FAULTED_DEV_R:
|
||||||
(void) printf(gettext("status: One or more devices are "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices are "
|
||||||
"faulted in response to persistent errors.\n\tSufficient "
|
"faulted in response to persistent errors.\n\tSufficient "
|
||||||
"replicas exist for the pool to continue functioning "
|
"replicas exist for the pool to continue functioning "
|
||||||
"in a\n\tdegraded state.\n"));
|
"in a\n\tdegraded state.\n"));
|
||||||
(void) printf(gettext("action: Replace the faulted device, "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Replace the faulted device, "
|
||||||
"or use 'zpool clear' to mark the device\n\trepaired.\n"));
|
"or use 'zpool clear' to mark the device\n\trepaired.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_FAULTED_DEV_NR:
|
case ZPOOL_STATUS_FAULTED_DEV_NR:
|
||||||
(void) printf(gettext("status: One or more devices are "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices are "
|
||||||
"faulted in response to persistent errors. There are "
|
"faulted in response to persistent errors. There are "
|
||||||
"insufficient replicas for the pool to\n\tcontinue "
|
"insufficient replicas for the pool to\n\tcontinue "
|
||||||
"functioning.\n"));
|
"functioning.\n"));
|
||||||
(void) printf(gettext("action: Destroy and re-create the pool "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"from a backup source. Manually marking the device\n"
|
printf_color(ANSI_YELLOW, gettext("Destroy and re-create the "
|
||||||
|
"pool from a backup source. Manually marking the device\n"
|
||||||
"\trepaired using 'zpool clear' may allow some data "
|
"\trepaired using 'zpool clear' may allow some data "
|
||||||
"to be recovered.\n"));
|
"to be recovered.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_IO_FAILURE_MMP:
|
case ZPOOL_STATUS_IO_FAILURE_MMP:
|
||||||
(void) printf(gettext("status: The pool is suspended because "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"multihost writes failed or were delayed;\n\tanother "
|
printf_color(ANSI_YELLOW, gettext("The pool is suspended "
|
||||||
"system could import the pool undetected.\n"));
|
"because multihost writes failed or were delayed;\n\t"
|
||||||
(void) printf(gettext("action: Make sure the pool's devices "
|
"another system could import the pool undetected.\n"));
|
||||||
"are connected, then reboot your system and\n\timport the "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Make sure the pool's devices"
|
||||||
|
" are connected, then reboot your system and\n\timport the "
|
||||||
"pool.\n"));
|
"pool.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_IO_FAILURE_WAIT:
|
case ZPOOL_STATUS_IO_FAILURE_WAIT:
|
||||||
case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
|
case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
|
||||||
(void) printf(gettext("status: One or more devices are "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("One or more devices are "
|
||||||
"faulted in response to IO failures.\n"));
|
"faulted in response to IO failures.\n"));
|
||||||
(void) printf(gettext("action: Make sure the affected devices "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"are connected, then run 'zpool clear'.\n"));
|
printf_color(ANSI_YELLOW, gettext("Make sure the affected "
|
||||||
|
"devices are connected, then run 'zpool clear'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_BAD_LOG:
|
case ZPOOL_STATUS_BAD_LOG:
|
||||||
(void) printf(gettext("status: An intent log record "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("An intent log record "
|
||||||
"could not be read.\n"
|
"could not be read.\n"
|
||||||
"\tWaiting for administrator intervention to fix the "
|
"\tWaiting for administrator intervention to fix the "
|
||||||
"faulted pool.\n"));
|
"faulted pool.\n"));
|
||||||
(void) printf(gettext("action: Either restore the affected "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Either restore the affected "
|
||||||
"device(s) and run 'zpool online',\n"
|
"device(s) and run 'zpool online',\n"
|
||||||
"\tor ignore the intent log records by running "
|
"\tor ignore the intent log records by running "
|
||||||
"'zpool clear'.\n"));
|
"'zpool clear'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_HOSTID_MISMATCH:
|
case ZPOOL_STATUS_HOSTID_MISMATCH:
|
||||||
(void) printf(gettext("status: Mismatch between pool hostid "
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
"and system hostid on imported pool.\n\tThis pool was "
|
printf_color(ANSI_YELLOW, gettext("Mismatch between pool hostid"
|
||||||
|
" and system hostid on imported pool.\n\tThis pool was "
|
||||||
"previously imported into a system with a different "
|
"previously imported into a system with a different "
|
||||||
"hostid,\n\tand then was verbatim imported into this "
|
"hostid,\n\tand then was verbatim imported into this "
|
||||||
"system.\n"));
|
"system.\n"));
|
||||||
(void) printf(gettext("action: Export this pool on all systems "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"on which it is imported.\n"
|
printf_color(ANSI_YELLOW, gettext("Export this pool on all "
|
||||||
|
"systems on which it is imported.\n"
|
||||||
"\tThen import it to correct the mismatch.\n"));
|
"\tThen import it to correct the mismatch.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_STATUS_ERRATA:
|
case ZPOOL_STATUS_ERRATA:
|
||||||
(void) printf(gettext("status: Errata #%d detected.\n"),
|
printf_color(ANSI_BOLD, gettext("status: "));
|
||||||
|
printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"),
|
||||||
errata);
|
errata);
|
||||||
|
|
||||||
switch (errata) {
|
switch (errata) {
|
||||||
|
@ -7718,16 +7833,18 @@ status_callback(zpool_handle_t *zhp, void *data)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_ERRATA_ZOL_2094_SCRUB:
|
case ZPOOL_ERRATA_ZOL_2094_SCRUB:
|
||||||
(void) printf(gettext("action: To correct the issue "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"run 'zpool scrub'.\n"));
|
printf_color(ANSI_YELLOW, gettext("To correct the issue"
|
||||||
|
" run 'zpool scrub'.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
|
case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
|
||||||
(void) printf(gettext("\tExisting encrypted datasets "
|
(void) printf(gettext("\tExisting encrypted datasets "
|
||||||
"contain an on-disk incompatibility\n\twhich "
|
"contain an on-disk incompatibility\n\twhich "
|
||||||
"needs to be corrected.\n"));
|
"needs to be corrected.\n"));
|
||||||
(void) printf(gettext("action: To correct the issue "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"backup existing encrypted datasets to new\n\t"
|
printf_color(ANSI_YELLOW, gettext("To correct the issue"
|
||||||
|
" backup existing encrypted datasets to new\n\t"
|
||||||
"encrypted datasets and destroy the old ones. "
|
"encrypted datasets and destroy the old ones. "
|
||||||
"'zfs mount -o ro' can\n\tbe used to temporarily "
|
"'zfs mount -o ro' can\n\tbe used to temporarily "
|
||||||
"mount existing encrypted datasets readonly.\n"));
|
"mount existing encrypted datasets readonly.\n"));
|
||||||
|
@ -7738,13 +7855,14 @@ status_callback(zpool_handle_t *zhp, void *data)
|
||||||
"and bookmarks contain an on-disk\n\tincompat"
|
"and bookmarks contain an on-disk\n\tincompat"
|
||||||
"ibility. This may cause on-disk corruption if "
|
"ibility. This may cause on-disk corruption if "
|
||||||
"they are used\n\twith 'zfs recv'.\n"));
|
"they are used\n\twith 'zfs recv'.\n"));
|
||||||
(void) printf(gettext("action: To correct the issue, "
|
printf_color(ANSI_BOLD, gettext("action: "));
|
||||||
"enable the bookmark_v2 feature. No additional\n\t"
|
printf_color(ANSI_YELLOW, gettext("To correct the"
|
||||||
"action is needed if there are no encrypted "
|
"issue, enable the bookmark_v2 feature. No "
|
||||||
"snapshots or bookmarks.\n\tIf preserving the "
|
"additional\n\taction is needed if there are no "
|
||||||
"encrypted snapshots and bookmarks is required, "
|
"encrypted snapshots or bookmarks.\n\tIf preserving"
|
||||||
"use\n\ta non-raw send to backup and restore them. "
|
"the encrypted snapshots and bookmarks is required,"
|
||||||
"Alternately, they may be\n\tremoved to resolve "
|
" use\n\ta non-raw send to backup and restore them."
|
||||||
|
" Alternately, they may be\n\tremoved to resolve "
|
||||||
"the incompatibility.\n"));
|
"the incompatibility.\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -7764,9 +7882,11 @@ status_callback(zpool_handle_t *zhp, void *data)
|
||||||
assert(reason == ZPOOL_STATUS_OK);
|
assert(reason == ZPOOL_STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msgid != NULL)
|
if (msgid != NULL) {
|
||||||
(void) printf(gettext(" see: http://zfsonlinux.org/msg/%s\n"),
|
printf(" ");
|
||||||
msgid);
|
printf_color(ANSI_BOLD, gettext("see:"));
|
||||||
|
printf(gettext(" http://zfsonlinux.org/msg/%s\n"), msgid);
|
||||||
|
}
|
||||||
|
|
||||||
if (config != NULL) {
|
if (config != NULL) {
|
||||||
uint64_t nerr;
|
uint64_t nerr;
|
||||||
|
@ -7782,7 +7902,6 @@ status_callback(zpool_handle_t *zhp, void *data)
|
||||||
ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
|
ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
|
||||||
(void) nvlist_lookup_uint64_array(nvroot,
|
(void) nvlist_lookup_uint64_array(nvroot,
|
||||||
ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
|
ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
|
||||||
|
|
||||||
print_scan_status(ps);
|
print_scan_status(ps);
|
||||||
print_checkpoint_scan_warning(ps, pcs);
|
print_checkpoint_scan_warning(ps, pcs);
|
||||||
print_removal_status(zhp, prs);
|
print_removal_status(zhp, prs);
|
||||||
|
@ -7793,13 +7912,16 @@ status_callback(zpool_handle_t *zhp, void *data)
|
||||||
if (cbp->cb_namewidth < 10)
|
if (cbp->cb_namewidth < 10)
|
||||||
cbp->cb_namewidth = 10;
|
cbp->cb_namewidth = 10;
|
||||||
|
|
||||||
|
color_start(ANSI_BOLD);
|
||||||
(void) printf(gettext("config:\n\n"));
|
(void) printf(gettext("config:\n\n"));
|
||||||
(void) printf(gettext("\t%-*s %-8s %5s %5s %5s"),
|
(void) printf(gettext("\t%-*s %-8s %5s %5s %5s"),
|
||||||
cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
|
cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
|
||||||
"CKSUM");
|
"CKSUM");
|
||||||
|
color_end();
|
||||||
|
|
||||||
if (cbp->cb_print_slow_ios)
|
if (cbp->cb_print_slow_ios) {
|
||||||
(void) printf(" %5s", gettext("SLOW"));
|
printf_color(ANSI_BOLD, " %5s", gettext("SLOW"));
|
||||||
|
}
|
||||||
|
|
||||||
if (cbp->vcdl != NULL)
|
if (cbp->vcdl != NULL)
|
||||||
print_cmd_columns(cbp->vcdl, 0);
|
print_cmd_columns(cbp->vcdl, 0);
|
||||||
|
|
|
@ -146,6 +146,18 @@ extern int zpool_history_unpack(char *, uint64_t, uint64_t *, nvlist_t ***,
|
||||||
struct zfs_cmd;
|
struct zfs_cmd;
|
||||||
int zfs_ioctl_fd(int fd, unsigned long request, struct zfs_cmd *zc);
|
int zfs_ioctl_fd(int fd, unsigned long request, struct zfs_cmd *zc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of colors to use
|
||||||
|
*/
|
||||||
|
#define ANSI_RED "\033[0;31m"
|
||||||
|
#define ANSI_YELLOW "\033[0;33m"
|
||||||
|
#define ANSI_RESET "\033[0m"
|
||||||
|
#define ANSI_BOLD "\033[1m"
|
||||||
|
|
||||||
|
void color_start(char *color);
|
||||||
|
void color_end(void);
|
||||||
|
int printf_color(char *color, char *format, ...);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1886,3 +1886,95 @@ zfs_version_print(void)
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 1 if the user requested ANSI color output, and our terminal supports
|
||||||
|
* it. Return 0 for no color.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
use_color(void)
|
||||||
|
{
|
||||||
|
static int use_color = -1;
|
||||||
|
char *term;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optimization:
|
||||||
|
*
|
||||||
|
* For each zpool invocation, we do a single check to see if we should
|
||||||
|
* be using color or not, and cache that value for the lifetime of the
|
||||||
|
* the zpool command. That makes it cheap to call use_color() when
|
||||||
|
* we're printing with color. We assume that the settings are not going
|
||||||
|
* to change during the invocation of a zpool command (the user isn't
|
||||||
|
* going to change the ZFS_COLOR value while zpool is running, for
|
||||||
|
* example).
|
||||||
|
*/
|
||||||
|
if (use_color != -1) {
|
||||||
|
/*
|
||||||
|
* We've already figured out if we should be using color or
|
||||||
|
* not. Return the cached value.
|
||||||
|
*/
|
||||||
|
return (use_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
term = getenv("TERM");
|
||||||
|
/*
|
||||||
|
* The user sets the ZFS_COLOR env var set to enable zpool ANSI color
|
||||||
|
* output. However if NO_COLOR is set (https://no-color.org/) then
|
||||||
|
* don't use it. Also, don't use color if terminal doesn't support
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
|
if (libzfs_envvar_is_set("ZFS_COLOR") &&
|
||||||
|
!libzfs_envvar_is_set("NO_COLOR") &&
|
||||||
|
isatty(STDOUT_FILENO) && term && strcmp("dumb", term) != 0 &&
|
||||||
|
strcmp("unknown", term) != 0) {
|
||||||
|
/* Color supported */
|
||||||
|
use_color = 1;
|
||||||
|
} else {
|
||||||
|
use_color = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (use_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* color_start() and color_end() are used for when you want to colorize a block
|
||||||
|
* of text. For example:
|
||||||
|
*
|
||||||
|
* color_start(ANSI_RED_FG)
|
||||||
|
* printf("hello");
|
||||||
|
* printf("world");
|
||||||
|
* color_end();
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
color_start(char *color)
|
||||||
|
{
|
||||||
|
if (use_color())
|
||||||
|
printf("%s", color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
color_end(void)
|
||||||
|
{
|
||||||
|
if (use_color())
|
||||||
|
printf(ANSI_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* printf() with a color. If color is NULL, then do a normal printf. */
|
||||||
|
int
|
||||||
|
printf_color(char *color, char *format, ...)
|
||||||
|
{
|
||||||
|
va_list aptr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (color)
|
||||||
|
color_start(color);
|
||||||
|
|
||||||
|
va_start(aptr, format);
|
||||||
|
rc = vprintf(format, aptr);
|
||||||
|
va_end(aptr);
|
||||||
|
|
||||||
|
if (color)
|
||||||
|
color_end();
|
||||||
|
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
|
@ -453,6 +453,12 @@ Cause
|
||||||
to dump core on exit for the purposes of running
|
to dump core on exit for the purposes of running
|
||||||
.Sy ::findleaks .
|
.Sy ::findleaks .
|
||||||
.El
|
.El
|
||||||
|
.Bl -tag -width "ZFS_COLOR"
|
||||||
|
.It Ev ZFS_COLOR
|
||||||
|
Use ANSI color in
|
||||||
|
.Nm zpool status
|
||||||
|
output.
|
||||||
|
.El
|
||||||
.Bl -tag -width "ZPOOL_IMPORT_PATH"
|
.Bl -tag -width "ZPOOL_IMPORT_PATH"
|
||||||
.It Ev ZPOOL_IMPORT_PATH
|
.It Ev ZPOOL_IMPORT_PATH
|
||||||
The search path for devices or files to use with the pool. This is a colon-separated list of directories in which
|
The search path for devices or files to use with the pool. This is a colon-separated list of directories in which
|
||||||
|
|
|
@ -282,7 +282,7 @@ tests = ['zfs_upgrade_001_pos', 'zfs_upgrade_002_pos', 'zfs_upgrade_003_pos',
|
||||||
tags = ['functional', 'cli_root', 'zfs_upgrade']
|
tags = ['functional', 'cli_root', 'zfs_upgrade']
|
||||||
|
|
||||||
[tests/functional/cli_root/zpool]
|
[tests/functional/cli_root/zpool]
|
||||||
tests = ['zpool_001_neg', 'zpool_002_pos', 'zpool_003_pos']
|
tests = ['zpool_001_neg', 'zpool_002_pos', 'zpool_003_pos', 'zpool_colors']
|
||||||
tags = ['functional', 'cli_root', 'zpool']
|
tags = ['functional', 'cli_root', 'zpool']
|
||||||
|
|
||||||
[tests/functional/cli_root/zpool_add]
|
[tests/functional/cli_root/zpool_add]
|
||||||
|
|
|
@ -77,6 +77,7 @@ export SYSTEM_FILES_COMMON='arp
|
||||||
rm
|
rm
|
||||||
rmdir
|
rmdir
|
||||||
scp
|
scp
|
||||||
|
script
|
||||||
sed
|
sed
|
||||||
seq
|
seq
|
||||||
setfacl
|
setfacl
|
||||||
|
|
|
@ -3916,3 +3916,18 @@ function stat_size #<path>
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Run a command as if it was being run in a TTY.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# faketty command
|
||||||
|
#
|
||||||
|
function faketty
|
||||||
|
{
|
||||||
|
if is_freebsd; then
|
||||||
|
script -q /dev/null "$@"
|
||||||
|
else
|
||||||
|
script --return --quiet -c "$*" /dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
|
@ -4,4 +4,5 @@ dist_pkgdata_SCRIPTS = \
|
||||||
cleanup.ksh \
|
cleanup.ksh \
|
||||||
zpool_001_neg.ksh \
|
zpool_001_neg.ksh \
|
||||||
zpool_002_pos.ksh \
|
zpool_002_pos.ksh \
|
||||||
zpool_003_pos.ksh
|
zpool_003_pos.ksh \
|
||||||
|
zpool_colors.ksh
|
||||||
|
|
|
@ -29,4 +29,4 @@
|
||||||
|
|
||||||
DISK=${DISKS%% *}
|
DISK=${DISKS%% *}
|
||||||
|
|
||||||
default_setup $DISK
|
default_mirror_setup $DISKS
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
#!/bin/ksh -p
|
||||||
|
#
|
||||||
|
# CDDL HEADER START
|
||||||
|
#
|
||||||
|
# This file and its contents are supplied under the terms of the
|
||||||
|
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||||
|
# You may only use this file in accordance with the terms of version
|
||||||
|
# 1.0 of the CDDL.
|
||||||
|
#
|
||||||
|
# A full copy of the text of the CDDL should have accompanied this
|
||||||
|
# source. A copy of the CDDL is also available via the Internet at
|
||||||
|
# http://www.illumos.org/license/CDDL.
|
||||||
|
#
|
||||||
|
# CDDL HEADER END
|
||||||
|
#
|
||||||
|
# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
|
||||||
|
|
||||||
|
. $STF_SUITE/include/libtest.shlib
|
||||||
|
|
||||||
|
#
|
||||||
|
# DESCRIPTION:
|
||||||
|
# Test that zpool status colored output works.
|
||||||
|
#
|
||||||
|
# STRATEGY:
|
||||||
|
# 1. Create a pool with a bunch of errors and force fault one of the vdevs.
|
||||||
|
# 2. Look for 'pool:' in bold.
|
||||||
|
# 3. Look for 'DEGRADED' in yellow
|
||||||
|
# 3. Look for 'FAULTED' in red
|
||||||
|
#
|
||||||
|
|
||||||
|
verify_runnable "both"
|
||||||
|
|
||||||
|
function cleanup
|
||||||
|
{
|
||||||
|
zinject -c all
|
||||||
|
}
|
||||||
|
|
||||||
|
log_onexit cleanup
|
||||||
|
|
||||||
|
log_assert "Test colorized zpool status output"
|
||||||
|
|
||||||
|
DISK2="$(echo $DISKS | cut -d' ' -f2)"
|
||||||
|
DISK3="$(echo $DISKS | cut -d' ' -f3)"
|
||||||
|
|
||||||
|
log_must dd if=/dev/urandom of=/$TESTDIR/testfile bs=10M count=1
|
||||||
|
|
||||||
|
log_must zpool sync
|
||||||
|
|
||||||
|
log_must zpool offline -f $TESTPOOL $DISK3
|
||||||
|
log_must wait_for_degraded $TESTPOOL
|
||||||
|
log_must zinject -d $DISK2 -e io -T read -f 20 $TESTPOOL
|
||||||
|
log_must zinject -d $DISK2 -e io -T write -f 20 $TESTPOOL
|
||||||
|
|
||||||
|
|
||||||
|
log_must zpool scrub -w $TESTPOOL
|
||||||
|
log_must zinject -c all
|
||||||
|
|
||||||
|
|
||||||
|
# Use 'script' to fake zpool status into thinking it's running in a tty.
|
||||||
|
# Log the output here in case it's needed for postmortem.
|
||||||
|
log_note "$(faketty TERM=xterm-256color ZFS_COLOR=1 zpool status)"
|
||||||
|
|
||||||
|
# Replace the escape codes with "ESC" so they're easier to grep
|
||||||
|
out="$(faketty TERM=xterm-256color ZFS_COLOR=1 zpool status | \
|
||||||
|
grep -E 'pool:|DEGRADED' | \
|
||||||
|
sed -r 's/\s+//g;'$(echo -e 's/\033/ESC/g'))"
|
||||||
|
|
||||||
|
log_note "$(echo $out)"
|
||||||
|
|
||||||
|
log_note "Look for 'pool:' in bold"
|
||||||
|
log_must eval "echo \"$out\" | grep -q 'ESC\[1mpool:ESC\[0m' "
|
||||||
|
|
||||||
|
log_note "Look for 'DEGRADED' in yellow"
|
||||||
|
log_must eval "echo \"$out\" | grep -q 'ESC\[0;33mDEGRADEDESC\[0m'"
|
||||||
|
|
||||||
|
#
|
||||||
|
# The escape code for 'FAULTED' is a little more tricky. The line starts like
|
||||||
|
# this:
|
||||||
|
#
|
||||||
|
# <start red escape code> loop2 FAULTED <end escape code>
|
||||||
|
#
|
||||||
|
# Luckily, awk counts the start and end escape codes as separate fields, so
|
||||||
|
# we can easily remove the vdev field to get what we want.
|
||||||
|
#
|
||||||
|
out="$(faketty TERM=xterm-256color ZFS_COLOR=1 zpool status \
|
||||||
|
| awk '/FAULTED/{print $1$3$4}' | sed -r $(echo -e 's/\033/ESC/g'))"
|
||||||
|
|
||||||
|
log_note "Look for 'FAULTED' in red"
|
||||||
|
log_must eval "echo \"$out\" | grep -q 'ESC\[0;31mFAULTEDESC\[0m'"
|
||||||
|
|
||||||
|
log_pass "zpool status displayed colors"
|
Loading…
Reference in New Issue