settings-connection: add a "plugin" argument to Update2()

This will allow migrating a connection. If specified, the connection will
be confined to a particular settings plugin when written back. If the
plugin differs from the existing one, it will be removed from the old one.
This commit is contained in:
Lubomir Rintel 2022-03-14 10:20:12 +01:00
parent 5451e60a89
commit c724c92f12
8 changed files with 79 additions and 12 deletions

View file

@ -114,9 +114,12 @@
"0x20" (block-autoconnect),
"0x40" (no-reapply).
Unknown flags cause the call to fail.
@args: optional arguments dictionary, for extentibility. Currently, no
arguments are accepted. Specifying unknown keys causes the call
to fail.
@args: optional arguments dictionary, for extensibility. Currently, the
following arguments are accepted:
"plugin" (s) string that specifies the settings plugin the newly
added connection will use, such as "keyfile" or "ifcfg-rh".
Since: 1.38
Specifying unknown or duplicate keys causes the call to fail.
@result: output argument, currently no results are returned.
Update the connection with new settings and properties (replacing all

View file

@ -3859,6 +3859,7 @@ update_external_connection(NMDevice *self)
if (connection_new) {
nm_settings_connection_update(settings_connection,
NULL,
connection_new,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,

View file

@ -231,6 +231,7 @@ restore_and_activate_connection(NMCheckpoint *self, DeviceCheckpoint *dev_checkp
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP;
nm_settings_connection_update(
connection,
NULL,
dev_checkpoint->settings_connection,
persist_mode,
sett_flags,

View file

@ -3060,6 +3060,7 @@ recheck_assume_connection(NMManager *self, NMDevice *device)
nm_settings_connection_update(
sett_conn,
NULL,
con2,
NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,

View file

@ -623,6 +623,7 @@ _secrets_update(NMConnection *connection,
gboolean
nm_settings_connection_update(NMSettingsConnection *self,
const char *plugin_name,
NMConnection *new_connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
@ -635,6 +636,7 @@ nm_settings_connection_update(NMSettingsConnection *self,
return nm_settings_update_connection(NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->settings,
self,
plugin_name,
new_connection,
persist_mode,
sett_flags,
@ -852,6 +854,7 @@ nm_settings_connection_new_secrets(NMSettingsConnection *self,
if (!nm_settings_connection_update(
self,
NULL,
new_connection ?: connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
@ -997,6 +1000,7 @@ get_secrets_done_cb(NMAgentManager *manager,
}
if (!nm_settings_connection_update(
self,
NULL,
new_connection,
agent_had_system ? NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP
: NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST,
@ -1426,6 +1430,7 @@ typedef struct {
NMConnection *new_settings;
NMSettingsUpdate2Flags flags;
char *audit_args;
char *plugin_name;
bool is_update2 : 1;
} UpdateInfo;
@ -1453,6 +1458,7 @@ update_complete(NMSettingsConnection *self, UpdateInfo *info, GError *error)
g_clear_object(&info->agent_mgr);
g_clear_object(&info->new_settings);
g_free(info->audit_args);
g_free(info->plugin_name);
g_slice_free(UpdateInfo, info);
}
@ -1589,6 +1595,7 @@ update_auth_cb(NMSettingsConnection *self,
nm_settings_connection_update(
self,
info->plugin_name,
info->new_settings,
persist_mode,
(NM_FLAGS_HAS(info->flags, NM_SETTINGS_UPDATE2_FLAG_VOLATILE)
@ -1659,6 +1666,7 @@ settings_connection_update(NMSettingsConnection *self,
gboolean is_update2,
GDBusMethodInvocation *context,
GVariant *new_settings,
const char *plugin_name,
NMSettingsUpdate2Flags flags)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
@ -1713,6 +1721,7 @@ settings_connection_update(NMSettingsConnection *self,
info->subject = subject;
info->flags = flags;
info->new_settings = tmp;
info->plugin_name = g_strdup(plugin_name);
permission = get_update_modify_permission(nm_settings_connection_get_connection(self),
tmp ?: nm_settings_connection_get_connection(self));
@ -1741,7 +1750,12 @@ impl_settings_connection_update(NMDBusObject *obj,
gs_unref_variant GVariant *settings = NULL;
g_variant_get(parameters, "(@a{sa{sv}})", &settings);
settings_connection_update(self, FALSE, invocation, settings, NM_SETTINGS_UPDATE2_FLAG_TO_DISK);
settings_connection_update(self,
FALSE,
invocation,
settings,
NULL,
NM_SETTINGS_UPDATE2_FLAG_TO_DISK);
}
static void
@ -1761,6 +1775,7 @@ impl_settings_connection_update_unsaved(NMDBusObject *obj,
FALSE,
invocation,
settings,
NULL,
NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY);
}
@ -1775,7 +1790,12 @@ impl_settings_connection_save(NMDBusObject *obj,
{
NMSettingsConnection *self = NM_SETTINGS_CONNECTION(obj);
settings_connection_update(self, FALSE, invocation, NULL, NM_SETTINGS_UPDATE2_FLAG_TO_DISK);
settings_connection_update(self,
FALSE,
invocation,
NULL,
NULL,
NM_SETTINGS_UPDATE2_FLAG_TO_DISK);
}
static void
@ -1787,13 +1807,15 @@ impl_settings_connection_update2(NMDBusObject *obj,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
NMSettingsConnection *self = NM_SETTINGS_CONNECTION(obj);
gs_unref_variant GVariant *settings = NULL;
gs_unref_variant GVariant *args = NULL;
NMSettingsConnection *self = NM_SETTINGS_CONNECTION(obj);
gs_unref_variant GVariant *settings = NULL;
gs_unref_variant GVariant *args = NULL;
gs_free char *plugin_name = NULL;
guint32 flags_u;
GError *error = NULL;
GVariantIter iter;
const char *args_name;
GVariant *args_value;
NMSettingsUpdate2Flags flags;
g_variant_get(parameters, "(@a{sa{sv}}u@a{sv})", &settings, &flags_u, &args);
@ -1829,7 +1851,13 @@ impl_settings_connection_update2(NMDBusObject *obj,
nm_assert(g_variant_is_of_type(args, G_VARIANT_TYPE("a{sv}")));
g_variant_iter_init(&iter, args);
while (g_variant_iter_next(&iter, "{&sv}", &args_name, NULL)) {
while (g_variant_iter_next(&iter, "{&sv}", &args_name, &args_value)) {
if (plugin_name == NULL && nm_streq(args_name, "plugin")
&& g_variant_is_of_type(args_value, G_VARIANT_TYPE_STRING)) {
plugin_name = g_variant_dup_string(args_value, NULL);
continue;
}
error = g_error_new(NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
"Unsupported argument '%s'",
@ -1838,7 +1866,7 @@ impl_settings_connection_update2(NMDBusObject *obj,
return;
}
settings_connection_update(self, TRUE, invocation, settings, flags);
settings_connection_update(self, TRUE, invocation, settings, plugin_name, flags);
}
static void
@ -2027,6 +2055,7 @@ dbus_clear_secrets_auth_cb(NMSettingsConnection *self,
if (!nm_settings_connection_update(
self,
NULL,
connection_cloned,
NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,

View file

@ -241,6 +241,7 @@ nm_settings_connection_has_unmodified_applied_connection(NMSettingsConnection *s
NMSettingCompareFlags compare_flage);
gboolean nm_settings_connection_update(NMSettingsConnection *self,
const char *plugin_name,
NMConnection *new_connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,

View file

@ -236,12 +236,16 @@ _sett_conn_entry_get_conn(SettConnEntry *sett_conn_entry)
* update-connection. If this parameter is omitted, then it's about what happens
* when adding a new profile (add-connection).
*
* @storage_check_ignore is optional, and if given then it skips this particular
* storage.
*
* Returns: the conflicting storage or %NULL if there is none.
*/
static NMSettingsStorage *
_sett_conn_entry_storage_find_conflicting_storage(SettConnEntry *sett_conn_entry,
NMSettingsPlugin *target_plugin,
NMSettingsStorage *storage_check_including,
NMSettingsStorage *storage_check_ignore,
const GSList *plugins)
{
StorageData *sd;
@ -269,6 +273,12 @@ _sett_conn_entry_storage_find_conflicting_storage(SettConnEntry *sett_conn_e
continue;
}
if (sd->storage == storage_check_ignore) {
/* We ignore this one, because we're in the process of
* replacing it. */
continue;
}
if (sd->storage == storage_check_including) {
/* ok, the storage is the one we are about to check. All other
* storages are lower priority, so there is no storage that hides
@ -1472,6 +1482,7 @@ _add_connection_to_first_plugin(NMSettings *self,
gboolean shadowed_owned,
NMSettingsStorage **out_new_storage,
NMConnection **out_new_connection,
NMSettingsStorage *drop_storage,
GError **error)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self);
@ -1506,6 +1517,7 @@ _add_connection_to_first_plugin(NMSettings *self,
conflicting_storage = _sett_conn_entry_storage_find_conflicting_storage(sett_conn_entry,
plugin,
NULL,
drop_storage,
priv->plugins);
if (conflicting_storage) {
/* we have a connection provided by a plugin with higher priority than the one
@ -1820,6 +1832,7 @@ nm_settings_add_connection(NMSettings *self,
sett_conn_entry,
nm_settings_storage_get_plugin(shadowed_storage),
shadowed_storage,
NULL,
priv->plugins);
if (conflicting_storage) {
/* We cannot add the profile as @shadowed_storage, because there is another, existing storage
@ -1853,6 +1866,7 @@ again_add_connection:
FALSE,
&new_storage,
&new_connection,
NULL,
&local);
} else {
success = _update_connection_to_plugin(self,
@ -1969,6 +1983,7 @@ again_delete_tombstone:
gboolean
nm_settings_update_connection(NMSettings *self,
NMSettingsConnection *sett_conn,
const char *plugin_name,
NMConnection *connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
@ -2175,8 +2190,9 @@ nm_settings_update_connection(NMSettings *self,
} else if (nm_settings_storage_is_keyfile_lib(cur_storage)) {
/* the profile is a keyfile in /usr/lib. It cannot be overwritten, we must migrate it
* from /usr/lib to /etc. */
} else
} else {
update_storage = cur_storage;
}
if (new_in_memory) {
if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY) {
@ -2195,9 +2211,22 @@ nm_settings_update_connection(NMSettings *self,
}
}
if (update_storage && plugin_name) {
NMSettingsPlugin *plugin = nm_settings_storage_get_plugin(update_storage);
if (strcmp(plugin_name, nm_settings_plugin_get_plugin_name(plugin))) {
/* We're updating a connection, we're confined to a particular
* plugin, but the connection is currently using a different one.
* We need to migrate. Drop the existing storage and look out for
* a new one. */
drop_storage = update_storage;
update_storage = NULL;
}
}
if (!update_storage) {
success = _add_connection_to_first_plugin(self,
NULL,
plugin_name,
sett_conn_entry,
connection,
new_in_memory,
@ -2206,6 +2235,7 @@ nm_settings_update_connection(NMSettings *self,
new_shadowed_owned,
&new_storage,
&new_connection,
drop_storage,
&local);
} else {
success = _update_connection_to_plugin(self,

View file

@ -101,6 +101,7 @@ gboolean nm_settings_add_connection(NMSettings *settings,
gboolean nm_settings_update_connection(NMSettings *self,
NMSettingsConnection *sett_conn,
const char *plugin_name,
NMConnection *new_connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,