core: device: implement storing to disk for Device.SetManaged()

If the NM_DEVICE_MANAGED_FLAGS_PERMANENT flag is used, the value will be
stored to disk, to the NetworkManager-intern.conf file, in a [device-*]
section.

To modify the runtime value, the NM_DEVICE_MANAGED_FLAGS_RUNTIME must be
passed. This allows to control independently whether to modify only one
or both.
This commit is contained in:
Íñigo Huguet 2026-02-24 11:33:49 +01:00
parent d5256111ba
commit 60a77f0fab
4 changed files with 69 additions and 9 deletions

View file

@ -397,10 +397,11 @@
<!--
SetManaged:
@managed: Whether the device is managed.
@flags: Flags which would modify the behavior of the SetManaged call. Invalid flags are rejected.
@flags: (<link linkend="NMDeviceManagedFlags">NMDeviceManagedFlags</link>) flags.
@since: 1.58
Set the managed state of the device.
Set the managed state of the device. With the flags argument different
behaviors can be achieved, like storing the new managed state to disk.
-->
<method name="SetManaged">
<arg name="managed" type="b" direction="in"/>

View file

@ -5,6 +5,7 @@ src/core/NetworkManagerUtils.c
src/core/devices/adsl/nm-device-adsl.c
src/core/devices/bluetooth/nm-bluez-manager.c
src/core/devices/bluetooth/nm-device-bt.c
src/core/devices/nm-device.c
src/core/devices/nm-device-6lowpan.c
src/core/devices/nm-device-bond.c
src/core/devices/nm-device-bridge.c

View file

@ -14942,16 +14942,67 @@ typedef struct {
NMDeviceManagedFlags managed_flags;
} SetManagedData;
/**
* set_managed:
* @self: the device
* @managed: the new managed state to set.
* @flags: flags to select different behaviors like storing to disk.
* @error: return location for a #GError, or %NULL
*
* Sets the managed state of the device. It can affect the runtime managed state
* if the %NM_DEVICE_MANAGED_FLAGS_RUNTIME is set, and to the value stored on disk
* (persistent across reboots) state if the %NM_DEVICE_MANAGED_FLAGS_PERMANENT is set.
*
* Returns: %TRUE if the managed state was set successfully, %FALSE otherwise.
*/
static gboolean
set_managed(NMDevice *self, gboolean managed, NMDeviceManagedFlags flags, GError **error)
{
gboolean old;
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
gboolean managed_old;
NMTernary managed_to_disk_old;
g_object_get(self, NM_DEVICE_MANAGED, &old, NULL);
g_object_set(self, NM_DEVICE_MANAGED, managed, NULL);
g_object_get(self, NM_DEVICE_MANAGED, &managed, NULL);
if (old != managed)
_notify(self, PROP_MANAGED);
if (flags & NM_DEVICE_MANAGED_FLAGS_PERMANENT) {
managed_to_disk_old = nm_config_get_device_managed(nm_manager_get_config(priv->manager),
nm_device_get_iface(self));
if (!nm_config_set_device_managed(nm_manager_get_config(priv->manager),
self,
managed,
flags & NM_DEVICE_MANAGED_FLAGS_BY_MAC,
error))
return FALSE;
/* Update the unmanaged flags after the change on disk */
nm_device_set_unmanaged_by_user_conf(self);
if (!!nm_device_get_unmanaged_flags(self, NM_UNMANAGED_USER_CONF) != !managed) {
/* We failed to make the new state effective on disk. Maybe the new config
* collides with other config. Try to revert and return error. Otherwise,
* we would set the runtime state correctly, but get an unexpected state
* after a reboot. */
nm_config_set_device_managed(nm_manager_get_config(priv->manager),
self,
managed_to_disk_old,
flags & NM_DEVICE_MANAGED_FLAGS_BY_MAC,
error);
g_set_error(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_FAILED,
_("failed to persist 'managed=%d' on disk, other configurations may be "
"overriding it"),
managed);
return FALSE;
}
}
if (flags & NM_DEVICE_MANAGED_FLAGS_RUNTIME) {
g_object_get(self, NM_DEVICE_MANAGED, &managed_old, NULL);
g_object_set(self, NM_DEVICE_MANAGED, !!managed, NULL);
g_object_get(self, NM_DEVICE_MANAGED, &managed, NULL);
if (managed_old != managed)
_notify(self, PROP_MANAGED);
}
return TRUE;
}

View file

@ -1248,13 +1248,20 @@ typedef enum /*< flags >*/ {
/**
* NMDeviceManagedFlags:
* @NM_DEVICE_MANAGED_FLAGS_NONE: no flag set.
* @NM_DEVICE_MANAGED_FLAGS_RUNTIME: to set the device managed state to the runtime value.
* @NM_DEVICE_MANAGED_FLAGS_PERMANENT: to set the device managed state to the permanent (on disk) value.
* @NM_DEVICE_MANAGED_FLAGS_BY_MAC: to match the device by MAC address, not by name.
* This option only makes sense together with %NM_DEVICE_MANAGED_FLAGS_PERMANENT.
*
* Flags for the SetManaged() D-Bus call of a device and nm_device_set_managed_async().
*
* Since: 1.58
*/
typedef enum /*< flags >*/ {
NM_DEVICE_MANAGED_FLAGS_NONE = 0,
NM_DEVICE_MANAGED_FLAGS_NONE = 0,
NM_DEVICE_MANAGED_FLAGS_RUNTIME = 0x1,
NM_DEVICE_MANAGED_FLAGS_PERMANENT = 0x2,
NM_DEVICE_MANAGED_FLAGS_BY_MAC = 0x4,
} NMDeviceManagedFlags;
/**