cli: don't allow multiple <ifname> arguments to device-reapply

Just like `nmcli device connect` only allows one argument, don't allow
multiple device arguments for reapply.

Allowing multiple device names makes it more complicated to add
additional options to the command. For example, it would be useful
to have a

    nmcli device reapply eth0 connection id other-connection

but when allowing multiple device names, it gets more complicated in
documentation, command line parsing and bash completion.

Note that the user can achieve a very similar outcome by using the
shell:

    for DEV in eth0 eth1 eth2; do
        nmcli device reapply $DEV &
    done
    wait

argubaly, this doesn't report the exit status properly. To properly
handle that would require more effort. Also, it is somewhat less
efficient, but well.

This is an API change, however it is very new API that probably nobody
is using much. Also, the documentation (man nmcli) didn't mention the
possibility to pass multiple device names.
This commit is contained in:
Thomas Haller 2016-04-30 14:14:31 +02:00
parent b217b68b80
commit d742ea7817
2 changed files with 32 additions and 51 deletions

View file

@ -286,7 +286,7 @@ usage (void)
" show [<ifname>]\n\n"
" set [ifname] <ifname> [autoconnect yes|no] [managed yes|no]\n\n"
" connect <ifname>\n\n"
" reapply <ifname> ...\n\n"
" reapply <ifname>\n\n"
" disconnect <ifname> ...\n\n"
" delete <ifname> ...\n\n"
" monitor <ifname> ...\n\n"
@ -342,7 +342,7 @@ usage_device_reapply (void)
{
g_printerr (_("Usage: nmcli device reapply { ARGUMENTS | help }\n"
"\n"
"ARGUMENTS := <ifname> ...\n"
"ARGUMENTS := <ifname>\n"
"\n"
"Attempts to update device with changes to the currently active connection\n"
"made since it was last applied.\n\n"));
@ -1835,11 +1835,10 @@ reapply_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
GError *error = NULL;
if (!nm_device_reapply_finish (device, result, &error)) {
g_string_printf (nmc->return_text, _("Error: not all connections reapplied."));
g_printerr (_("Error: Reapplying connection to device '%s' (%s) failed: %s\n"),
nm_device_get_iface (device),
nm_object_get_path (NM_OBJECT (device)),
error->message);
g_string_printf (nmc->return_text, _("Error: Reapplying connection to device '%s' (%s) failed: %s"),
nm_device_get_iface (device),
nm_object_get_path (NM_OBJECT (device)),
error->message);
g_error_free (error);
nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
device_cb_info_finish (info, device);
@ -1856,14 +1855,13 @@ static NMCResultCode
do_device_reapply (NmCli *nmc, int argc, char **argv)
{
gs_free NMDevice **devices = NULL;
NMDevice *device;
NMDevice *device = NULL;
DeviceCbInfo *info = NULL;
gs_free_slist GSList *queue = NULL;
GSList *iter;
gs_strfreev char **arg_arr = NULL;
char **arg_ptr = argv;
int arg_num = argc;
int i;
gs_free char *device_name_free = NULL;
const char *device_name = NULL;
/* Set default timeout for reapply operation. */
if (nmc->timeout == -1)
@ -1871,64 +1869,47 @@ do_device_reapply (NmCli *nmc, int argc, char **argv)
if (argc == 0) {
if (nmc->ask) {
char *line = nmc_readline (PROMPT_INTERFACES);
nmc_string_to_arg_array (line, NULL, FALSE, &arg_arr, &arg_num);
g_free (line);
arg_ptr = arg_arr;
device_name_free = nmc_readline (PROMPT_INTERFACE);
device_name = device_name_free;
}
if (arg_num == 0) {
if (!device_name) {
g_string_printf (nmc->return_text, _("Error: No interface specified."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return nmc->return_value;
}
} else if (argc == 1) {
device_name = arg_ptr[0];
next_arg (&arg_num, &arg_ptr);
} else {
next_arg (&arg_num, &arg_ptr);
g_string_printf (nmc->return_text, _("Error: unsupported argument '%s'."), *arg_ptr);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return nmc->return_value;
}
devices = get_devices_sorted (nmc->client);
while (arg_num > 0) {
device = NULL;
for (i = 0; devices[i]; i++) {
if (!g_strcmp0 (nm_device_get_iface (devices[i]), *arg_ptr)) {
device = devices[i];
break;
}
for (i = 0; devices[i]; i++) {
if (!g_strcmp0 (nm_device_get_iface (devices[i]), device_name)) {
device = devices[i];
break;
}
if (device) {
if (!g_slist_find (queue, device))
queue = g_slist_prepend (queue, device);
else
g_printerr (_("Warning: argument '%s' is duplicated.\n"), *arg_ptr);
} else {
g_printerr (_("Error: Device '%s' not found.\n"), *arg_ptr);
g_string_printf (nmc->return_text, _("Error: not all devices found."));
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
}
/* Take next argument */
next_arg (&arg_num, &arg_ptr);
}
if (!queue) {
g_string_printf (nmc->return_text, _("Error: no valid device provided."));
if (!device) {
g_string_printf (nmc->return_text, _("Error: device '%s' not found."), device_name);
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
return nmc->return_value;
}
queue = g_slist_reverse (queue);
info = g_slice_new0 (DeviceCbInfo);
info->nmc = nmc;
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
for (iter = queue; iter; iter = g_slist_next (iter)) {
device = iter->data;
info = g_slice_new0 (DeviceCbInfo);
info->nmc = nmc;
info->queue = g_slist_prepend (info->queue, g_object_ref (device));
info->queue = g_slist_prepend (info->queue, g_object_ref (device));
/* Now reapply the connection to the device */
nm_device_reapply_async (device, NULL, 0, 0, NULL, reapply_device_cb, info);
}
/* Now reapply the connection to the device */
nm_device_reapply_async (device, NULL, 0, 0, NULL, reapply_device_cb, info);
return nmc->return_value;
}

View file

@ -1425,12 +1425,12 @@ _nmcli()
fi
;;
sh|sho|show| \
r|re|rea|reap|reapp|reappl|reapply| \
c|co|con|conn|conne|connec|connect)
if [[ ${#words[@]} -eq 3 ]]; then
_nmcli_compl_COMMAND_nl "${words[2]}" "$(_nmcli_dev_status DEVICE)"
fi
;;
r|re|rea|reap|reapp|reappl|reapply| \
d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect| \
de|del|dele|delet|delete| \
m|mo|mon|moni|monit|monito|monitor)