mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-03-21 19:10:45 +01:00
checkpoint: introduce new flags to better restore previous state
When a global checkpoint is created (one with empty device list) we save the status of all devices to restore it later. After the checkpoint new interfaces and connections may appear and they can significantly influence the overall networking status, but we don't consider them at the moment. Introduce a new flag DELETE_NEW_CONNECTIONS to delete any connection added after the checkpoint and similarly a DISCONNECT_NEW_DEVICES to ensure that the connection active on newly appeared devices doesn't disrupt network connectivity. https://bugzilla.redhat.com/show_bug.cgi?id=1378393
This commit is contained in:
parent
a5e3016fc9
commit
ddeef464af
4 changed files with 69 additions and 5 deletions
|
|
@ -712,14 +712,20 @@ typedef enum {
|
|||
* @NM_CHECKPOINT_CREATE_FLAG_NONE: no flags
|
||||
* @NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL: when creating
|
||||
* a new checkpoint, destroy all existing ones.
|
||||
* @NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS: upon rollback,
|
||||
* delete any new connection added after the checkpoint.
|
||||
* @NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES: upon rollback,
|
||||
* disconnect any new device appeared after the checkpoint.
|
||||
*
|
||||
* The flags for CheckpointCreate call
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
typedef enum { /*< skip >*/
|
||||
NM_CHECKPOINT_CREATE_FLAG_NONE = 0,
|
||||
NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL = 0x01,
|
||||
NM_CHECKPOINT_CREATE_FLAG_NONE = 0,
|
||||
NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL = 0x01,
|
||||
NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS = 0x02,
|
||||
NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES = 0x04,
|
||||
} NMCheckpointCreateFlags;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -155,6 +155,10 @@ nm_checkpoint_manager_create (NMCheckpointManager *self,
|
|||
if (!device_paths || !device_paths[0]) {
|
||||
device_paths_free = nm_manager_get_device_paths (manager);
|
||||
device_paths = (const char *const *) device_paths_free;
|
||||
} else if (NM_FLAGS_HAS (flags, NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES)) {
|
||||
g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_INVALID_ARGUMENTS,
|
||||
"the DISCONNECT_NEW_DEVICES flag can only be used with an empty device list");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
devices = g_ptr_array_new ();
|
||||
|
|
@ -180,7 +184,7 @@ nm_checkpoint_manager_create (NMCheckpointManager *self,
|
|||
}
|
||||
}
|
||||
|
||||
checkpoint = nm_checkpoint_new (manager, devices, rollback_timeout, error);
|
||||
checkpoint = nm_checkpoint_new (manager, devices, rollback_timeout, flags, error);
|
||||
if (!checkpoint)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ typedef struct {
|
|||
/* private members */
|
||||
NMManager *manager;
|
||||
gint64 rollback_ts;
|
||||
NMCheckpointCreateFlags flags;
|
||||
GHashTable *connection_uuids;
|
||||
} NMCheckpointPrivate;
|
||||
|
||||
struct _NMCheckpoint {
|
||||
|
|
@ -245,6 +247,47 @@ next_dev:
|
|||
g_variant_builder_add (&builder, "{su}", dev_checkpoint->original_dev_path, result);
|
||||
}
|
||||
|
||||
if (NM_FLAGS_HAS (priv->flags, NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS)) {
|
||||
NMSettingsConnection *con;
|
||||
gs_free_slist GSList *list = NULL;
|
||||
GSList *item;
|
||||
|
||||
g_return_val_if_fail (priv->connection_uuids, NULL);
|
||||
list = nm_settings_get_connections_sorted (nm_settings_get ());
|
||||
|
||||
for (item = list; item; item = g_slist_next (item)) {
|
||||
con = item->data;
|
||||
if (!g_hash_table_contains (priv->connection_uuids,
|
||||
nm_settings_connection_get_uuid (con))) {
|
||||
_LOGD ("rollback: deleting new connection %s (%s)",
|
||||
nm_settings_connection_get_uuid (con),
|
||||
nm_settings_connection_get_id (con));
|
||||
nm_settings_connection_delete (con, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NM_FLAGS_HAS (priv->flags, NM_CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES)) {
|
||||
const GSList *list = nm_manager_get_devices (priv->manager);
|
||||
NMDeviceState state;
|
||||
NMDevice *dev;
|
||||
|
||||
for (list = nm_manager_get_devices (priv->manager); list ; list = g_slist_next (list)) {
|
||||
dev = list->data;
|
||||
if (!g_hash_table_contains (priv->devices, dev)) {
|
||||
state = nm_device_get_state (dev);
|
||||
if ( state > NM_DEVICE_STATE_DISCONNECTED
|
||||
&& state < NM_DEVICE_STATE_DEACTIVATING) {
|
||||
_LOGD ("rollback: disconnecting new device %s", nm_device_get_iface (dev));
|
||||
nm_device_state_changed (dev,
|
||||
NM_DEVICE_STATE_DEACTIVATING,
|
||||
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return g_variant_new ("(a{su})", &builder);
|
||||
}
|
||||
|
||||
|
|
@ -340,10 +383,11 @@ nm_checkpoint_init (NMCheckpoint *self)
|
|||
|
||||
NMCheckpoint *
|
||||
nm_checkpoint_new (NMManager *manager, GPtrArray *devices, guint32 rollback_timeout,
|
||||
GError **error)
|
||||
NMCheckpointCreateFlags flags, GError **error)
|
||||
{
|
||||
NMCheckpoint *self;
|
||||
NMCheckpointPrivate *priv;
|
||||
NMSettingsConnection *const *con;
|
||||
DeviceCheckpoint *dev_checkpoint;
|
||||
NMDevice *device;
|
||||
guint i;
|
||||
|
|
@ -370,6 +414,15 @@ nm_checkpoint_new (NMManager *manager, GPtrArray *devices, guint32 rollback_time
|
|||
priv->rollback_ts = rollback_timeout ?
|
||||
(nm_utils_get_monotonic_timestamp_ms () + ((gint64) rollback_timeout * 1000)) :
|
||||
0;
|
||||
priv->flags = flags;
|
||||
|
||||
if (NM_FLAGS_HAS (flags, NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS)) {
|
||||
priv->connection_uuids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
for (con = nm_settings_get_connections (nm_settings_get (), NULL); *con; con++) {
|
||||
g_hash_table_add (priv->connection_uuids,
|
||||
g_strdup (nm_settings_connection_get_uuid (*con)));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < devices->len; i++) {
|
||||
device = (NMDevice *) devices->pdata[i];
|
||||
|
|
@ -391,6 +444,7 @@ dispose (GObject *object)
|
|||
NMCheckpointPrivate *priv = NM_CHECKPOINT_GET_PRIVATE (self);
|
||||
|
||||
g_clear_pointer (&priv->devices, g_hash_table_unref);
|
||||
g_clear_pointer (&priv->connection_uuids, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (nm_checkpoint_parent_class)->dispose (object);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ typedef struct _NMCheckpointClass NMCheckpointClass;
|
|||
GType nm_checkpoint_get_type (void);
|
||||
|
||||
NMCheckpoint *nm_checkpoint_new (NMManager *manager, GPtrArray *devices, guint32 rollback_timeout,
|
||||
GError **error);
|
||||
NMCheckpointCreateFlags flags, GError **error);
|
||||
|
||||
guint64 nm_checkpoint_get_rollback_ts (NMCheckpoint *checkpoint);
|
||||
gboolean nm_checkpoint_includes_device (NMCheckpoint *checkpoint, NMDevice *device);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue