Improve sysinstall messages (#43050)
I was trying to use systemd-sysinstall and those are the fixes for various ugly parts that are immediately obvious when it is used.
This commit is contained in:
@@ -151,7 +151,7 @@ static int ask_wipe(EnrollContext *c, unsigned existing_mask) {
|
||||
return log_oom();
|
||||
|
||||
bool wipe;
|
||||
r = prompt_loop_yes_no(question, /* def= */ false, &wipe);
|
||||
r = prompt_loop_yes_no(question, "no", /* def= */ false, &wipe);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -108,7 +108,8 @@ static uint16_t link_get_pvid(Link *link, bool *ret_untagged) {
|
||||
static int bridge_vlan_append_set_info(Link *link, sd_netlink_message *m) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
uint16_t pvid, begin = UINT16_MAX;
|
||||
bool untagged, pvid_is_untagged;
|
||||
bool pvid_is_untagged, untagged = false; /* <untagged> is always set togather with <begin>.
|
||||
* Initialize to appease gcc. */
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
+23
-9
@@ -11437,10 +11437,13 @@ static int context_ponder(Context *context) {
|
||||
if (context_drop_or_foreignize_one_priority(context))
|
||||
continue; /* Still no luck. Let's drop a priority and try again. */
|
||||
|
||||
/* No more priorities left to drop. This configuration just doesn't fit on this disk... */
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
|
||||
"Can't fit requested partitions into available free space (%s), refusing.",
|
||||
FORMAT_BYTES(largest_free_area));
|
||||
/* No more priorities left to drop. This configuration just doesn't fit on this disk...
|
||||
* In Varlink service mode the failure is reported to the client as a structured error,
|
||||
* hence only log at debug level here. */
|
||||
return log_full_errno(arg_varlink ? LOG_DEBUG : LOG_ERR,
|
||||
SYNTHETIC_ERRNO(ENOSPC),
|
||||
"Can't fit requested partitions into available free space (%s), refusing.",
|
||||
FORMAT_BYTES(largest_free_area));
|
||||
}
|
||||
|
||||
LIST_FOREACH(partitions, p, context->partitions) {
|
||||
@@ -11617,7 +11620,7 @@ static int vl_method_run(
|
||||
return sd_varlink_errorbo(
|
||||
link,
|
||||
"io.systemd.Repart.DiskTooSmall",
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("currentSizeBytes", current_size),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("currentSizeBytes", context->total),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("minimalSizeBytes", minimal_size));
|
||||
|
||||
/* Or if the disk would fit, but theres's not enough unallocated space */
|
||||
@@ -11625,7 +11628,7 @@ static int vl_method_run(
|
||||
return sd_varlink_errorbo(
|
||||
link,
|
||||
"io.systemd.Repart.InsufficientFreeSpace",
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("currentSizeBytes", current_size),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("currentSizeBytes", context->total),
|
||||
JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("needFreeBytes", need_free),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("minimalSizeBytes", minimal_size));
|
||||
}
|
||||
@@ -11633,17 +11636,28 @@ static int vl_method_run(
|
||||
return r;
|
||||
|
||||
if (p.dry_run) {
|
||||
uint64_t current_size, minimal_size;
|
||||
uint64_t minimal_size;
|
||||
|
||||
/* If we are doing a dry-run, report the minimal size. */
|
||||
r = determine_auto_size(context, LOG_DEBUG, ¤t_size, /* ret_foreign_size= */ NULL, &minimal_size);
|
||||
r = determine_auto_size(context, LOG_DEBUG, /* ret_current_size= */ NULL, /* ret_foreign_size= */ NULL, &minimal_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
bool count_partitions = IN_SET(context->empty, EMPTY_REFUSE, EMPTY_ALLOW);
|
||||
uint64_t n_partitions = 0;
|
||||
|
||||
if (count_partitions)
|
||||
LIST_FOREACH(partitions, pp, context->partitions)
|
||||
n_partitions += PARTITION_EXISTS(pp);
|
||||
|
||||
/* In 'force' and 'require' modes the existing partition table is not read, hence we don't
|
||||
* know how many partitions the disk contains, and say nothing about it. */
|
||||
return sd_varlink_replybo(
|
||||
link,
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("minimalSizeBytes", minimal_size),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("currentSizeBytes", current_size));
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("currentSizeBytes", context->total),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(count_partitions,
|
||||
"partitionCount", SD_JSON_BUILD_UNSIGNED(n_partitions)));
|
||||
}
|
||||
|
||||
r = context_write_partition_table(context);
|
||||
|
||||
@@ -217,19 +217,19 @@ static int boolean_is_valid(const char *name, void *userdata) {
|
||||
return parse_boolean(name) >= 0;
|
||||
}
|
||||
|
||||
int prompt_loop_yes_no(const char *question, bool def, bool *ret) {
|
||||
int prompt_loop_yes_no(const char *question, const char *prefill, bool def, bool *ret) {
|
||||
int r;
|
||||
|
||||
assert(question);
|
||||
assert(ret);
|
||||
|
||||
char **l = STRV_MAKE("yes", "no");
|
||||
char **menu = STRV_MAKE("yes", "no");
|
||||
|
||||
_cleanup_free_ char *reply = NULL;
|
||||
r = prompt_loop(question,
|
||||
GLYPH_WARNING_SIGN,
|
||||
/* prefill= */ def ? "yes" : "no",
|
||||
/* menu= */ l,
|
||||
/* prefill= */ prefill,
|
||||
/* menu= */ menu,
|
||||
/* accepted= */ NULL,
|
||||
/* ellipsize_percentage= */ 20,
|
||||
/* n_columns= */ 2,
|
||||
|
||||
@@ -26,7 +26,7 @@ int prompt_loop(const char *text,
|
||||
PromptFlags flags,
|
||||
char **ret);
|
||||
|
||||
int prompt_loop_yes_no(const char *question, bool def, bool *ret);
|
||||
int prompt_loop_yes_no(const char *question, const char *prefill, bool def, bool *ret);
|
||||
|
||||
int chrome_show(const char *top, const char *bottom);
|
||||
void chrome_hide(void);
|
||||
|
||||
@@ -59,11 +59,13 @@ static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||
SD_VARLINK_DEFINE_OUTPUT(minimalSizeBytes, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("In dry-run mode returns the size of the selected block device."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(currentSizeBytes, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Returns the number of partitions currently on the selected block device. Omitted if not determined by the workflow, e.g. if the existing partition table was not read because empty mode 'force' or 'require' was selected."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(partitionCount, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("If used with the 'more' flag, a phase identifier is sent in progress updates."),
|
||||
SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(phase, ProgressPhase, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("If used with the 'more' flag, an object identifier string is sent in progress updates."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(object, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("If used with the 'more' flag, a progress percentrage (specific to the work done for the specified phase+object is sent in progress updates."),
|
||||
SD_VARLINK_FIELD_COMMENT("If used with the 'more' flag, a progress percentage (specific to the work done for the specified phase+object)."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(progress, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||
|
||||
+35
-16
@@ -689,11 +689,12 @@ static int sysinstall_context_invoke_repart_run(SysInstallContext *context) {
|
||||
return result.ret;
|
||||
}
|
||||
|
||||
static int read_space_metrics(
|
||||
static int read_repart_metrics(
|
||||
sd_json_variant *v,
|
||||
uint64_t *min_size,
|
||||
uint64_t *current_size,
|
||||
uint64_t *need_free) {
|
||||
uint64_t *need_free,
|
||||
uint64_t *n_partitions) {
|
||||
|
||||
int r;
|
||||
|
||||
@@ -701,16 +702,19 @@ static int read_space_metrics(
|
||||
uint64_t min_size;
|
||||
uint64_t current_size;
|
||||
uint64_t need_free;
|
||||
uint64_t n_partitions;
|
||||
} p = {
|
||||
.min_size = UINT64_MAX,
|
||||
.current_size = UINT64_MAX,
|
||||
.need_free = UINT64_MAX,
|
||||
.n_partitions = UINT64_MAX,
|
||||
};
|
||||
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "minimalSizeBytes", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, voffsetof(p, min_size), 0 },
|
||||
{ "currentSizeBytes", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, voffsetof(p, current_size), 0 },
|
||||
{ "needFreeBytes", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, voffsetof(p, need_free), 0 },
|
||||
{ "partitionCount", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, voffsetof(p, n_partitions), 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -724,6 +728,8 @@ static int read_space_metrics(
|
||||
*current_size = p.current_size;
|
||||
if (need_free)
|
||||
*need_free = p.need_free;
|
||||
if (n_partitions)
|
||||
*n_partitions = p.n_partitions;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -736,7 +742,8 @@ static int invoke_repart(
|
||||
char **definitions,
|
||||
uint64_t *min_size, /* initialized both on success and error */
|
||||
uint64_t *current_size, /* ditto */
|
||||
uint64_t *need_free) { /* ditto */
|
||||
uint64_t *need_free, /* ditto */
|
||||
uint64_t *n_partitions) { /* ditto; UINT64_MAX if not determined */
|
||||
|
||||
int r;
|
||||
|
||||
@@ -747,7 +754,7 @@ static int invoke_repart(
|
||||
|
||||
r = connect_to_repart(link);
|
||||
if (r < 0) {
|
||||
read_space_metrics(/* v= */ NULL, min_size, current_size, need_free);
|
||||
read_repart_metrics(/* v= */ NULL, min_size, current_size, need_free, n_partitions);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -772,19 +779,19 @@ static int invoke_repart(
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("deferPartitionsEmpty", true),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("deferPartitionsFactoryReset", true));
|
||||
if (r < 0) {
|
||||
read_space_metrics(/* v= */ NULL, min_size, current_size, need_free);
|
||||
read_repart_metrics(/* v= */ NULL, min_size, current_size, need_free, n_partitions);
|
||||
return log_error_errno(r, "Failed to issue io.systemd.Repart.Run() varlink call: %m");
|
||||
}
|
||||
if (error_id) {
|
||||
if (streq(error_id, "io.systemd.Repart.InsufficientFreeSpace")) {
|
||||
(void) read_space_metrics(reply, min_size, current_size, need_free);
|
||||
(void) read_repart_metrics(reply, min_size, current_size, need_free, n_partitions);
|
||||
return log_full_errno(
|
||||
dry_run ? LOG_DEBUG : LOG_ERR,
|
||||
SYNTHETIC_ERRNO(ENOSPC),
|
||||
"Not enough free space on disk, cannot install.");
|
||||
}
|
||||
if (streq(error_id, "io.systemd.Repart.DiskTooSmall")) {
|
||||
(void) read_space_metrics(reply, min_size, current_size, need_free);
|
||||
(void) read_repart_metrics(reply, min_size, current_size, need_free, n_partitions);
|
||||
return log_full_errno(
|
||||
dry_run ? LOG_DEBUG : LOG_ERR,
|
||||
SYNTHETIC_ERRNO(E2BIG),
|
||||
@@ -792,7 +799,7 @@ static int invoke_repart(
|
||||
}
|
||||
|
||||
/* For all other errors reset the metrics */
|
||||
read_space_metrics(/* v= */ NULL, min_size, current_size, need_free);
|
||||
read_repart_metrics(/* v= */ NULL, min_size, current_size, need_free, n_partitions);
|
||||
|
||||
if (streq(error_id, "io.systemd.Repart.ConflictingDiskLabelPresent"))
|
||||
return log_full_errno(
|
||||
@@ -807,7 +814,7 @@ static int invoke_repart(
|
||||
return log_error_errno(r, "Failed to issue io.systemd.Repart.Run() varlink call: %s", error_id);
|
||||
}
|
||||
|
||||
(void) read_space_metrics(reply, min_size, current_size, need_free);
|
||||
(void) read_repart_metrics(reply, min_size, current_size, need_free, n_partitions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -903,6 +910,7 @@ static int prompt_confirm(void) {
|
||||
bool yes;
|
||||
r = prompt_loop_yes_no(arg_summary ? "Please type 'yes' to confirm the choices above and begin the installation" :
|
||||
"Please type 'yes' to begin the installation",
|
||||
/* prefill= */ NULL,
|
||||
/* def= */ false,
|
||||
&yes);
|
||||
if (r < 0)
|
||||
@@ -922,7 +930,8 @@ static int validate_run(sd_varlink **repart_link, const char *node) {
|
||||
/* First loop: either with explicitly configured --erase= value, or false. A second loop only if not configured explicitly. */
|
||||
bool try_erase = arg_erase > 0, conflicting_disk_label = false;
|
||||
for (;;) {
|
||||
uint64_t min_size = UINT64_MAX, current_size = UINT64_MAX, need_free = UINT64_MAX;
|
||||
uint64_t min_size = UINT64_MAX, current_size = UINT64_MAX, need_free = UINT64_MAX,
|
||||
n_partitions = UINT64_MAX;
|
||||
r = invoke_repart(
|
||||
repart_link,
|
||||
node,
|
||||
@@ -931,7 +940,8 @@ static int validate_run(sd_varlink **repart_link, const char *node) {
|
||||
arg_definitions,
|
||||
&min_size,
|
||||
¤t_size,
|
||||
&need_free);
|
||||
&need_free,
|
||||
&n_partitions);
|
||||
if (r == -ENOSPC) {
|
||||
/* The disk is large enough, but there's not enough unallocated space. Hence proceed, but require erasing */
|
||||
if (try_erase || arg_erase >= 0)
|
||||
@@ -969,9 +979,16 @@ static int validate_run(sd_varlink **repart_link, const char *node) {
|
||||
log_warning("A conflicting disk label has been found, and must be erased for installation.");
|
||||
|
||||
if (arg_erase < 0) {
|
||||
r = prompt_erase(/* can_add= */ !try_erase, &arg_erase);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (n_partitions == 0) {
|
||||
/* If the disk contains no partitions there's nothing worth preserving on
|
||||
* it, hence don't bother asking whether to erase it. */
|
||||
log_info("The selected disk contains no partitions, proceeding.");
|
||||
arg_erase = false;
|
||||
} else {
|
||||
r = prompt_erase(/* can_add= */ !try_erase, &arg_erase);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1753,7 +1770,8 @@ static int fetch_candidate_devices_reply(
|
||||
context->definitions,
|
||||
&min_size,
|
||||
¤t_size,
|
||||
&need_free);
|
||||
&need_free,
|
||||
/* n_partitions= */ NULL);
|
||||
|
||||
DeviceFit fit;
|
||||
if (r < 0) {
|
||||
@@ -2131,7 +2149,8 @@ static int run(int argc, char *argv[]) {
|
||||
arg_definitions,
|
||||
&min_size,
|
||||
/* current_size= */ NULL,
|
||||
/* need_free= */ NULL);
|
||||
/* need_free= */ NULL,
|
||||
/* n_partitions= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user