summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2013-07-24 10:41:39 -0500
committerDan Williams <dcbw@redhat.com>2013-10-31 15:33:58 -0500
commit35124dbb1432693d650d835dde95d2d4a6e0b65f (patch)
tree3cf03b856388435877348b865080449acb9b6869
parentf4befaab00cb365456b25954c60faecd180e64c5 (diff)
downloadNetworkManager-35124dbb1432693d650d835dde95d2d4a6e0b65f.tar.gz
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.
-rw-r--r--introspection/nm-manager.xml11
-rw-r--r--src/nm-manager.c55
2 files changed, 63 insertions, 3 deletions
diff --git a/introspection/nm-manager.xml b/introspection/nm-manager.xml
index a3d6647926..e076e0516e 100644
--- a/introspection/nm-manager.xml
+++ b/introspection/nm-manager.xml
@@ -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.
diff --git a/src/nm-manager.c b/src/nm-manager.c
index af663c95ab..9b6a48fac2 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -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,