summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-12-01 12:56:09 +0100
committerThomas Haller <thaller@redhat.com>2017-12-05 20:18:10 +0100
commit35dc6421de78cffd1761cfb6edf9e94233f99966 (patch)
treeb2d8c5946633f9da0cc2ef37326fc9208d8c4fe4
parentcfced599cab19bb929494f6f38712e3b08ce3d55 (diff)
downloadNetworkManager-th/user-block-autoconnect-rh1401515.tar.gz
settings: support setting a connection as volatile via Update2()th/user-block-autoconnect-rh1401515
Extend the Update2 flags to allow marking a connection as volatile. Making a connection as volatile means that the connection stays alive as long as an active connection references it. It is correct that Update2() returns before the connection is actually deleted. It might take an arbitrary long time until the volatile mechanism cleans up the connection. Also add two more IN_MEMORY flags: "detached" and "only". The existing NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY would not detach nor delete the possible file on disk. That is, the mode only changes what NM thinks is the current content of the connection profile. It would not delete the file on disk nor would it detach the profile in-memory from the file. As such, later persisting the connection again to disk would overwrite the file, and deleting the profile, would delete the file. Now add two new IN_MEMORY modes. NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACH is like making the connection in-memory only, but forgetting that there might be any profile on disk. That means, a later Delete() would not delete the file. Similarly, a later Update2() that persists the connection again, would not overwrite the existing file on disk, instead it would choose a new file name. On the other hand, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY would delete a potential file from disk right away. It's clear that "volatile" only makes sense with either "in-memory-detached" or "in-memory-only". That is, the file on disk should be deleted right away (before the in-memory part is garbage collected) or the file on disk should be forgotten.
-rw-r--r--introspection/org.freedesktop.NetworkManager.Settings.Connection.xml3
-rw-r--r--libnm-core/nm-dbus-interface.h25
-rw-r--r--src/settings/nm-settings-connection.c121
-rw-r--r--src/settings/nm-settings-connection.h4
4 files changed, 110 insertions, 43 deletions
diff --git a/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml b/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml
index 9064ecaf39..ec596fd1e9 100644
--- a/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml
+++ b/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml
@@ -108,6 +108,9 @@
@flags: optional flags argument. Currently supported flags are:
"0x1" (to-disk),
"0x2" (in-memory),
+ "0x4" (in-memory-detached),
+ "0x8" (in-memory-only),
+ "0x10" (volatile),
"0x20" (block-autoconnect).
Unknown flags cause the call to fail.
@args: optional arguments dictionary, for extensibility. Currently no
diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h
index 064bcf65d7..4c586d5d8d 100644
--- a/libnm-core/nm-dbus-interface.h
+++ b/libnm-core/nm-dbus-interface.h
@@ -901,6 +901,28 @@ typedef enum { /*< flags >*/
* @NM_SETTINGS_UPDATE2_FLAG_NONE: an alias for numeric zero, no flags set.
* @NM_SETTINGS_UPDATE2_FLAG_TO_DISK: to persist the connection to disk.
* @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY: to make the connection in-memory only.
+ * If the connection was previously persistent, the corresponding file on disk
+ * is not deleted but merely the connection is decoupled from the file
+ * on disk. If you later delete an in-memory connection, the connection
+ * on disk will be deleted as well.
+ * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED: this is like @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY,
+ * but if the connection has a corresponding file on disk, the association between
+ * the connection and the file is forgotten but the file is not modified.
+ * The difference to %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY is if you later
+ * save the connection again to disk, a new file name will be chosen without
+ * overwriting the remaining file on disk. Also, if you delete the connection
+ * later, the file on disk will not be deleted.
+ * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY: this is like @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY,
+ * but if the connection has a corresponding file on disk, the file on
+ * disk will be deleted.
+ * @NM_SETTINGS_UPDATE2_FLAG_VOLATILE: This can be specified with either
+ * %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED or %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY.
+ * After making the connection in-memory only, the connection is marked
+ * as volatile. That means, if the connection is currently not active
+ * it will be deleted right away. Otherwise, it is marked to for deletion
+ * once the connection deactivates. A volatile connection cannot autoactivate
+ * again (because it's about to be deleted), but a manual activation will
+ * clear the volatile flag.
* @NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT: usually, when the connection
* has autoconnect enabled and is modified, it becomes elegible to autoconnect
* right away. Setting this flag, disables autoconnect until the connection
@@ -912,6 +934,9 @@ typedef enum { /*< flags >*/
NM_SETTINGS_UPDATE2_FLAG_NONE = 0,
NM_SETTINGS_UPDATE2_FLAG_TO_DISK = (1LL << 0),
NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY = (1LL << 1),
+ NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED = (1LL << 2),
+ NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY = (1LL << 3),
+ NM_SETTINGS_UPDATE2_FLAG_VOLATILE = (1LL << 4),
NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT = (1LL << 5),
} NMSettingsUpdate2Flags;
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index cef26d6cb8..3afe7de820 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -488,26 +488,41 @@ secrets_cleared_cb (NMSettingsConnection *self)
}
static void
-set_unsaved (NMSettingsConnection *self, gboolean now_unsaved)
+set_persist_mode (NMSettingsConnection *self, NMSettingsConnectionPersistMode persist_mode)
{
- NMSettingsConnectionFlags flags;
+ NMSettingsConnectionFlags flags = NM_SETTINGS_CONNECTION_FLAGS_NONE;
const NMSettingsConnectionFlags ALL = NM_SETTINGS_CONNECTION_FLAGS_UNSAVED
| NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_FLAGS_VOLATILE;
- if (NM_FLAGS_HAS (nm_settings_connection_get_flags (self), NM_SETTINGS_CONNECTION_FLAGS_UNSAVED) != !!now_unsaved) {
- if (now_unsaved)
- flags = NM_SETTINGS_CONNECTION_FLAGS_UNSAVED;
- else
- flags = NM_SETTINGS_CONNECTION_FLAGS_NONE;
- nm_settings_connection_set_flags_full (self, ALL, flags);
+ if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP)
+ return;
+
+ switch (persist_mode) {
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK:
+ flags = NM_SETTINGS_CONNECTION_FLAGS_NONE;
+ break;
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY:
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED:
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY:
+ flags = NM_SETTINGS_CONNECTION_FLAGS_UNSAVED;
+ break;
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED:
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY:
+ flags = NM_SETTINGS_CONNECTION_FLAGS_UNSAVED |
+ NM_SETTINGS_CONNECTION_FLAGS_VOLATILE;
+ break;
+ case NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP:
+ g_return_if_reached ();
}
+
+ nm_settings_connection_set_flags_full (self, ALL, flags);
}
static void
connection_changed_cb (NMSettingsConnection *self, gpointer unused)
{
- set_unsaved (self, TRUE);
+ set_persist_mode (self, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY);
_emit_updated (self, FALSE);
}
@@ -515,23 +530,34 @@ static gboolean
_delete (NMSettingsConnection *self, GError **error)
{
NMSettingsConnectionClass *klass;
+ GError *local = NULL;
+ const char *filename;
nm_assert (NM_IS_SETTINGS_CONNECTION (self));
klass = NM_SETTINGS_CONNECTION_GET_CLASS (self);
if (!klass->delete) {
- g_set_error (error,
+ g_set_error (&local,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_FAILED,
"delete not supported");
- return FALSE;
+ goto fail;
}
if (!klass->delete (self,
- error))
- return FALSE;
+ &local))
+ goto fail;
- nm_settings_connection_set_filename (self, NULL);
+ filename = nm_settings_connection_get_filename (self);
+ if (filename) {
+ _LOGD ("delete: success deleting connection (\"%s\")", filename);
+ nm_settings_connection_set_filename (self, NULL);
+ } else
+ _LOGT ("delete: success deleting connection (no-file)");
return TRUE;
+fail:
+ _LOGD ("delete: failure deleting connection: %s", local->message);
+ g_propagate_error (error, local);
+ return FALSE;
}
static gboolean
@@ -576,18 +602,17 @@ nm_settings_connection_update (NMSettingsConnection *self,
gboolean replaced = FALSE;
gs_free char *logmsg_change = NULL;
GError *local = NULL;
+ gboolean save_to_disk;
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE);
priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
- if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP) {
- persist_mode = nm_settings_connection_get_unsaved (self)
- ? NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY
- : NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
- }
+ save_to_disk = (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK)
+ || ( persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP
+ && !nm_settings_connection_get_unsaved (self));
- if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK) {
+ if (save_to_disk) {
klass = NM_SETTINGS_CONNECTION_GET_CLASS (self);
if (!klass->commit_changes) {
g_set_error (&local,
@@ -604,7 +629,7 @@ nm_settings_connection_update (NMSettingsConnection *self,
&local))
goto out;
- if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK) {
+ if (save_to_disk) {
if (!klass->commit_changes (self,
new_connection ?: NM_CONNECTION (self),
commit_reason,
@@ -666,19 +691,14 @@ nm_settings_connection_update (NMSettingsConnection *self,
nm_settings_connection_recheck_visibility (self);
- /* Manually emit changed signal since we disconnected the handler, but
- * only update Unsaved if the caller wanted us to.
- */
- switch (persist_mode) {
- case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY:
- set_unsaved (self, TRUE);
- break;
- case NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK:
- set_unsaved (self, FALSE);
- break;
- case NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP:
- break;
- }
+ set_persist_mode (self, persist_mode);
+
+ if (NM_IN_SET (persist_mode, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
+ NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY))
+ _delete (self, NULL);
+ else if (NM_IN_SET (persist_mode, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED,
+ NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED))
+ nm_settings_connection_set_filename (self, NULL);
g_signal_handlers_unblock_by_func (self, G_CALLBACK (connection_changed_cb), NULL);
@@ -1700,15 +1720,23 @@ update_auth_cb (NMSettingsConnection *self,
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
else if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY))
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY;
- else
+ else if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED)) {
+ persist_mode = NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_VOLATILE)
+ ? NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED
+ : NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED;
+ } else if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY)) {
+ persist_mode = NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_VOLATILE)
+ ? NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY
+ : NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY;
+ } else
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP;
- if ( persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY
+ if ( persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK
|| ( persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP
- && nm_settings_connection_get_unsaved (self)))
- log_diff_name = info->new_settings ? "update-unsaved" : "make-unsaved";
- else
+ && !nm_settings_connection_get_unsaved (self)))
log_diff_name = info->new_settings ? "update-settings" : "write-out-to-disk";
+ else
+ log_diff_name = info->new_settings ? "update-unsaved" : "make-unsaved";
if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT)) {
nm_settings_connection_autoconnect_blocked_reason_set (self,
@@ -1887,9 +1915,13 @@ impl_settings_connection_update2 (NMSettingsConnection *self,
GVariantIter iter;
const char *args_name;
const NMSettingsUpdate2Flags flags = (NMSettingsUpdate2Flags) flags_u;
+ const NMSettingsUpdate2Flags ALL_PERSIST_MODES = NM_SETTINGS_UPDATE2_FLAG_TO_DISK
+ | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY
+ | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED
+ | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY;
- if (NM_FLAGS_ANY (flags_u, ~((guint32) (NM_SETTINGS_UPDATE2_FLAG_TO_DISK |
- NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY |
+ if (NM_FLAGS_ANY (flags_u, ~((guint32) (ALL_PERSIST_MODES |
+ NM_SETTINGS_UPDATE2_FLAG_VOLATILE |
NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT)))) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
@@ -1898,8 +1930,11 @@ impl_settings_connection_update2 (NMSettingsConnection *self,
return;
}
- if (NM_FLAGS_ALL (flags, NM_SETTINGS_UPDATE2_FLAG_TO_DISK |
- NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY)) {
+ if ( ( NM_FLAGS_ANY (flags, ALL_PERSIST_MODES)
+ && !nm_utils_is_power_of_two (flags & ALL_PERSIST_MODES))
+ || ( NM_FLAGS_HAS (flags, NM_SETTINGS_UPDATE2_FLAG_VOLATILE)
+ && !NM_FLAGS_ANY (flags, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED |
+ NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY))) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
"Conflicting flags");
diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h
index 7615fb4655..051fcf7ff9 100644
--- a/src/settings/nm-settings-connection.h
+++ b/src/settings/nm-settings-connection.h
@@ -139,6 +139,10 @@ typedef enum {
NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP,
NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY,
+ NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED,
+ NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
+ NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED,
+ NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY,
} NMSettingsConnectionPersistMode;
gboolean nm_settings_connection_update (NMSettingsConnection *self,