summaryrefslogtreecommitdiff
path: root/src/nm-checkpoint.c
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-03-28 08:09:56 +0200
committerThomas Haller <thaller@redhat.com>2018-04-04 14:02:13 +0200
commitf67303221bdc8098cb3b6203ec777b294e412971 (patch)
treec084b9d71667d8bdb8617e36cc965ee437ee751f /src/nm-checkpoint.c
parentab8312a18e8b281a62f39ce59a077fda77943187 (diff)
downloadNetworkManager-f67303221bdc8098cb3b6203ec777b294e412971.tar.gz
checkpoint: allow resetting the rollback timeout via D-Bus
This allows to adjust the timeout of an existing checkpoint. The main usecase of checkpoints, is to have a fail-safe when configuring the network remotely. By allowing to reset the timeout, the user can perform a series of actions, and keep bumping the timeout. That way, the entire series is still guarded by the same checkpoint, but the user can start with short timeout, and re-adjust the timeout as he goes along. The libnm API only implements the async form (at least for now). Sync methods are fundamentally wrong with D-Bus, and it's probably not needed. Also, follow glib convenction, where the async form doesn't have the _async name suffix. Also, accept a D-Bus path as argument, not a NMCheckpoint instance. The libnm API should not be more restricted than the underlying D-Bus API. It would be cumbersome to require the user to lookup the NMCheckpoint instance first, especially since libnm doesn't provide an efficient or convenient lookup-by-path method. On the other hand, retrieving the path from a NMCheckpoint instance is always possible.
Diffstat (limited to 'src/nm-checkpoint.c')
-rw-r--r--src/nm-checkpoint.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c
index 29e748bb39..f7e857c558 100644
--- a/src/nm-checkpoint.c
+++ b/src/nm-checkpoint.c
@@ -48,7 +48,7 @@ typedef struct {
NMUnmanFlagOp unmanaged_explicit;
} DeviceCheckpoint;
-NM_GOBJECT_PROPERTIES_DEFINE_BASE (
+NM_GOBJECT_PROPERTIES_DEFINE (NMCheckpoint,
PROP_DEVICES,
PROP_CREATED,
PROP_ROLLBACK_TIMEOUT,
@@ -474,6 +474,42 @@ _timeout_cb (gpointer user_data)
return G_SOURCE_REMOVE;
}
+void
+nm_checkpoint_adjust_rollback_timeout (NMCheckpoint *self, guint32 add_timeout)
+{
+ guint32 rollback_timeout_s;
+ gint64 now_ms, add_timeout_ms, rollback_timeout_ms;
+
+ NMCheckpointPrivate *priv = NM_CHECKPOINT_GET_PRIVATE (self);
+
+ nm_clear_g_source (&priv->timeout_id);
+
+ if (add_timeout == 0)
+ rollback_timeout_s = 0;
+ else {
+ now_ms = nm_utils_get_monotonic_timestamp_ms ();
+ add_timeout_ms = ((gint64) add_timeout) * 1000;
+ rollback_timeout_ms = (now_ms - priv->created_at_ms) + add_timeout_ms;
+
+ /* round to nearest integer second. Since NM_CHECKPOINT_ROLLBACK_TIMEOUT is
+ * in units seconds, it will be able to exactly express the timeout. */
+ rollback_timeout_s = NM_MIN ((rollback_timeout_ms + 500) / 1000, (gint64) G_MAXUINT32);
+
+ /* we expect the timeout to be positive, because add_timeout_ms is positive.
+ * We cannot accept a zero, because it means "infinity". */
+ nm_assert (rollback_timeout_s > 0);
+
+ priv->timeout_id = g_timeout_add (NM_MIN (add_timeout_ms, (gint64) G_MAXUINT32),
+ _timeout_cb,
+ self);
+ }
+
+ if (rollback_timeout_s != priv->rollback_timeout_s) {
+ priv->rollback_timeout_s = rollback_timeout_s;
+ _notify (self, PROP_ROLLBACK_TIMEOUT);
+ }
+}
+
/*****************************************************************************/
static void