summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-12-07 15:13:39 +0100
committerThomas Haller <thaller@redhat.com>2022-12-19 15:46:45 +0100
commit7218daac78c16884b77f3a583bca2a226a706b60 (patch)
treecae13f7150a8df348a34efad9fc9bbb6f66c055e
parentc9a8fd680898a2449074ce71bcf1e8aa27e784e6 (diff)
downloadNetworkManager-7218daac78c16884b77f3a583bca2a226a706b60.tar.gz
core: support flag "preserve-external-ip" for Reapply() call
Reapply() is supposed to make sure that the system (the interface) is configured as indicated by the applied-connection. That means, it will remove/add configuration to make the system match the requested configuration. Add a flag "preserve-external-ip" which relaxes this. During reapply, IP addresses/routes that exist on the interface and which are not known (or added) by NetworkManager will be left alone. This will be used by nm-cloud-setup, so that it can reconfigure the interface in a less destructive way, which does not conflict with external `ip addr/route` calls. Note that the previous commit just adds "VersionInfo" and the possibility to expose capabilities (patch-level). This is not used for the new reapply flag, because, while we might backport the reapply flag, we won't backport the "VersionInfo" property. Exposing new capabilities via the "VersionInfo" property will only become useful in the future, where we can backport a capability to older NM versions (but those that have "VersionInfo" too). (cherry picked from commit 2c1fb50fb56ee72b2cb9b7eb712e5c221d70379e)
-rw-r--r--introspection/org.freedesktop.NetworkManager.Device.xml5
-rw-r--r--src/core/devices/nm-device.c73
-rw-r--r--src/libnm-client-impl/nm-device.c4
-rw-r--r--src/libnm-core-public/nm-dbus-interface.h18
4 files changed, 69 insertions, 31 deletions
diff --git a/introspection/org.freedesktop.NetworkManager.Device.xml b/introspection/org.freedesktop.NetworkManager.Device.xml
index e694fcda3c..ae626a8eb5 100644
--- a/introspection/org.freedesktop.NetworkManager.Device.xml
+++ b/introspection/org.freedesktop.NetworkManager.Device.xml
@@ -322,7 +322,7 @@
Reapply:
@connection: The optional connection settings that will be reapplied on the device. If empty, the currently active settings-connection will be used. The connection cannot arbitrarily differ from the current applied-connection otherwise the call will fail. Only certain changes are supported, like adding or removing IP addresses.
@version_id: If non-zero, the current version id of the applied-connection must match. The current version id can be retrieved via GetAppliedConnection. This optional argument allows to catch concurrent modifications between the GetAppliedConnection call and Reapply.
- @flags: Flags which would modify the behavior of the Reapply call. There are no flags defined currently and the users should use the value of 0.
+ @flags: Flags which would modify the behavior of the Reapply call. Invalid flags are rejected.
Attempts to update the configuration of a device without deactivating it.
NetworkManager has the concept of connections, which are profiles that
@@ -344,6 +344,9 @@
Reapply can make the applied-connection different from the
settings-connection, just like updating the settings-connection can make
them different.
+
+ Since 1.42, 1.40.10, "preserve-external-ip" flag (0x1) is supported to not
+ remove externally added IP addresses and routes on the device during reapply.
-->
<method name="Reapply">
<arg name="connection" type="a{sa{sv}}" direction="in"/>
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 922579b234..594274d691 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -12791,6 +12791,7 @@ reapply_connection(NMDevice *self, NMConnection *con_old, NMConnection *con_new)
* the current settings connection
* @version_id: either zero, or the current version id for the applied
* connection.
+ * @reapply_flags: the #NMDeviceReapplyFlags.
* @audit_args: on return, a string representing the changes
* @error: the error if %FALSE is returned
*
@@ -12800,11 +12801,12 @@ reapply_connection(NMDevice *self, NMConnection *con_old, NMConnection *con_new)
* Return: %FALSE if the new configuration can not be reapplied.
*/
static gboolean
-check_and_reapply_connection(NMDevice *self,
- NMConnection *connection,
- guint64 version_id,
- char **audit_args,
- GError **error)
+check_and_reapply_connection(NMDevice *self,
+ NMConnection *connection,
+ guint64 version_id,
+ NMDeviceReapplyFlags reapply_flags,
+ char **audit_args,
+ GError **error)
{
NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -12972,7 +12974,12 @@ check_and_reapply_connection(NMDevice *self,
reactivate_proxy_config(self);
- nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE);
+ nm_device_l3cfg_commit(
+ self,
+ NM_FLAGS_HAS(reapply_flags, NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP)
+ ? NM_L3_CFG_COMMIT_TYPE_UPDATE
+ : NM_L3_CFG_COMMIT_TYPE_REAPPLY,
+ FALSE);
}
if (priv->state >= NM_DEVICE_STATE_IP_CHECK)
@@ -12989,12 +12996,18 @@ nm_device_reapply(NMDevice *self, NMConnection *connection, GError **error)
{
g_return_val_if_fail(NM_IS_DEVICE(self), FALSE);
- return check_and_reapply_connection(self, connection, 0, NULL, error);
+ return check_and_reapply_connection(self,
+ connection,
+ 0,
+ NM_DEVICE_REAPPLY_FLAGS_NONE,
+ NULL,
+ error);
}
typedef struct {
- NMConnection *connection;
- guint64 version_id;
+ NMConnection *connection;
+ guint64 version_id;
+ NMDeviceReapplyFlags reapply_flags;
} ReapplyData;
static void
@@ -13005,16 +13018,16 @@ reapply_cb(NMDevice *self,
gpointer user_data)
{
ReapplyData *reapply_data = user_data;
- guint64 version_id = 0;
- gs_unref_object NMConnection *connection = NULL;
- GError *local = NULL;
- gs_free char *audit_args = NULL;
+ guint64 version_id;
+ gs_unref_object NMConnection *connection = NULL;
+ NMDeviceReapplyFlags reapply_flags;
+ GError *local = NULL;
+ gs_free char *audit_args = NULL;
- if (reapply_data) {
- connection = reapply_data->connection;
- version_id = reapply_data->version_id;
- g_slice_free(ReapplyData, reapply_data);
- }
+ connection = reapply_data->connection;
+ version_id = reapply_data->version_id;
+ reapply_flags = reapply_data->reapply_flags;
+ nm_g_slice_free(reapply_data);
if (error) {
nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY,
@@ -13034,6 +13047,7 @@ reapply_cb(NMDevice *self,
connection
?: nm_device_get_settings_connection_get_connection(self),
version_id,
+ reapply_flags,
&audit_args,
&local)) {
nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY,
@@ -13067,12 +13081,12 @@ impl_device_reapply(NMDBusObject *obj,
ReapplyData *reapply_data;
gs_unref_variant GVariant *settings = NULL;
guint64 version_id;
- guint32 flags;
+ guint32 reapply_flags_u;
+ NMDeviceReapplyFlags reapply_flags;
- g_variant_get(parameters, "(@a{sa{sv}}tu)", &settings, &version_id, &flags);
+ g_variant_get(parameters, "(@a{sa{sv}}tu)", &settings, &version_id, &reapply_flags_u);
- /* No flags supported as of now. */
- if (flags != 0) {
+ if (NM_FLAGS_ANY(reapply_flags_u, ~((guint32) NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP))) {
error =
g_error_new_literal(NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "Invalid flags specified");
nm_audit_log_device_op(NM_AUDIT_OP_DEVICE_REAPPLY,
@@ -13085,6 +13099,9 @@ impl_device_reapply(NMDBusObject *obj,
return;
}
+ reapply_flags = reapply_flags_u;
+ nm_assert(reapply_flags_u == reapply_flags);
+
if (priv->state < NM_DEVICE_STATE_PREPARE || priv->state > NM_DEVICE_STATE_ACTIVATED) {
error = g_error_new_literal(NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ACTIVE,
@@ -13122,12 +13139,12 @@ impl_device_reapply(NMDBusObject *obj,
nm_connection_clear_secrets(connection);
}
- if (connection || version_id) {
- reapply_data = g_slice_new(ReapplyData);
- reapply_data->connection = connection;
- reapply_data->version_id = version_id;
- } else
- reapply_data = NULL;
+ reapply_data = g_slice_new(ReapplyData);
+ *reapply_data = (ReapplyData){
+ .connection = connection,
+ .version_id = version_id,
+ .reapply_flags = reapply_flags,
+ };
nm_device_auth_request(self,
invocation,
diff --git a/src/libnm-client-impl/nm-device.c b/src/libnm-client-impl/nm-device.c
index 238e7c1709..0e971d39b5 100644
--- a/src/libnm-client-impl/nm-device.c
+++ b/src/libnm-client-impl/nm-device.c
@@ -2496,7 +2496,7 @@ nm_device_reapply_finish(NMDevice *device, GAsyncResult *result, GError **error)
/**
* nm_device_get_applied_connection:
* @device: a #NMDevice
- * @flags: the flags argument. Currently, this value must always be zero.
+ * @flags: the flags argument. See #NMDeviceReapplyFlags.
* @version_id: (out) (allow-none): returns the current version id of
* the applied connection
* @cancellable: a #GCancellable, or %NULL
@@ -2559,7 +2559,7 @@ nm_device_get_applied_connection(NMDevice *device,
/**
* nm_device_get_applied_connection_async:
* @device: a #NMDevice
- * @flags: the flags argument. Currently, this value must always be zero.
+ * @flags: the flags argument. See #NMDeviceReapplyFlags.
* @cancellable: a #GCancellable, or %NULL
* @callback: callback to be called when the reapply operation completes
* @user_data: caller-specific data passed to @callback
diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h
index 6e1a84a1dd..3e79d4c670 100644
--- a/src/libnm-core-public/nm-dbus-interface.h
+++ b/src/libnm-core-public/nm-dbus-interface.h
@@ -1145,6 +1145,24 @@ typedef enum /*< flags >*/ {
} NMSettingsUpdate2Flags;
/**
+ * NMDeviceReapplyFlags:
+ * @NM_DEVICE_REAPPLY_FLAGS_NONE: no flag set.
+ * @NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP: during reapply,
+ * preserve external IP addresses and routes.
+ *
+ * Flags for the Reapply() D-Bus call of a device and
+ * nm_device_reapply_async().
+ *
+ * Since: 1.42, 1.40.10
+ *
+ * On 1.40.10+, no GFlags type is created.
+ */
+typedef enum /*< skip >*/ {
+ NM_DEVICE_REAPPLY_FLAGS_NONE = 0,
+ NM_DEVICE_REAPPLY_FLAGS_PRESERVE_EXTERNAL_IP = 0x1,
+} NMDeviceReapplyFlags;
+
+/**
* NMTernary:
* @NM_TERNARY_DEFAULT: use the globally-configured default value.
* @NM_TERNARY_FALSE: the option is disabled.