core: extend ActivateConnection to allow NULL connection paths

When called with a connection path, activates that connection.

When called without a connection path, picks the best available
connection to activate for that device.

Doesn't work with VPN connections because they don't have devices.
This commit is contained in:
Dan Williams 2013-07-24 10:41:39 -05:00
parent f4befaab00
commit 35124dbb14
2 changed files with 63 additions and 3 deletions

View file

@ -41,12 +41,17 @@
</tp:docstring>
<arg name="connection" type="o" direction="in">
<tp:docstring>
The connection to activate the devices with.
The connection to activate. If "/" is given, a valid device path must
be given, and NetworkManager picks the best connection to activate for
the given device. VPN connections must always pass a valid connection
path.
</tp:docstring>
</arg>
<arg name="device" type="o" direction="in">
<tp:docstring>
The object path of device to be activated for physical connections. This parameter is ignored for VPN connections, because the specific_object (if provided) specifies the device to use.
The object path of device to be activated for physical connections.
This parameter is ignored for VPN connections, because the
specific_object (if provided) specifies the device to use.
</tp:docstring>
</arg>
<arg name="specific_object" type="o" direction="in">
@ -55,7 +60,7 @@
This parameter is currently ignored for wired and mobile broadband connections,
and the value of "/" should be used (ie, no specific object). For WiFi
connections, pass the object path of a specific AP from the card's scan
list, or "/" to pick and AP automatically. For VPN connections, pass
list, or "/" to pick an AP automatically. For VPN connections, pass
the object path of an ActiveConnection object that should serve as the
"base" connection (to which the VPN connections lifetime will be tied),
or pass "/" and NM will automatically use the current default device.

View file

@ -3110,6 +3110,61 @@ impl_manager_activate_connection (NMManager *self,
gboolean is_vpn = FALSE;
GError *error = NULL;
/* Normalize object paths */
if (g_strcmp0 (connection_path, "/") == 0)
connection_path = NULL;
if (g_strcmp0 (specific_object_path, "/") == 0)
specific_object_path = NULL;
if (g_strcmp0 (device_path, "/") == 0)
device_path = NULL;
/* If the connection path is given and valid, that connection is activated.
* Otherwise the "best" connection for the device is chosen and activated,
* regardless of whether that connection is autoconnect-enabled or not
* (since this is an explicit request, not an auto-activation request).
*/
if (!connection_path) {
GPtrArray *available;
guint64 best_timestamp = 0;
guint i;
/* If no connection is given, find a suitable connection for the given device path */
if (!device_path) {
error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
"Only devices may be activated without a specifying a connection");
goto error;
}
device = nm_manager_get_device_by_path (self, device_path);
if (!device) {
error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
"Cannot activate unknown device %s", device_path);
goto error;
}
available = nm_device_get_available_connections (device, specific_object_path);
for (i = 0; available && i < available->len; i++) {
NMSettingsConnection *candidate = g_ptr_array_index (available, i);
guint64 candidate_timestamp = 0;
nm_settings_connection_get_timestamp (candidate, &candidate_timestamp);
if (!connection_path || (candidate_timestamp > best_timestamp)) {
connection_path = nm_connection_get_path (NM_CONNECTION (candidate));
best_timestamp = candidate_timestamp;
}
}
if (available)
g_ptr_array_free (available, TRUE);
if (!connection_path) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
"The device has no connections available.");
goto error;
}
}
g_assert (connection_path);
connection = (NMConnection *) nm_settings_get_connection_by_path (priv->settings, connection_path);
if (!connection) {
error = g_error_new_literal (NM_MANAGER_ERROR,