summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2016-09-26 15:10:44 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2016-09-26 15:10:44 +0200
commitd27ae4a8fec0c8f21a7171e01535f8beb8e5b105 (patch)
tree3732c92ac529d7e685bab5c43b75cc1a798877e2
parent5b8c092d6be5251695fb59ff0821ab0161438966 (diff)
parent45f72c8cc12338a4a0300d7040be45ecaae0b2d6 (diff)
downloadNetworkManager-d27ae4a8fec0c8f21a7171e01535f8beb8e5b105.tar.gz
checkpoint: merge branch 'bg/checkpoint-improvements-bgo770315'
https://bugzilla.gnome.org/show_bug.cgi?id=770315
-rwxr-xr-xexamples/python/dbus/checkpoint.py56
-rw-r--r--introspection/nm-manager.xml2
-rw-r--r--src/nm-activation-request.c6
-rw-r--r--src/nm-activation-request.h1
-rw-r--r--src/nm-active-connection.c27
-rw-r--r--src/nm-active-connection.h1
-rw-r--r--src/nm-checkpoint-manager.c13
-rw-r--r--src/nm-checkpoint.c140
-rw-r--r--src/nm-manager.c40
-rw-r--r--src/nm-manager.h2
-rw-r--r--src/nm-policy.c3
11 files changed, 189 insertions, 102 deletions
diff --git a/examples/python/dbus/checkpoint.py b/examples/python/dbus/checkpoint.py
index 72a9a414dc..6e57f9c68b 100755
--- a/examples/python/dbus/checkpoint.py
+++ b/examples/python/dbus/checkpoint.py
@@ -20,36 +20,48 @@
import dbus, sys
-# This example takes a device interface name as a parameter and tells
-# NetworkManager to disconnect that device, closing down any network
-# connection it may have
-
-if len(sys.argv) != 2:
- raise Exception("Usage: %s <interface>" % sys.argv[0])
-
-bus = dbus.SystemBus()
+# This example takes a list of device interface names as a parameter
+# and tells NetworkManager to create a checkpoint on those devices. It
+# is then possible to restore or destroy the checkpoint.
# Get a proxy for the base NetworkManager object
+bus = dbus.SystemBus()
proxy = bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager")
manager = dbus.Interface(proxy, "org.freedesktop.NetworkManager")
+allDevs = manager.GetDevices()
+
+def Usage():
+ print "Usage: %s <ROLLBACK-INTERVAL> [INTERFACE]..." % sys.argv[0]
+ sys.exit(1)
+
+def GetDevicePath(ifname):
+ for dev in allDevs:
+ dev_proxy = bus.get_object("org.freedesktop.NetworkManager", dev)
+ prop_iface = dbus.Interface(dev_proxy, "org.freedesktop.DBus.Properties")
+ interface = prop_iface.Get("org.freedesktop.NetworkManager.Device", "Interface")
+ if interface == ifname:
+ return dev
+ return
+
+if len(sys.argv) < 2:
+ Usage()
-dpath = None
+try:
+ interval = int(sys.argv[1])
+except ValueError:
+ Usage()
-# Find the device
-devices = manager.GetDevices()
-for d in devices:
- dev_proxy = bus.get_object("org.freedesktop.NetworkManager", d)
- prop_iface = dbus.Interface(dev_proxy, "org.freedesktop.DBus.Properties")
- iface = prop_iface.Get("org.freedesktop.NetworkManager.Device", "Interface")
- if iface == sys.argv[1]:
- dpath = d
- break
+devList = []
-if not dpath or not len(dpath):
- raise Exception("NetworkManager knows nothing about %s" % sys.argv[1])
+for arg in sys.argv[2:]:
+ path = GetDevicePath(arg)
+ if path == None:
+ raise Exception("NetworkManager knows nothing about %s" % arg)
+ else:
+ devList.append(path)
-checkpoint = manager.CheckpointCreate([ dpath ],
- 0, # no rollback
+checkpoint = manager.CheckpointCreate(devList,
+ interval,
1); # DESTROY_ALL
choice = raw_input('Do you want to rollback [y/n]? ').lower()
diff --git a/introspection/nm-manager.xml b/introspection/nm-manager.xml
index 0537e86533..1c29936285 100644
--- a/introspection/nm-manager.xml
+++ b/introspection/nm-manager.xml
@@ -209,7 +209,7 @@
<!--
CheckpointCreate:
- @devices: a list of device paths for which a checkpoint should be created. An empty list means all managed devices.
+ @devices: a list of device paths for which a checkpoint should be created. An empty list means all devices.
@rollback_timeout: the time in seconds until NetworkManager will automatically rollback to the checkpoint. Set to zero for infinite.
@flags: optional flags that influence the creation.
@checkpoint: on success, returns the path of the checkpoint.
diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c
index 22fa5b6910..6da89432a8 100644
--- a/src/nm-activation-request.c
+++ b/src/nm-activation-request.c
@@ -462,17 +462,20 @@ master_failed (NMActiveConnection *self)
* nm_act_request_new:
*
* @settings_connection: (allow-none): the connection to activate @device with
+ * @applied_connection: (allow-none): the applied connection
* @specific_object: the object path of the specific object (ie, WiFi access point,
* etc) that will be used to activate @connection and @device
* @subject: the #NMAuthSubject representing the requestor of the activation
* @device: the device/interface to configure according to @connection
*
- * Creates a new device-based activation request.
+ * Creates a new device-based activation request. If an applied connection is
+ * supplied, it shall not be modified by the caller afterwards.
*
* Returns: the new activation request on success, %NULL on error.
*/
NMActRequest *
nm_act_request_new (NMSettingsConnection *settings_connection,
+ NMConnection *applied_connection,
const char *specific_object,
NMAuthSubject *subject,
NMDevice *device)
@@ -482,6 +485,7 @@ nm_act_request_new (NMSettingsConnection *settings_connection,
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
return (NMActRequest *) g_object_new (NM_TYPE_ACT_REQUEST,
+ NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION, applied_connection,
NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, settings_connection,
NM_ACTIVE_CONNECTION_INT_DEVICE, device,
NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object,
diff --git a/src/nm-activation-request.h b/src/nm-activation-request.h
index 1bd004994e..5a170d8976 100644
--- a/src/nm-activation-request.h
+++ b/src/nm-activation-request.h
@@ -46,6 +46,7 @@ typedef struct {
GType nm_act_request_get_type (void);
NMActRequest *nm_act_request_new (NMSettingsConnection *settings_connection,
+ NMConnection *applied_connection,
const char *specific_object,
NMAuthSubject *subject,
NMDevice *device);
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index 1844587c67..503c53191b 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -90,6 +90,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection,
PROP_MASTER,
PROP_INT_SETTINGS_CONNECTION,
+ PROP_INT_APPLIED_CONNECTION,
PROP_INT_DEVICE,
PROP_INT_SUBJECT,
PROP_INT_MASTER,
@@ -951,6 +952,14 @@ constructed (GObject *object)
G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
+ if (!priv->applied_connection && priv->settings_connection) {
+ priv->applied_connection =
+ nm_simple_connection_new_clone ((NMConnection *) priv->settings_connection);
+ }
+
+ if (priv->applied_connection)
+ nm_connection_clear_secrets (priv->applied_connection);
+
_LOGD ("constructed (%s, version-id %llu)", G_OBJECT_TYPE_NAME (self), (long long unsigned) priv->version_id);
g_return_if_fail (priv->subject);
@@ -964,16 +973,20 @@ set_property (GObject *object, guint prop_id,
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
const char *tmp;
NMSettingsConnection *con;
+ NMConnection *acon;
switch (prop_id) {
case PROP_INT_SETTINGS_CONNECTION:
/* construct-only */
con = g_value_get_object (value);
- if (con) {
+ if (con)
_set_settings_connection (self, con);
- priv->applied_connection = nm_simple_connection_new_clone ((NMConnection *) priv->settings_connection);
- nm_connection_clear_secrets (priv->applied_connection);
- }
+ break;
+ case PROP_INT_APPLIED_CONNECTION:
+ /* construct-only */
+ acon = g_value_get_object (value);
+ if (acon)
+ priv->applied_connection = g_object_ref (acon);
break;
case PROP_INT_DEVICE:
/* construct-only */
@@ -1259,6 +1272,12 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_INT_APPLIED_CONNECTION] =
+ g_param_spec_object (NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION, "", "",
+ NM_TYPE_CONNECTION,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
obj_properties[PROP_INT_DEVICE] =
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_DEVICE, "", "",
NM_TYPE_DEVICE,
diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h
index a66f8e9ffc..42e45a2bf1 100644
--- a/src/nm-active-connection.h
+++ b/src/nm-active-connection.h
@@ -50,6 +50,7 @@
/* Internal non-exported properties */
#define NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION "int-settings-connection"
+#define NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION "int-applied-connection"
#define NM_ACTIVE_CONNECTION_INT_DEVICE "int-device"
#define NM_ACTIVE_CONNECTION_INT_SUBJECT "int-subject"
#define NM_ACTIVE_CONNECTION_INT_MASTER "int-master"
diff --git a/src/nm-checkpoint-manager.c b/src/nm-checkpoint-manager.c
index 254dc31e3d..49e8b89595 100644
--- a/src/nm-checkpoint-manager.c
+++ b/src/nm-checkpoint-manager.c
@@ -145,19 +145,27 @@ nm_checkpoint_manager_create (NMCheckpointManager *self,
NMCheckpointCreateFlags flags,
GError **error)
{
+ NMManager *manager;
NMCheckpoint *checkpoint;
const char * const *path;
gs_unref_ptrarray GPtrArray *devices = NULL;
NMDevice *device;
const char *checkpoint_path;
+ gs_free const char **device_paths_free = NULL;
guint i;
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (!error || !*error, FALSE);
+ manager = GET_MANAGER (self);
+
+ if (!device_paths || !device_paths[0]) {
+ device_paths_free = nm_manager_get_device_paths (manager);
+ device_paths = (const char *const *) device_paths_free;
+ }
devices = g_ptr_array_new ();
for (path = device_paths; *path; path++) {
- device = nm_manager_get_device_by_path (GET_MANAGER (self), *path);
+ device = nm_manager_get_device_by_path (manager, *path);
if (!device) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
"device %s does not exist", *path);
@@ -178,8 +186,7 @@ nm_checkpoint_manager_create (NMCheckpointManager *self,
}
}
- checkpoint = nm_checkpoint_new (GET_MANAGER (self), devices,
- rollback_timeout, error);
+ checkpoint = nm_checkpoint_new (manager, devices, rollback_timeout, error);
if (!checkpoint)
return NULL;
diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c
index 605e0700be..8869204d72 100644
--- a/src/nm-checkpoint.c
+++ b/src/nm-checkpoint.c
@@ -55,7 +55,11 @@
typedef struct {
char *original_dev_path;
NMDevice *device;
- NMConnection *connection;
+ NMConnection *applied_connection;
+ NMConnection *settings_connection;
+ NMDeviceState state;
+ bool realized:1;
+ bool unmanaged_explicit:1;
} DeviceCheckpoint;
typedef struct {
@@ -122,47 +126,75 @@ nm_checkpoint_rollback (NMCheckpoint *self)
while (g_hash_table_iter_next (&iter, (gpointer *) &device, (gpointer *) &dev_checkpoint)) {
gs_unref_object NMAuthSubject *subject = NULL;
guint32 result = NM_ROLLBACK_RESULT_OK;
- const char *con_path;
-
- _LOGD ("rollback: restoring state of device %s", nm_device_get_iface (device));
-
- if (!nm_device_is_real (device)) {
- result = NM_ROLLBACK_RESULT_ERR_NO_DEVICE;
- _LOGD ("rollback: device is not realized");
+ const char *con_uuid;
+
+ _LOGD ("rollback: restoring device %s (state %d, realized %d, explicitly unmanaged %d)",
+ nm_device_get_iface (device),
+ (int) dev_checkpoint->state,
+ dev_checkpoint->realized,
+ dev_checkpoint->unmanaged_explicit);
+
+ if (nm_device_is_real (device)) {
+ if (!dev_checkpoint->realized) {
+ _LOGD ("rollback: device was not realized, unmanage it");
+ nm_device_set_unmanaged_by_flags_queue (device,
+ NM_UNMANAGED_USER_EXPLICIT,
+ TRUE,
+ NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
+ goto next_dev;
+ }
+ } else {
+ if (dev_checkpoint->realized) {
+ if (nm_device_is_software (device)) {
+ /* try to recreate software device */
+ _LOGD ("rollback: software device not realized, will re-activate");
+ goto activate;
+ } else {
+ _LOGD ("rollback: device is not realized");
+ result = NM_ROLLBACK_RESULT_ERR_FAILED;
+ }
+ }
goto next_dev;
}
- if (nm_device_get_state (device) <= NM_DEVICE_STATE_UNMANAGED) {
- result = NM_ROLLBACK_RESULT_ERR_DEVICE_UNMANAGED;
- _LOGD ("rollback: device is unmanaged");
+activate:
+ if (dev_checkpoint->state == NM_DEVICE_STATE_UNMANAGED) {
+ if ( nm_device_get_state (device) != NM_DEVICE_STATE_UNMANAGED
+ || dev_checkpoint->unmanaged_explicit) {
+ _LOGD ("rollback: explicitly unmanage device");
+ nm_device_set_unmanaged_by_flags_queue (device,
+ NM_UNMANAGED_USER_EXPLICIT,
+ TRUE,
+ NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
+ }
goto next_dev;
}
- if (dev_checkpoint->connection) {
+ if (dev_checkpoint->applied_connection) {
/* The device had an active connection, check if the
* connection still exists
* */
- con_path = nm_connection_get_path (dev_checkpoint->connection);
- connection = nm_settings_get_connection_by_path (nm_settings_get(), con_path);
+ con_uuid = nm_connection_get_uuid (dev_checkpoint->settings_connection);
+ connection = nm_settings_get_connection_by_uuid (nm_settings_get (), con_uuid);
if (connection) {
/* If the connection is still there, restore its content
* and save it
* */
- _LOGD ("rollback: connection %s still exists", con_path);
+ _LOGD ("rollback: connection %s still exists", con_uuid);
nm_connection_replace_settings_from_connection (NM_CONNECTION (connection),
- dev_checkpoint->connection);
+ dev_checkpoint->settings_connection);
nm_settings_connection_commit_changes (connection,
NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE,
NULL,
NULL);
} else {
/* The connection was deleted, recreate it */
- _LOGD ("rollback: adding connection %s again", con_path);
+ _LOGD ("rollback: adding connection %s again", con_uuid);
connection = nm_settings_add_connection (nm_settings_get (),
- dev_checkpoint->connection,
+ dev_checkpoint->settings_connection,
TRUE,
&local_error);
if (!connection) {
@@ -177,6 +209,7 @@ nm_checkpoint_rollback (NMCheckpoint *self)
subject = nm_auth_subject_new_internal ();
if (!nm_manager_activate_connection (priv->manager,
connection,
+ dev_checkpoint->applied_connection,
NULL,
device,
subject,
@@ -213,36 +246,32 @@ device_checkpoint_create (NMDevice *device,
GError **error)
{
DeviceCheckpoint *dev_checkpoint;
- NMConnection *connection;
+ NMConnection *applied_connection;
+ NMSettingsConnection *settings_connection;
const char *path;
-
- if (!nm_device_is_real (device)) {
- g_set_error (error,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_INVALID_ARGUMENTS,
- "device '%s' is not realized",
- nm_device_get_iface (device));
- return NULL;
- }
-
- if (nm_device_get_state (device) <= NM_DEVICE_STATE_UNMANAGED) {
- g_set_error (error,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_INVALID_ARGUMENTS,
- "device '%s' is unmanaged",
- nm_device_get_iface (device));
- return NULL;
- }
+ gboolean unmanaged_explicit;
path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (device));
+ unmanaged_explicit = !!nm_device_get_unmanaged_flags (device,
+ NM_UNMANAGED_USER_EXPLICIT);
dev_checkpoint = g_slice_new0 (DeviceCheckpoint);
dev_checkpoint->device = g_object_ref (device);
dev_checkpoint->original_dev_path = g_strdup (path);
-
- connection = nm_device_get_applied_connection (device);
- if (connection)
- dev_checkpoint->connection = nm_simple_connection_new_clone (connection);
+ dev_checkpoint->state = nm_device_get_state (device);
+ dev_checkpoint->realized = nm_device_is_real (device);
+ dev_checkpoint->unmanaged_explicit = unmanaged_explicit;
+
+ applied_connection = nm_device_get_applied_connection (device);
+ if (applied_connection) {
+ dev_checkpoint->applied_connection =
+ nm_simple_connection_new_clone (applied_connection);
+
+ settings_connection = nm_device_get_settings_connection (device);
+ g_return_val_if_fail (settings_connection, NULL);
+ dev_checkpoint->settings_connection =
+ nm_simple_connection_new_clone (NM_CONNECTION (settings_connection));
+ }
return dev_checkpoint;
}
@@ -252,7 +281,8 @@ device_checkpoint_destroy (gpointer data)
{
DeviceCheckpoint *dev_checkpoint = data;
- g_clear_object (&dev_checkpoint->connection);
+ g_clear_object (&dev_checkpoint->applied_connection);
+ g_clear_object (&dev_checkpoint->settings_connection);
g_clear_object (&dev_checkpoint->device);
g_free (dev_checkpoint->original_dev_path);
@@ -268,29 +298,6 @@ nm_checkpoint_init (NMCheckpoint *self)
NULL, device_checkpoint_destroy);
}
-static void
-get_all_devices (NMManager *manager, GPtrArray *devices)
-{
- const GSList *list, *iter;
- NMDevice *dev;
-
- list = nm_manager_get_devices (manager);
-
- for (iter = list; iter; iter = g_slist_next (iter)) {
- dev = iter->data;
-
- if (!nm_device_is_real (dev))
- continue;
- if (nm_device_get_state (dev) <= NM_DEVICE_STATE_UNMANAGED)
- continue;
- /* We never touch assumed connections, unless told explicitly */
- if (nm_device_uses_assumed_connection (dev))
- continue;
-
- g_ptr_array_add (devices, dev);
- }
-}
-
NMCheckpoint *
nm_checkpoint_new (NMManager *manager, GPtrArray *devices, guint32 rollback_timeout,
GError **error)
@@ -305,9 +312,6 @@ nm_checkpoint_new (NMManager *manager, GPtrArray *devices, guint32 rollback_time
g_return_val_if_fail (devices, NULL);
g_return_val_if_fail (!error || !*error, NULL);
- if (!devices->len)
- get_all_devices (manager, devices);
-
if (!devices->len) {
g_set_error_literal (error,
NM_MANAGER_ERROR,
diff --git a/src/nm-manager.c b/src/nm-manager.c
index dfbe10c049..9d536e358b 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -64,6 +64,7 @@ static gboolean add_device (NMManager *self, NMDevice *device, GError **error);
static NMActiveConnection *_new_active_connection (NMManager *self,
NMConnection *connection,
+ NMConnection *applied,
const char *specific_object,
NMDevice *device,
NMAuthSubject *subject,
@@ -1745,7 +1746,7 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn
g_return_val_if_fail (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
subject = nm_auth_subject_new_internal ();
- active = _new_active_connection (self, NM_CONNECTION (connection), NULL, device, subject, &error);
+ active = _new_active_connection (self, NM_CONNECTION (connection), NULL, NULL, device, subject, &error);
g_object_unref (subject);
if (!active) {
@@ -2288,6 +2289,28 @@ nm_manager_get_devices (NMManager *manager)
return NM_MANAGER_GET_PRIVATE (manager)->devices;
}
+const char **
+nm_manager_get_device_paths (NMManager *self)
+{
+ const GSList *devices, *iter;
+ GPtrArray *paths;
+ const char *path;
+
+ g_return_val_if_fail (NM_IS_MANAGER (self), NULL);
+ devices = NM_MANAGER_GET_PRIVATE (self)->devices;
+ paths = g_ptr_array_new ();
+
+ for (iter = devices; iter; iter = g_slist_next (iter)) {
+ path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data));
+ if (path)
+ g_ptr_array_add (paths, (gpointer) path);
+ }
+
+ g_ptr_array_add (paths, NULL);
+
+ return (const char **) g_ptr_array_free (paths, FALSE);
+}
+
static NMDevice *
nm_manager_get_connection_device (NMManager *self,
NMConnection *connection)
@@ -2612,6 +2635,7 @@ ensure_master_active_connection (NMManager *self,
master_ac = nm_manager_activate_connection (self,
candidate,
NULL,
+ NULL,
master_device,
subject,
error);
@@ -2658,6 +2682,7 @@ ensure_master_active_connection (NMManager *self,
master_ac = nm_manager_activate_connection (self,
master_connection,
NULL,
+ NULL,
candidate,
subject,
error);
@@ -2782,6 +2807,7 @@ autoconnect_slaves (NMManager *self,
nm_manager_activate_connection (self,
slave_connection,
NULL,
+ NULL,
nm_manager_get_best_device_for_connection (self, NM_CONNECTION (slave_connection), FALSE),
subject,
&local_err);
@@ -2941,7 +2967,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
return FALSE;
}
- parent_ac = nm_manager_activate_connection (self, parent_con, NULL, parent, subject, error);
+ parent_ac = nm_manager_activate_connection (self, parent_con, NULL, NULL, parent, subject, error);
if (!parent_ac) {
g_prefix_error (error, "%s failed to activate parent: ", nm_device_get_iface (device));
return FALSE;
@@ -3123,6 +3149,7 @@ _new_vpn_active_connection (NMManager *self,
static NMActiveConnection *
_new_active_connection (NMManager *self,
NMConnection *connection,
+ NMConnection *applied,
const char *specific_object,
NMDevice *device,
NMAuthSubject *subject,
@@ -3162,6 +3189,7 @@ _new_active_connection (NMManager *self,
}
return (NMActiveConnection *) nm_act_request_new (settings_connection,
+ applied,
specific_object,
subject,
device);
@@ -3212,6 +3240,7 @@ _internal_activation_auth_done (NMActiveConnection *active,
* nm_manager_activate_connection():
* @self: the #NMManager
* @connection: the #NMSettingsConnection to activate on @device
+ * @applied: (allow-none): the applied connection to activate on @device
* @specific_object: the specific object path, if any, for the activation
* @device: the #NMDevice to activate @connection on
* @subject: the subject which requested activation
@@ -3221,7 +3250,8 @@ _internal_activation_auth_done (NMActiveConnection *active,
* @subject should be the subject of the activation that triggered this
* one, or if this is an autoconnect request, a new internal subject.
* The returned #NMActiveConnection is owned by the Manager and should be
- * referenced by the caller if the caller continues to use it.
+ * referenced by the caller if the caller continues to use it. If @applied
+ * is supplied, it shall not be modified by the caller afterwards.
*
* Returns: (transfer none): the new #NMActiveConnection that tracks
* activation of @connection on @device
@@ -3229,6 +3259,7 @@ _internal_activation_auth_done (NMActiveConnection *active,
NMActiveConnection *
nm_manager_activate_connection (NMManager *self,
NMSettingsConnection *connection,
+ NMConnection *applied,
const char *specific_object,
NMDevice *device,
NMAuthSubject *subject,
@@ -3274,6 +3305,7 @@ nm_manager_activate_connection (NMManager *self,
active = _new_active_connection (self,
NM_CONNECTION (connection),
+ applied,
specific_object,
device,
subject,
@@ -3528,6 +3560,7 @@ impl_manager_activate_connection (NMManager *self,
active = _new_active_connection (self,
NM_CONNECTION (connection),
+ NULL,
specific_object_path,
device,
subject,
@@ -3735,6 +3768,7 @@ impl_manager_add_and_activate_connection (NMManager *self,
active = _new_active_connection (self,
connection,
+ NULL,
specific_object_path,
device,
subject,
diff --git a/src/nm-manager.h b/src/nm-manager.h
index fb97951ce3..90041ccd7d 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -91,6 +91,7 @@ void nm_manager_write_device_state (NMManager *manager);
/* Device handling */
const GSList * nm_manager_get_devices (NMManager *manager);
+const char ** nm_manager_get_device_paths (NMManager *self);
NMDevice * nm_manager_get_device_by_ifindex (NMManager *manager,
int ifindex);
@@ -104,6 +105,7 @@ char * nm_manager_get_connection_iface (NMManager *self,
NMActiveConnection *nm_manager_activate_connection (NMManager *manager,
NMSettingsConnection *connection,
+ NMConnection *applied_connection,
const char *specific_object,
NMDevice *device,
NMAuthSubject *subject,
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 5fa46259cd..0e437d9d4c 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -724,6 +724,7 @@ auto_activate_device (gpointer user_data)
subject = nm_auth_subject_new_internal ();
if (!nm_manager_activate_connection (priv->manager,
best_connection,
+ NULL,
specific_object,
data->device,
subject,
@@ -1117,6 +1118,7 @@ activate_secondary_connections (NMPolicy *self,
nm_connection_get_id (connection), nm_connection_get_uuid (connection));
ac = nm_manager_activate_connection (priv->manager,
settings_con,
+ NULL,
nm_exported_object_get_path (NM_EXPORTED_OBJECT (req)),
device,
nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (req)),
@@ -1520,6 +1522,7 @@ vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *self)
connection,
NULL,
NULL,
+ NULL,
nm_active_connection_get_subject (ac),
&error)) {
_LOGW (LOGD_DEVICE, "VPN '%s' reconnect failed: %s",