cli: add support for 'nmcli dev connect ifname XXX'

This commit is contained in:
Dan Williams
2013-09-16 21:03:34 -05:00
parent 42c7ea85a1
commit 7d57386e04
3 changed files with 171 additions and 19 deletions

View File

@@ -854,12 +854,13 @@ _nmcli()
;; ;;
d|de|dev|devi|devic|device) d|de|dev|devi|devic|device)
if [[ ${#words[@]} -eq 2 ]]; then if [[ ${#words[@]} -eq 2 ]]; then
_nmcli_list "status show disconnect wifi wimax help" _nmcli_list "status show connect disconnect wifi wimax help"
elif [[ ${#words[@]} -gt 2 ]]; then elif [[ ${#words[@]} -gt 2 ]]; then
case "$command" in case "$command" in
s|st|sta|stat|statu|status) s|st|sta|stat|statu|status)
;; ;;
sh|sho|show| \ sh|sho|show| \
c|co|con|conn|conne|connec|connect| \
d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect) d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect)
if [[ ${#words[@]} -eq 3 ]]; then if [[ ${#words[@]} -eq 3 ]]; then
_nmcli_list_nl "$(_nmcli_NM_devices)" _nmcli_list_nl "$(_nmcli_NM_devices)"

View File

@@ -262,12 +262,13 @@ usage (void)
fprintf (stderr, fprintf (stderr,
_("Usage: nmcli device { COMMAND | help }\n\n" _("Usage: nmcli device { COMMAND | help }\n\n"
#if WITH_WIMAX #if WITH_WIMAX
" COMMAND := { status | show | disconnect | wifi | wimax }\n\n" " COMMAND := { status | show | connect | disconnect | wifi | wimax }\n\n"
#else #else
" COMMAND := { status | show | disconnect | wifi }\n\n" " COMMAND := { status | show | connect | disconnect | wifi }\n\n"
#endif #endif
" status\n\n" " status\n\n"
" show [<ifname>]\n\n" " show [<ifname>]\n\n"
" connect <ifname>\n\n"
" disconnect <ifname>\n\n" " disconnect <ifname>\n\n"
" wifi [list [ifname <ifname>] [bssid <BSSID>]]\n\n" " wifi [list [ifname <ifname>] [bssid <BSSID>]]\n\n"
" wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>] [bssid <BSSID>] [name <name>]\n\n" " wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>] [bssid <BSSID>] [name <name>]\n\n"
@@ -1142,20 +1143,6 @@ error:
return nmc->return_value; return nmc->return_value;
} }
static void
device_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
{
NmCli *nmc = (NmCli *) user_data;
NMDeviceState state;
state = nm_device_get_state (device);
if (state == NM_DEVICE_STATE_DISCONNECTED) {
g_string_printf (nmc->return_text, _("Success: Device '%s' successfully disconnected."), nm_device_get_iface (device));
quit ();
}
}
static gboolean static gboolean
timeout_cb (gpointer user_data) timeout_cb (gpointer user_data)
{ {
@@ -1179,6 +1166,160 @@ progress_cb (gpointer user_data)
return TRUE; return TRUE;
} }
static void
connected_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
{
NmCli *nmc = (NmCli *) user_data;
NMDeviceState state;
state = nm_device_get_state (device);
if (state == NM_DEVICE_STATE_ACTIVATED) {
g_string_printf (nmc->return_text, _("Success: Device '%s' successfully activated."), nm_device_get_iface (device));
quit ();
}
}
static void
connect_device_cb (NMClient *client, NMActiveConnection *active, GError *error, gpointer user_data)
{
NmCli *nmc = (NmCli *) user_data;
const GPtrArray *devices;
NMDevice *device;
NMDeviceState state;
if (error) {
g_string_printf (nmc->return_text, _("Error: Device activation failed: %s"),
error->message ? error->message : _("(unknown)"));
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
quit ();
} else {
g_assert (active);
devices = nm_active_connection_get_devices (active);
g_assert (devices && devices->len);
device = g_ptr_array_index (devices, 0);
g_assert (device);
state = nm_device_get_state (device);
if (nmc->nowait_flag || state == NM_DEVICE_STATE_ACTIVATED) {
/* Don't want to wait or device already activated */
if (state == NM_DEVICE_STATE_ACTIVATED && nmc->print_output == NMC_PRINT_PRETTY) {
nmc_terminal_erase_line ();
printf (_("Device '%s' has been connected.\n"), nm_device_get_iface (device));
}
quit ();
} else {
g_signal_connect (device, "notify::state", G_CALLBACK (connected_state_cb), nmc);
/* Start timer not to loop forever if "notify::state" signal is not issued */
g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc);
}
}
}
static NMCResultCode
do_device_connect (NmCli *nmc, int argc, char **argv)
{
NMDevice **devices;
NMDevice *device = NULL;
const char *ifname = NULL;
char *ifname_ask = NULL;
int i;
/* Set default timeout for connect operation. */
if (nmc->timeout == -1)
nmc->timeout = 90;
if (argc == 0) {
if (nmc->ask) {
ifname = ifname_ask = nmc_get_user_input (_("Interface: "));
// TODO: list available devices when just Enter is pressed ?
}
if (!ifname_ask) {
g_string_printf (nmc->return_text, _("Error: No interface specified."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
goto error;
}
} else {
ifname = *argv;
}
if (!ifname) {
g_string_printf (nmc->return_text, _("Error: No interface specified."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
goto error;
}
if (next_arg (&argc, &argv) == 0) {
g_string_printf (nmc->return_text, _("Error: extra argument not allowed: '%s'."), *argv);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
goto error;
}
nmc->get_client (nmc);
if (!nm_client_get_manager_running (nmc->client)) {
g_string_printf (nmc->return_text, _("Error: NetworkManager is not running."));
nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING;
goto error;
}
if (!nmc_versions_match (nmc))
goto error;
devices = get_devices_sorted (nmc->client);
for (i = 0; devices[i]; i++) {
NMDevice *candidate = devices[i];
const char *dev_iface = nm_device_get_iface (candidate);
if (!g_strcmp0 (dev_iface, ifname))
device = candidate;
}
g_free (devices);
if (!device) {
g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), ifname);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
/*
* Use nowait_flag instead of should_wait, because exiting has to be postponed
* till connect_device_cb() is called, giving NM time to check our permissions.
*/
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
nm_client_activate_connection (nmc->client,
NULL, /* let NM find a connection automatically */
device,
NULL,
connect_device_cb,
nmc);
/* Start progress indication */
if (nmc->print_output == NMC_PRINT_PRETTY)
progress_id = g_timeout_add (120, progress_cb, device);
error:
g_free (ifname_ask);
return nmc->return_value;
}
static void
disconnect_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
{
NmCli *nmc = (NmCli *) user_data;
NMDeviceState state;
state = nm_device_get_state (device);
if (state == NM_DEVICE_STATE_DISCONNECTED) {
g_string_printf (nmc->return_text, _("Success: Device '%s' successfully disconnected."), nm_device_get_iface (device));
quit ();
}
}
static void static void
disconnect_device_cb (NMDevice *device, GError *error, gpointer user_data) disconnect_device_cb (NMDevice *device, GError *error, gpointer user_data)
{ {
@@ -1204,7 +1345,7 @@ disconnect_device_cb (NMDevice *device, GError *error, gpointer user_data)
} }
quit (); quit ();
} else { } else {
g_signal_connect (device, "notify::state", G_CALLBACK (device_state_cb), nmc); g_signal_connect (device, "notify::state", G_CALLBACK (disconnect_state_cb), nmc);
/* Start timer not to loop forever if "notify::state" signal is not issued */ /* Start timer not to loop forever if "notify::state" signal is not issued */
g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc); g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc);
} }
@@ -2296,6 +2437,9 @@ do_devices (NmCli *nmc, int argc, char **argv)
nmc->multiline_output = TRUE; /* multiline mode is default for 'device show' */ nmc->multiline_output = TRUE; /* multiline mode is default for 'device show' */
nmc->return_value = do_devices_show (nmc, argc-1, argv+1); nmc->return_value = do_devices_show (nmc, argc-1, argv+1);
} }
else if (matches (*argv, "connect") == 0) {
nmc->return_value = do_device_connect (nmc, argc-1, argv+1);
}
else if (matches (*argv, "disconnect") == 0) { else if (matches (*argv, "disconnect") == 0) {
nmc->return_value = do_device_disconnect (nmc, argc-1, argv+1); nmc->return_value = do_device_disconnect (nmc, argc-1, argv+1);
} }

View File

@@ -615,7 +615,7 @@ then \fINetworkManager\fP will reload connection files any time they change
.B device - show and manage network interfaces .B device - show and manage network interfaces
.br .br
.TP .TP
.SS \fICOMMAND\fP := { status | show | disconnect | wifi | wimax } .SS \fICOMMAND\fP := { status | show | connect | disconnect | wifi | wimax }
.sp .sp
.RS .RS
.TP .TP
@@ -631,6 +631,13 @@ Show detailed information about devices. Without an argument, all devices are
examined. To get information for a specific device, the interface name has examined. To get information for a specific device, the interface name has
to be provided. to be provided.
.TP .TP
.B connect <ifname>
.br
Connect the device. NetworkManager will try to find a suitable connection that
will be activated. It will also consider connections that are not set to auto connect.
.br
If '--wait' option is not specified, the default timeout will be 90 seconds.
.TP
.B disconnect <ifname> .B disconnect <ifname>
.br .br
Disconnect a device and prevent the device from automatically activating further Disconnect a device and prevent the device from automatically activating further