mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-03 18:20:29 +01:00
merge: branch 'lr/conn-migrate'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1146 https://bugzilla.redhat.com/show_bug.cgi?id=2059608
This commit is contained in:
commit
8dbe6fa0d5
13 changed files with 347 additions and 19 deletions
|
|
@ -105,7 +105,7 @@
|
|||
Update2:
|
||||
@settings: New connection settings, properties, and (optionally) secrets. Provide an empty array to use the current settings.
|
||||
@flags: Optional flags. 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 extentibility. Specifying unknown keys causes the call to fail.
|
||||
@result: Currently no results are returned.
|
||||
@since: 1.12
|
||||
|
||||
|
|
@ -156,6 +156,17 @@
|
|||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
The %args argument accepts the following keys:
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><literal>plugin</literal>:</term>
|
||||
<listitem><para>The settings plugin the connection will be migrated to
|
||||
such as "keyfile" or "ifcfg-rh".</para>
|
||||
<para role="since">Since 1.38</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
Secrets may be part of the update request, and will be either stored in persistent
|
||||
storage or sent to a Secret Agent for storage, depending on the flags
|
||||
associated with each secret.
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@
|
|||
AddConnection2:
|
||||
@settings: New connection settings, properties, and (optionally) secrets.
|
||||
@flags: Flags. 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 extentibility. Specifying unknown keys causes the call to fail.
|
||||
@path: Object path of the new connection that was just added.
|
||||
@result: Output argument, currently no additional results are returned.
|
||||
@since: 1.20
|
||||
|
|
@ -100,6 +100,17 @@
|
|||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
The %args argument accepts the following keys:
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><literal>plugin</literal>:</term>
|
||||
<listitem><para>The settings plugin the newly added connection will
|
||||
use, such as "keyfile" or "ifcfg-rh".</para>
|
||||
<para role="since">Since 1.38</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
Either the flags 0x1 (to-disk) or 0x2 (in-memory) must be specified.
|
||||
The effect is whether to behave like
|
||||
<link linkend="gdbus-method-org-freedesktop-NetworkManager-Settings.AddConnection">AddConnection</link> or
|
||||
|
|
|
|||
|
|
@ -659,6 +659,7 @@
|
|||
<arg choice='plain'><command>load</command></arg>
|
||||
<arg choice='plain'><command>import</command></arg>
|
||||
<arg choice='plain'><command>export</command></arg>
|
||||
<arg choice='plain'><command>migrate</command></arg>
|
||||
</group>
|
||||
<arg rep='repeat'><replaceable>ARGUMENTS</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
|
|
@ -1312,6 +1313,40 @@
|
|||
data will be printed to standard output.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>migrate</command>
|
||||
<arg>
|
||||
<option>--plugin</option>
|
||||
<arg choice='plain' rep='repeat'><replaceable>plugin</replaceable></arg>
|
||||
</arg>
|
||||
<group>
|
||||
<arg choice='plain'><option>id</option></arg>
|
||||
<arg choice='plain'><option>uuid</option></arg>
|
||||
<arg choice='plain'><option>path</option></arg>
|
||||
</group>
|
||||
<arg rep='repeat'><replaceable>ID</replaceable></arg>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>Migrate connection profiles to a different settings plugin, such
|
||||
as <literal>keyfile</literal> (default) or <literal>ifcfg-rh</literal>.</para>
|
||||
|
||||
<para>The connection to be migrated is identified by its name, UUID or D-Bus path.
|
||||
If <replaceable>ID</replaceable> is ambiguous, a keyword <option>id</option>,
|
||||
<option>uuid</option> or <option>path</option> can be used. See <command>connection
|
||||
show</command> above for the description of the
|
||||
<replaceable>ID</replaceable>-specifying keywords.</para>
|
||||
|
||||
<para>If no connections are specified, the command acts on all available
|
||||
connections. Therefore, with no arguments, the command migrates all connection
|
||||
profiles to the <literal>keyfile</literal> plugin.</para>
|
||||
|
||||
<para>If <option>--wait</option> option is not specified, the default timeout will be 10
|
||||
seconds.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
|
|
|||
|
|
@ -1352,6 +1352,7 @@ _conn_create_panu_connection(NMBluezManager *self, BzDBusObj *bzobj)
|
|||
bzobj->d_device.address);
|
||||
|
||||
nm_settings_add_connection(priv->settings,
|
||||
NULL,
|
||||
connection,
|
||||
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
|
||||
NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -948,6 +948,7 @@ mirror_connection(NMIwdManager *self,
|
|||
|
||||
if (!nm_settings_add_connection(
|
||||
priv->settings,
|
||||
NULL,
|
||||
connection,
|
||||
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
|
||||
NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -247,6 +248,7 @@ restore_and_activate_connection(NMCheckpoint *self, DeviceCheckpoint *dev_checkp
|
|||
|
||||
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK;
|
||||
if (!nm_settings_add_connection(NM_SETTINGS_GET,
|
||||
NULL,
|
||||
dev_checkpoint->settings_connection,
|
||||
persist_mode,
|
||||
NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
|
|
|
|||
|
|
@ -2939,6 +2939,7 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat
|
|||
nm_device_assume_state_reset(device);
|
||||
|
||||
if (!nm_settings_add_connection(priv->settings,
|
||||
NULL,
|
||||
connection,
|
||||
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
|
||||
NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
|
|
@ -3059,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,
|
||||
|
|
@ -5915,6 +5917,7 @@ _add_and_activate_auth_done(NMManager *self,
|
|||
* shutdown. */
|
||||
nm_settings_add_connection_dbus(
|
||||
priv->settings,
|
||||
NULL,
|
||||
connection,
|
||||
persist_mode,
|
||||
NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
|
|
|
|||
|
|
@ -606,6 +606,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,
|
||||
|
|
@ -618,6 +619,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,
|
||||
|
|
@ -835,6 +837,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,
|
||||
|
|
@ -980,6 +983,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,
|
||||
|
|
@ -1409,6 +1413,7 @@ typedef struct {
|
|||
NMConnection *new_settings;
|
||||
NMSettingsUpdate2Flags flags;
|
||||
char *audit_args;
|
||||
char *plugin_name;
|
||||
bool is_update2 : 1;
|
||||
} UpdateInfo;
|
||||
|
||||
|
|
@ -1436,6 +1441,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);
|
||||
}
|
||||
|
||||
|
|
@ -1572,6 +1578,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)
|
||||
|
|
@ -1642,6 +1649,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);
|
||||
|
|
@ -1696,6 +1704,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));
|
||||
|
|
@ -1724,7 +1733,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
|
||||
|
|
@ -1744,6 +1758,7 @@ impl_settings_connection_update_unsaved(NMDBusObject *obj,
|
|||
FALSE,
|
||||
invocation,
|
||||
settings,
|
||||
NULL,
|
||||
NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY);
|
||||
}
|
||||
|
||||
|
|
@ -1758,7 +1773,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
|
||||
|
|
@ -1770,13 +1790,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);
|
||||
|
|
@ -1812,7 +1834,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'",
|
||||
|
|
@ -1821,7 +1849,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
|
||||
|
|
@ -2010,6 +2038,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,
|
||||
|
|
|
|||
|
|
@ -240,6 +240,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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1463,6 +1473,7 @@ _plugin_connections_reload(NMSettings *self)
|
|||
|
||||
static gboolean
|
||||
_add_connection_to_first_plugin(NMSettings *self,
|
||||
const char *plugin_name,
|
||||
SettConnEntry *sett_conn_entry,
|
||||
NMConnection *new_connection,
|
||||
gboolean in_memory,
|
||||
|
|
@ -1471,12 +1482,14 @@ _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);
|
||||
gs_free_error GError *first_error = NULL;
|
||||
GSList *iter;
|
||||
const char *uuid;
|
||||
gboolean no_plugin = TRUE;
|
||||
|
||||
uuid = nm_connection_get_uuid(new_connection);
|
||||
|
||||
|
|
@ -1493,12 +1506,18 @@ _add_connection_to_first_plugin(NMSettings *self,
|
|||
gboolean success;
|
||||
const char *filename;
|
||||
|
||||
if (plugin_name && strcmp(plugin_name, nm_settings_plugin_get_plugin_name(plugin))) {
|
||||
/* Not the plugin we're confined to. Ignore. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!in_memory) {
|
||||
NMSettingsStorage *conflicting_storage;
|
||||
|
||||
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
|
||||
|
|
@ -1545,6 +1564,8 @@ _add_connection_to_first_plugin(NMSettings *self,
|
|||
&add_error);
|
||||
}
|
||||
|
||||
no_plugin = FALSE;
|
||||
|
||||
if (!success) {
|
||||
_LOGT("add-connection: failed to add %s/'%s': %s",
|
||||
nm_connection_get_uuid(new_connection),
|
||||
|
|
@ -1588,8 +1609,18 @@ _add_connection_to_first_plugin(NMSettings *self,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
nm_assert(first_error);
|
||||
g_propagate_error(error, g_steal_pointer(&first_error));
|
||||
if (no_plugin) {
|
||||
nm_assert(plugin_name);
|
||||
nm_assert(!first_error);
|
||||
g_set_error(error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
|
||||
"a plugin by the name of '%s' is not available",
|
||||
plugin_name);
|
||||
} else {
|
||||
nm_assert(first_error);
|
||||
g_propagate_error(error, g_steal_pointer(&first_error));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1704,6 +1735,7 @@ _set_nmmeta_tombstone(NMSettings *self,
|
|||
*/
|
||||
gboolean
|
||||
nm_settings_add_connection(NMSettings *self,
|
||||
const char *plugin,
|
||||
NMConnection *connection,
|
||||
NMSettingsConnectionPersistMode persist_mode,
|
||||
NMSettingsConnectionAddReason add_reason,
|
||||
|
|
@ -1800,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
|
||||
|
|
@ -1824,6 +1857,7 @@ again_add_connection:
|
|||
|
||||
if (!update_storage) {
|
||||
success = _add_connection_to_first_plugin(self,
|
||||
plugin,
|
||||
sett_conn_entry,
|
||||
connection,
|
||||
new_in_memory,
|
||||
|
|
@ -1832,6 +1866,7 @@ again_add_connection:
|
|||
FALSE,
|
||||
&new_storage,
|
||||
&new_connection,
|
||||
NULL,
|
||||
&local);
|
||||
} else {
|
||||
success = _update_connection_to_plugin(self,
|
||||
|
|
@ -1948,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,
|
||||
|
|
@ -2154,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) {
|
||||
|
|
@ -2174,8 +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,
|
||||
plugin_name,
|
||||
sett_conn_entry,
|
||||
connection,
|
||||
new_in_memory,
|
||||
|
|
@ -2184,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,
|
||||
|
|
@ -2462,6 +2514,7 @@ pk_add_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data
|
|||
nm_assert(NM_IS_CONNECTION(connection));
|
||||
|
||||
nm_settings_add_connection(self,
|
||||
nm_auth_chain_get_data(chain, "plugin"),
|
||||
connection,
|
||||
GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "persist-mode")),
|
||||
GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "add-reason")),
|
||||
|
|
@ -2489,6 +2542,7 @@ pk_add_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data
|
|||
|
||||
void
|
||||
nm_settings_add_connection_dbus(NMSettings *self,
|
||||
const char *plugin,
|
||||
NMConnection *connection,
|
||||
NMSettingsConnectionPersistMode persist_mode,
|
||||
NMSettingsConnectionAddReason add_reason,
|
||||
|
|
@ -2549,6 +2603,7 @@ nm_settings_add_connection_dbus(NMSettings *self,
|
|||
nm_auth_chain_set_data(chain, "persist-mode", GUINT_TO_POINTER(persist_mode), NULL);
|
||||
nm_auth_chain_set_data(chain, "add-reason", GUINT_TO_POINTER(add_reason), NULL);
|
||||
nm_auth_chain_set_data(chain, "sett-flags", GUINT_TO_POINTER(sett_flags), NULL);
|
||||
nm_auth_chain_set_data(chain, "plugin", g_strdup(plugin), g_free);
|
||||
nm_auth_chain_add_call_unsafe(chain, perm, TRUE);
|
||||
return;
|
||||
|
||||
|
|
@ -2601,6 +2656,7 @@ settings_add_connection_helper(NMSettings *self,
|
|||
GDBusMethodInvocation *context,
|
||||
gboolean is_add_connection_2,
|
||||
GVariant *settings,
|
||||
const char *plugin,
|
||||
NMSettingsAddConnection2Flags flags)
|
||||
{
|
||||
gs_unref_object NMConnection *connection = NULL;
|
||||
|
|
@ -2636,6 +2692,7 @@ settings_add_connection_helper(NMSettings *self,
|
|||
|
||||
nm_settings_add_connection_dbus(
|
||||
self,
|
||||
plugin,
|
||||
connection,
|
||||
persist_mode,
|
||||
NM_FLAGS_HAS(flags, NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT)
|
||||
|
|
@ -2665,6 +2722,7 @@ impl_settings_add_connection(NMDBusObject *obj,
|
|||
invocation,
|
||||
FALSE,
|
||||
settings,
|
||||
NULL,
|
||||
NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK);
|
||||
}
|
||||
|
||||
|
|
@ -2685,6 +2743,7 @@ impl_settings_add_connection_unsaved(NMDBusObject *obj,
|
|||
invocation,
|
||||
FALSE,
|
||||
settings,
|
||||
NULL,
|
||||
NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY);
|
||||
}
|
||||
|
||||
|
|
@ -2700,8 +2759,10 @@ impl_settings_add_connection2(NMDBusObject *obj,
|
|||
NMSettings *self = NM_SETTINGS(obj);
|
||||
gs_unref_variant GVariant *settings = NULL;
|
||||
gs_unref_variant GVariant *args = NULL;
|
||||
gs_free char *plugin = NULL;
|
||||
NMSettingsAddConnection2Flags flags;
|
||||
const char *args_name;
|
||||
GVariant *args_value;
|
||||
GVariantIter iter;
|
||||
guint32 flags_u;
|
||||
|
||||
|
|
@ -2745,7 +2806,13 @@ impl_settings_add_connection2(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 == NULL && nm_streq(args_name, "plugin")
|
||||
&& g_variant_is_of_type(args_value, G_VARIANT_TYPE_STRING)) {
|
||||
plugin = g_variant_dup_string(args_value, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_take_error(invocation,
|
||||
g_error_new(NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
|
||||
|
|
@ -2754,7 +2821,7 @@ impl_settings_add_connection2(NMDBusObject *obj,
|
|||
return;
|
||||
}
|
||||
|
||||
settings_add_connection_helper(self, invocation, TRUE, settings, flags);
|
||||
settings_add_connection_helper(self, invocation, TRUE, settings, plugin, flags);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -3606,6 +3673,7 @@ device_realized(NMDevice *device, GParamSpec *pspec, NMSettings *self)
|
|||
nm_device_get_iface(device));
|
||||
|
||||
nm_settings_add_connection(self,
|
||||
NULL,
|
||||
connection,
|
||||
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
|
||||
NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ typedef void (*NMSettingsAddCallback)(NMSettings *settings,
|
|||
gpointer user_data);
|
||||
|
||||
void nm_settings_add_connection_dbus(NMSettings *self,
|
||||
const char *plugin,
|
||||
NMConnection *connection,
|
||||
NMSettingsConnectionPersistMode persist_mode,
|
||||
NMSettingsConnectionAddReason add_reason,
|
||||
|
|
@ -90,6 +91,7 @@ NMSettingsConnection **nm_settings_get_connections_clone(NMSettings
|
|||
gpointer sort_data);
|
||||
|
||||
gboolean nm_settings_add_connection(NMSettings *settings,
|
||||
const char *plugin,
|
||||
NMConnection *connection,
|
||||
NMSettingsConnectionPersistMode persist_mode,
|
||||
NMSettingsConnectionAddReason add_reason,
|
||||
|
|
@ -99,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,
|
||||
|
|
|
|||
|
|
@ -1231,10 +1231,10 @@ usage_connection_delete(void)
|
|||
{
|
||||
g_printerr(_("Usage: nmcli connection delete { ARGUMENTS | help }\n"
|
||||
"\n"
|
||||
"ARGUMENTS := [id | uuid | path] <ID>\n"
|
||||
"ARGUMENTS := [id | uuid | path] <ID>, ...\n"
|
||||
"\n"
|
||||
"Delete a connection profile.\n"
|
||||
"The profile is identified by its name, UUID or D-Bus path.\n\n"));
|
||||
"Delete connection profiles.\n"
|
||||
"The profiles are identified by their name, UUID or D-Bus path.\n\n"));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1294,6 +1294,17 @@ usage_connection_export(void)
|
|||
"The data are directed to standard output or to a file if a name is given.\n\n"));
|
||||
}
|
||||
|
||||
static void
|
||||
usage_connection_migrate(void)
|
||||
{
|
||||
g_printerr(_("Usage: nmcli connection migrate { ARGUMENTS | help }\n"
|
||||
"\n"
|
||||
"ARGUMENTS := [--plugin <plugin>] [id | uuid | path] <ID>, ...\n"
|
||||
"\n"
|
||||
"Migrate connection profiles to a different settings plugin,\n"
|
||||
"such as \"keyfile\" (default) or \"ifcfg-rh\".\n\n"));
|
||||
}
|
||||
|
||||
static void
|
||||
quit(void)
|
||||
{
|
||||
|
|
@ -9138,8 +9149,11 @@ do_connection_delete(const NMCCommand *cmd, NmCli *nmc, int argc, const char *co
|
|||
nmc->return_value = error->code;
|
||||
g_clear_error(&error);
|
||||
|
||||
if (nmc->return_value != NMC_RESULT_ERROR_NOT_FOUND)
|
||||
if (nmc->return_value != NMC_RESULT_ERROR_NOT_FOUND) {
|
||||
g_string_free(invalid_cons, TRUE);
|
||||
invalid_cons = NULL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!invalid_cons)
|
||||
invalid_cons = g_string_new(NULL);
|
||||
|
|
@ -9192,7 +9206,6 @@ finish:
|
|||
g_string_printf(nmc->return_text,
|
||||
_("Error: cannot delete unknown connection(s): %s."),
|
||||
invalid_cons->str);
|
||||
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9645,6 +9658,154 @@ finish:
|
|||
unlink(path);
|
||||
}
|
||||
|
||||
static void
|
||||
migrate_cb(GObject *obj, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
ConnectionCbInfo *info = (ConnectionCbInfo *) user_data;
|
||||
NMConnection *connection = NM_CONNECTION(obj);
|
||||
gs_unref_variant GVariant *res = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
res = nm_remote_connection_update2_finish(NM_REMOTE_CONNECTION(obj), result, &error);
|
||||
if (!res) {
|
||||
g_string_printf(info->nmc->return_text, _("Error: not all connections migrated."));
|
||||
g_printerr(_("Error: Connection migration failed: %s\n"), error->message);
|
||||
g_error_free(error);
|
||||
info->nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||
} else {
|
||||
g_print(_("Connection '%s' (%s) successfully migrated.\n"),
|
||||
nm_connection_get_id(connection),
|
||||
nm_connection_get_uuid(connection));
|
||||
}
|
||||
connection_cb_info_finish(info, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
do_connection_migrate(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
||||
{
|
||||
NMConnection *connection;
|
||||
ConnectionCbInfo *info = NULL;
|
||||
gs_strfreev char **arg_arr = NULL;
|
||||
const char *const *arg_ptr;
|
||||
guint i;
|
||||
int arg_num;
|
||||
nm_auto_free_gstring GString *invalid_cons = NULL;
|
||||
gs_unref_ptrarray GPtrArray *found_cons = NULL;
|
||||
GError *error = NULL;
|
||||
const char *plugin = "keyfile";
|
||||
const GPtrArray *connections = NULL;
|
||||
int option;
|
||||
|
||||
if (nmc->timeout == -1)
|
||||
nmc->timeout = 10;
|
||||
|
||||
while ((option = next_arg(nmc, &argc, &argv, "--plugin", NULL)) > 0) {
|
||||
switch (option) {
|
||||
case 1: /* --plugin */
|
||||
argc--;
|
||||
argv++;
|
||||
if (!argc) {
|
||||
g_set_error_literal(&error, NMCLI_ERROR, 0, _("'--plugin' argument is missing"));
|
||||
goto finish;
|
||||
}
|
||||
plugin = *argv;
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
arg_ptr = argv;
|
||||
arg_num = argc;
|
||||
if (argc == 0) {
|
||||
if (nmc->ask) {
|
||||
gs_free char *line = NULL;
|
||||
|
||||
/* nmc_do_cmd() should not call this with argc=0. */
|
||||
g_assert(!nmc->complete);
|
||||
|
||||
line = nmc_readline(&nmc->nmc_config, PROMPT_CONNECTIONS);
|
||||
nmc_string_to_arg_array(line, NULL, TRUE, &arg_arr, &arg_num);
|
||||
arg_ptr = (const char *const *) arg_arr;
|
||||
}
|
||||
}
|
||||
|
||||
while (arg_num > 0) {
|
||||
const char *cur_selector, *cur_value;
|
||||
|
||||
connection =
|
||||
get_connection(nmc, &arg_num, &arg_ptr, &cur_selector, &cur_value, &found_cons, &error);
|
||||
if (!connection) {
|
||||
if (!nmc->complete)
|
||||
g_printerr(_("Error: %s.\n"), error->message);
|
||||
g_string_printf(nmc->return_text, _("Error: not all connections found."));
|
||||
nmc->return_value = error->code;
|
||||
g_clear_error(&error);
|
||||
|
||||
if (nmc->return_value != NMC_RESULT_ERROR_NOT_FOUND) {
|
||||
g_string_free(invalid_cons, TRUE);
|
||||
invalid_cons = NULL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!invalid_cons)
|
||||
invalid_cons = g_string_new(NULL);
|
||||
if (cur_selector)
|
||||
g_string_append_printf(invalid_cons, "%s '%s', ", cur_selector, cur_value);
|
||||
else
|
||||
g_string_append_printf(invalid_cons, "'%s', ", cur_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (nmc->complete)
|
||||
goto finish;
|
||||
|
||||
if (invalid_cons)
|
||||
goto finish;
|
||||
|
||||
if (!found_cons) {
|
||||
/* No connections specified explicitly? Fine, add all. */
|
||||
found_cons = g_ptr_array_new();
|
||||
connections = nm_client_get_connections(nmc->client);
|
||||
for (i = 0; i < connections->len; i++) {
|
||||
connection = connections->pdata[i];
|
||||
g_ptr_array_add(found_cons, connection);
|
||||
}
|
||||
}
|
||||
|
||||
info = g_slice_new0(ConnectionCbInfo);
|
||||
info->nmc = nmc;
|
||||
info->obj_list = g_ptr_array_sized_new(found_cons->len);
|
||||
for (i = 0; i < found_cons->len; i++) {
|
||||
connection = found_cons->pdata[i];
|
||||
g_ptr_array_add(info->obj_list, g_object_ref(connection));
|
||||
}
|
||||
info->timeout_id = g_timeout_add_seconds(nmc->timeout, connection_op_timeout_cb, info);
|
||||
info->cancellable = g_cancellable_new();
|
||||
|
||||
nmc->nowait_flag = (nmc->timeout == 0);
|
||||
nmc->should_wait++;
|
||||
|
||||
for (i = 0; i < found_cons->len; i++) {
|
||||
nm_remote_connection_update2(NM_REMOTE_CONNECTION(found_cons->pdata[i]),
|
||||
NULL,
|
||||
0,
|
||||
g_variant_new_parsed("{'plugin': <%s>}", plugin),
|
||||
info->cancellable,
|
||||
migrate_cb,
|
||||
info);
|
||||
}
|
||||
|
||||
finish:
|
||||
if (invalid_cons) {
|
||||
g_string_truncate(invalid_cons, invalid_cons->len - 2); /* truncate trailing ", " */
|
||||
g_string_printf(nmc->return_text,
|
||||
_("Error: cannot migrate unknown connection(s): %s."),
|
||||
invalid_cons->str);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
gen_func_connection_names(const char *text, int state)
|
||||
{
|
||||
|
|
@ -9752,6 +9913,7 @@ nmc_command_func_connection(const NMCCommand *cmd, NmCli *nmc, int argc, const c
|
|||
{"clone", do_connection_clone, usage_connection_clone, TRUE, TRUE},
|
||||
{"import", do_connection_import, usage_connection_import, TRUE, TRUE},
|
||||
{"export", do_connection_export, usage_connection_export, TRUE, TRUE},
|
||||
{"migrate", do_connection_migrate, usage_connection_migrate, TRUE, TRUE},
|
||||
{"monitor", do_connection_monitor, usage_connection_monitor, TRUE, TRUE},
|
||||
{NULL, do_connections_show, usage, TRUE, TRUE},
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue