cli/connections: decide about activation success and failure in single place
Track both device and active connections at the same time and decide whether activation finished (either successfully or not) in a single place, check_activated(). This makes the already too complex code path a bit more straightforward and also makes it possible to be more reasonable about the diagnostics. Now that the active connection signals the reason, we include it; but if the failure is due to the device disconnection while we're activating, include a device reason instead, since it's often more useful. Like: Before: Error: Connection activation failed. Without considering the device: Error: Connection activation failed: the base network connection was interrupted After: Error: Connection activation failed: The Wi-Fi network could not be found
This commit is contained in:
@@ -2124,50 +2124,62 @@ typedef struct {
|
|||||||
static void activate_connection_info_finish (ActivateConnectionInfo *info);
|
static void activate_connection_info_finish (ActivateConnectionInfo *info);
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
vpn_connection_state_reason_to_string (NMVpnConnectionStateReason reason)
|
active_connection_state_reason_to_string (NMActiveConnectionStateReason reason)
|
||||||
{
|
{
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_UNKNOWN:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN:
|
||||||
return _("unknown reason");
|
return _("Unknown reason");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_NONE:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_NONE:
|
||||||
return _("none");
|
return _("The connection was disconnected");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED:
|
||||||
return _("the user was disconnected");
|
return _("Disconnected by user");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED:
|
||||||
return _("the base network connection was interrupted");
|
return _("The base network connection was interrupted");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED:
|
||||||
return _("the VPN service stopped unexpectedly");
|
return _("The VPN service stopped unexpectedly");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID:
|
||||||
return _("the VPN service returned invalid configuration");
|
return _("The VPN service returned invalid configuration");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT:
|
||||||
return _("the connection attempt timed out");
|
return _("The connection attempt timed out");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT:
|
||||||
return _("the VPN service did not start in time");
|
return _("The VPN service did not start in time");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED:
|
||||||
return _("the VPN service failed to start");
|
return _("The VPN service failed to start");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS:
|
||||||
return _("no valid VPN secrets");
|
return _("No valid secrets");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED:
|
||||||
return _("invalid VPN secrets");
|
return _("Invalid secrets");
|
||||||
case NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED:
|
||||||
return _("the connection was removed");
|
return _("The connection was removed");
|
||||||
default:
|
case NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED:
|
||||||
return _("unknown");
|
return _("Master connection failed");
|
||||||
|
case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED:
|
||||||
|
return _("Could not create a software link");
|
||||||
|
case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED:
|
||||||
|
return _("The device disappeared");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (_("Invalid reason"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
device_state_cb (NMDevice *device, GParamSpec *pspec, ActivateConnectionInfo *info)
|
check_activated (ActivateConnectionInfo *info)
|
||||||
{
|
{
|
||||||
NmCli *nmc = info->nmc;
|
NmCli *nmc = info->nmc;
|
||||||
NMActiveConnection *active;
|
NMDevice *device = info->device;
|
||||||
NMDeviceState state;
|
NMActiveConnection *active = info->active;
|
||||||
NMActiveConnectionState ac_state;
|
NMActiveConnectionState ac_state;
|
||||||
|
NMActiveConnectionStateReason ac_reason;
|
||||||
|
NMDeviceState dev_state;
|
||||||
|
NMDeviceStateReason dev_reason;
|
||||||
|
|
||||||
active = nm_device_get_active_connection (device);
|
ac_state = nm_active_connection_get_state (active);
|
||||||
state = nm_device_get_state (device);
|
ac_reason = nm_active_connection_get_state_reason (active);
|
||||||
|
|
||||||
ac_state = active ? nm_active_connection_get_state (active) : NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
|
if (device) {
|
||||||
|
dev_state = nm_device_get_state (device);
|
||||||
|
dev_reason = nm_device_get_state_reason (device);
|
||||||
|
}
|
||||||
|
|
||||||
if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY)
|
if (nmc->print_output == NMC_PRINT_PRETTY)
|
||||||
@@ -2175,53 +2187,27 @@ device_state_cb (NMDevice *device, GParamSpec *pspec, ActivateConnectionInfo *in
|
|||||||
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
||||||
nm_object_get_path (NM_OBJECT (active)));
|
nm_object_get_path (NM_OBJECT (active)));
|
||||||
activate_connection_info_finish (info);
|
activate_connection_info_finish (info);
|
||||||
} else if ( ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
|
} else if (ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
|
||||||
&& state >= NM_DEVICE_STATE_IP_CONFIG
|
if (device && ac_reason == NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED) {
|
||||||
&& state <= NM_DEVICE_STATE_ACTIVATED) {
|
if (dev_state == NM_DEVICE_STATE_FAILED || dev_state == NM_DEVICE_STATE_DISCONNECTED) {
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY)
|
g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"),
|
||||||
nmc_terminal_erase_line ();
|
nmc_device_reason_to_string (dev_reason));
|
||||||
g_print (_("Connection successfully activated (master waiting for slaves) (D-Bus active path: %s)\n"),
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
||||||
nm_object_get_path (NM_OBJECT (active)));
|
activate_connection_info_finish (info);
|
||||||
activate_connection_info_finish (info);
|
} else {
|
||||||
}
|
/* Just wait for the device to go failed. We'll get a better error message. */
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
static void
|
} else {
|
||||||
active_connection_removed_cb (NMClient *client, NMActiveConnection *active, ActivateConnectionInfo *info)
|
g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s"),
|
||||||
{
|
active_connection_state_reason_to_string (ac_reason));
|
||||||
NmCli *nmc = info->nmc;
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
||||||
|
activate_connection_info_finish (info);
|
||||||
if (active == info->active) {
|
}
|
||||||
g_string_printf (nmc->return_text, _("Error: Connection activation failed."));
|
} else if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) {
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
|
||||||
activate_connection_info_finish (info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
active_connection_state_cb (NMActiveConnection *active, GParamSpec *pspec, ActivateConnectionInfo *info)
|
|
||||||
{
|
|
||||||
NmCli *nmc = info->nmc;
|
|
||||||
NMActiveConnectionState state;
|
|
||||||
|
|
||||||
state = nm_active_connection_get_state (active);
|
|
||||||
|
|
||||||
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY)
|
|
||||||
nmc_terminal_erase_line ();
|
|
||||||
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
|
|
||||||
nm_object_get_path (NM_OBJECT (active)));
|
|
||||||
activate_connection_info_finish (info);
|
|
||||||
} else if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
|
|
||||||
g_string_printf (nmc->return_text, _("Error: Connection activation failed."));
|
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
|
||||||
activate_connection_info_finish (info);
|
|
||||||
} else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) {
|
|
||||||
/* activating master connection does not automatically activate any slaves, so their
|
/* activating master connection does not automatically activate any slaves, so their
|
||||||
* active connection state will not progress beyond ACTIVATING state.
|
* active connection state will not progress beyond ACTIVATING state.
|
||||||
* Monitor the device instead. */
|
* Monitor the device instead. */
|
||||||
const GPtrArray *devices;
|
|
||||||
NMDevice *device;
|
|
||||||
|
|
||||||
if (nmc->secret_agent) {
|
if (nmc->secret_agent) {
|
||||||
NMRemoteConnection *connection = nm_active_connection_get_connection (active);
|
NMRemoteConnection *connection = nm_active_connection_get_connection (active);
|
||||||
@@ -2230,53 +2216,34 @@ active_connection_state_cb (NMActiveConnection *active, GParamSpec *pspec, Activ
|
|||||||
nm_connection_get_path (NM_CONNECTION (connection)));
|
nm_connection_get_path (NM_CONNECTION (connection)));
|
||||||
}
|
}
|
||||||
|
|
||||||
devices = nm_active_connection_get_devices (active);
|
|
||||||
device = devices->len ? g_ptr_array_index (devices, 0) : NULL;
|
|
||||||
if ( device
|
if ( device
|
||||||
&& ( NM_IS_DEVICE_BOND (device)
|
&& ( NM_IS_DEVICE_BOND (device)
|
||||||
|| NM_IS_DEVICE_TEAM (device)
|
|| NM_IS_DEVICE_TEAM (device)
|
||||||
|| NM_IS_DEVICE_BRIDGE (device))) {
|
|| NM_IS_DEVICE_BRIDGE (device))
|
||||||
g_signal_connect (device, "notify::" NM_DEVICE_STATE, G_CALLBACK (device_state_cb), info);
|
&& dev_state >= NM_DEVICE_STATE_IP_CONFIG
|
||||||
device_state_cb (device, NULL, info);
|
&& dev_state <= NM_DEVICE_STATE_ACTIVATED) {
|
||||||
|
if (nmc->print_output == NMC_PRINT_PRETTY)
|
||||||
|
nmc_terminal_erase_line ();
|
||||||
|
g_print (_("Connection successfully activated (master waiting for slaves) (D-Bus active path: %s)\n"),
|
||||||
|
nm_object_get_path (NM_OBJECT (active)));
|
||||||
|
activate_connection_info_finish (info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vpn_connection_state_cb (NMVpnConnection *vpn,
|
device_state_cb (NMDevice *device, GParamSpec *pspec, ActivateConnectionInfo *info)
|
||||||
NMVpnConnectionState state,
|
|
||||||
NMVpnConnectionStateReason reason,
|
|
||||||
ActivateConnectionInfo *info)
|
|
||||||
{
|
{
|
||||||
NmCli *nmc = info->nmc;
|
check_activated (info);
|
||||||
|
}
|
||||||
|
|
||||||
switch (state) {
|
static void
|
||||||
case NM_VPN_CONNECTION_STATE_PREPARE:
|
active_connection_state_cb (NMActiveConnection *active,
|
||||||
case NM_VPN_CONNECTION_STATE_NEED_AUTH:
|
NMActiveConnectionState state,
|
||||||
case NM_VPN_CONNECTION_STATE_CONNECT:
|
NMActiveConnectionStateReason reason,
|
||||||
case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET:
|
ActivateConnectionInfo *info)
|
||||||
/* no operation */
|
{
|
||||||
break;
|
check_activated (info);
|
||||||
|
|
||||||
case NM_VPN_CONNECTION_STATE_ACTIVATED:
|
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY)
|
|
||||||
nmc_terminal_erase_line ();
|
|
||||||
g_print (_("VPN connection successfully activated (D-Bus active path: %s)\n"),
|
|
||||||
nm_object_get_path (NM_OBJECT (vpn)));
|
|
||||||
activate_connection_info_finish (info);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NM_VPN_CONNECTION_STATE_FAILED:
|
|
||||||
case NM_VPN_CONNECTION_STATE_DISCONNECTED:
|
|
||||||
g_string_printf (nmc->return_text, _("Error: Connection activation failed: %s."),
|
|
||||||
vpn_connection_state_reason_to_string (reason));
|
|
||||||
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
|
||||||
activate_connection_info_finish (info);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2308,24 +2275,28 @@ progress_cb (gpointer user_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
progress_device_cb (gpointer user_data)
|
progress_active_connection_cb (gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDevice *device = (NMDevice *) user_data;
|
NMActiveConnection *active = user_data;
|
||||||
|
|
||||||
nmc_terminal_show_progress (device ? nmc_device_state_to_string (nm_device_get_state (device)) : "");
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
progress_vpn_cb (gpointer user_data)
|
|
||||||
{
|
|
||||||
NMVpnConnection *vpn = (NMVpnConnection *) user_data;
|
|
||||||
const char *str;
|
const char *str;
|
||||||
|
NMDevice *device;
|
||||||
|
NMActiveConnectionState ac_state;
|
||||||
|
const GPtrArray *ac_devs;
|
||||||
|
|
||||||
str = NM_IS_VPN_CONNECTION (vpn) ?
|
ac_state = nm_active_connection_get_state (active);
|
||||||
vpn_connection_state_to_string (nm_vpn_connection_get_vpn_state (vpn)) :
|
|
||||||
"";
|
if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING) {
|
||||||
|
/* If the connection is activating, the device state
|
||||||
|
* is more interesting. */
|
||||||
|
ac_devs = nm_active_connection_get_devices (active);
|
||||||
|
device = ac_devs->len > 0 ? g_ptr_array_index (ac_devs, 0) : NULL;
|
||||||
|
} else {
|
||||||
|
device = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = device
|
||||||
|
? nmc_device_state_to_string (nm_device_get_state (device))
|
||||||
|
: active_connection_state_to_string (ac_state);
|
||||||
|
|
||||||
nmc_terminal_show_progress (str);
|
nmc_terminal_show_progress (str);
|
||||||
|
|
||||||
@@ -2341,14 +2312,9 @@ activate_connection_info_finish (ActivateConnectionInfo *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (info->active) {
|
if (info->active) {
|
||||||
if (NM_IS_VPN_CONNECTION (info->active))
|
g_signal_handlers_disconnect_by_func (info->active, G_CALLBACK (active_connection_state_cb), info);
|
||||||
g_signal_handlers_disconnect_by_func (info->active, G_CALLBACK (vpn_connection_state_cb), info);
|
|
||||||
else
|
|
||||||
g_signal_handlers_disconnect_by_func (info->active, G_CALLBACK (active_connection_state_cb), info);
|
|
||||||
g_object_unref (info->active);
|
g_object_unref (info->active);
|
||||||
|
|
||||||
}
|
}
|
||||||
g_signal_handlers_disconnect_by_func (info->nmc->client, G_CALLBACK (active_connection_removed_cb), info);
|
|
||||||
|
|
||||||
g_free (info);
|
g_free (info);
|
||||||
quit ();
|
quit ();
|
||||||
@@ -2393,34 +2359,27 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
|
|||||||
}
|
}
|
||||||
activate_connection_info_finish (info);
|
activate_connection_info_finish (info);
|
||||||
} else {
|
} else {
|
||||||
if (NM_IS_VPN_CONNECTION (active)) {
|
/* Monitor the active connection state state */
|
||||||
/* Monitor VPN state */
|
g_signal_connect (G_OBJECT (active), "state-changed", G_CALLBACK (active_connection_state_cb), info);
|
||||||
g_signal_connect (G_OBJECT (active), "vpn-state-changed", G_CALLBACK (vpn_connection_state_cb), info);
|
active_connection_state_cb (active,
|
||||||
|
nm_active_connection_get_state (active),
|
||||||
|
nm_active_connection_get_state_reason (active),
|
||||||
|
info);
|
||||||
|
|
||||||
/* Start progress indication showing VPN states */
|
if (device) {
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY) {
|
g_signal_connect (device, "notify::" NM_DEVICE_STATE, G_CALLBACK (device_state_cb), info);
|
||||||
if (progress_id)
|
device_state_cb (device, NULL, info);
|
||||||
g_source_remove (progress_id);
|
}
|
||||||
progress_id = g_timeout_add (120, progress_vpn_cb, NM_VPN_CONNECTION (active));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g_signal_connect (active, "notify::state", G_CALLBACK (active_connection_state_cb), info);
|
|
||||||
active_connection_state_cb (active, NULL, info);
|
|
||||||
|
|
||||||
/* Start progress indication showing device states */
|
/* Start progress indication showing VPN states */
|
||||||
if (nmc->print_output == NMC_PRINT_PRETTY) {
|
if (nmc->print_output == NMC_PRINT_PRETTY) {
|
||||||
if (progress_id)
|
if (progress_id)
|
||||||
g_source_remove (progress_id);
|
g_source_remove (progress_id);
|
||||||
progress_id = g_timeout_add (120, progress_device_cb, device);
|
progress_id = g_timeout_add (120, progress_active_connection_cb, active);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start timer not to loop forever when signals are not emitted */
|
/* Start timer not to loop forever when signals are not emitted */
|
||||||
g_timeout_add_seconds (nmc->timeout, activate_connection_timeout_cb, info);
|
g_timeout_add_seconds (nmc->timeout, activate_connection_timeout_cb, info);
|
||||||
|
|
||||||
/* Fail when the active connection goes away. */
|
|
||||||
g_signal_connect (nmc->client, NM_CLIENT_ACTIVE_CONNECTION_REMOVED,
|
|
||||||
G_CALLBACK (active_connection_removed_cb), info);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user