Add more checkpoint/restore information to 'inspect'

This adds the following information to the output of 'podman inspect':

 * CheckpointedAt - time the container was checkpointed
   Only set if the container has been checkpointed

 * RestoredAt - time the container was restored
   Only set if the container has been restored

 * CheckpointLog - path to the checkpoint log file (CRIU's dump.log)
   Only set if the log file exists (--keep)

 * RestoreLog - path to the restore log file (CRIU's restore.log)
   Only set if the log file exists (--keep)

 * CheckpointPath - path to the actual (CRIU) checkpoint files
   Only set if the checkpoint files exists (--keep)

 * Restored - set to true if the container has been restored
   Only set if the container has been restored

Signed-off-by: Adrian Reber <areber@redhat.com>
This commit is contained in:
Adrian Reber
2021-12-15 16:37:02 +00:00
parent 91e55e263e
commit bc3389e212
5 changed files with 82 additions and 30 deletions

View File

@ -213,6 +213,15 @@ type ContainerState struct {
// containerPlatformState holds platform-specific container state.
containerPlatformState
// Following checkpoint/restore related information is displayed
// if the container has been checkpointed or restored.
CheckpointedTime time.Time `json:"checkpointedTime,omitempty"`
RestoredTime time.Time `json:"restoredTime,omitempty"`
CheckpointLog string `json:"checkpointLog,omitempty"`
CheckpointPath string `json:"checkpointPath,omitempty"`
RestoreLog string `json:"restoreLog,omitempty"`
Restored bool `json:"restored,omitempty"`
}
// ContainerNamedVolume is a named volume that will be mounted into the

View File

@ -127,6 +127,12 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
FinishedAt: runtimeInfo.FinishedTime,
Checkpointed: runtimeInfo.Checkpointed,
CgroupPath: cgroupPath,
RestoredAt: runtimeInfo.RestoredTime,
CheckpointedAt: runtimeInfo.CheckpointedTime,
Restored: runtimeInfo.Restored,
CheckpointPath: runtimeInfo.CheckpointPath,
CheckpointLog: runtimeInfo.CheckpointLog,
RestoreLog: runtimeInfo.RestoreLog,
},
Image: config.RootfsImageID,
ImageName: config.RootfsImageName,

View File

@ -634,6 +634,12 @@ func resetState(state *ContainerState) {
state.RestartPolicyMatch = false
state.RestartCount = 0
state.Checkpointed = false
state.Restored = false
state.CheckpointedTime = time.Time{}
state.RestoredTime = time.Time{}
state.CheckpointPath = ""
state.CheckpointLog = ""
state.RestoreLog = ""
}
// Refresh refreshes the container's state after a restart.
@ -1111,6 +1117,12 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
}
c.state.Checkpointed = false
c.state.Restored = false
c.state.CheckpointedTime = time.Time{}
c.state.RestoredTime = time.Time{}
c.state.CheckpointPath = ""
c.state.CheckpointLog = ""
c.state.RestoreLog = ""
c.state.ExitCode = 0
c.state.Exited = false
c.state.State = define.ContainerStateCreated

View File

@ -1134,6 +1134,10 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
return nil, 0, err
}
// Setting CheckpointLog early in case there is a failure.
c.state.CheckpointLog = path.Join(c.bundlePath(), "dump.log")
c.state.CheckpointPath = c.CheckpointPath()
runtimeCheckpointDuration, err := c.ociRuntime.CheckpointContainer(c, options)
if err != nil {
return nil, 0, err
@ -1169,6 +1173,9 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
if !options.KeepRunning && !options.PreCheckPoint {
c.state.State = define.ContainerStateStopped
c.state.Checkpointed = true
c.state.CheckpointedTime = time.Now()
c.state.Restored = false
c.state.RestoredTime = time.Time{}
// Cleanup Storage and Network
if err := c.cleanup(ctx); err != nil {
@ -1216,6 +1223,8 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
logrus.Debugf("Unable to remove file %s", file)
}
}
// The file has been deleted. Do not mention it.
c.state.CheckpointLog = ""
}
c.state.FinishedTime = time.Now()
@ -1293,6 +1302,10 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return nil, 0, err
}
// Setting RestoreLog early in case there is a failure.
c.state.RestoreLog = path.Join(c.bundlePath(), "restore.log")
c.state.CheckpointPath = c.CheckpointPath()
// Read network configuration from checkpoint
var netStatus map[string]types.StatusBlock
_, err := metadata.ReadJSONFile(&netStatus, c.bundlePath(), metadata.NetworkStatusFile)
@ -1559,6 +1572,9 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
c.state.State = define.ContainerStateRunning
c.state.Checkpointed = false
c.state.Restored = true
c.state.CheckpointedTime = time.Time{}
c.state.RestoredTime = time.Now()
if !options.Keep {
// Delete all checkpoint related files. At this point, in theory, all files
@ -1569,6 +1585,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if err != nil {
logrus.Debugf("Non-fatal: removal of checkpoint directory (%s) failed: %v", c.CheckpointPath(), err)
}
c.state.CheckpointPath = ""
err = os.RemoveAll(c.PreCheckPointPath())
if err != nil {
logrus.Debugf("Non-fatal: removal of pre-checkpoint directory (%s) failed: %v", c.PreCheckPointPath(), err)
@ -1589,6 +1606,8 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
logrus.Debugf("Non-fatal: removal of checkpoint file (%s) failed: %v", file, err)
}
}
c.state.CheckpointLog = ""
c.state.RestoreLog = ""
}
return criuStatistics, runtimeRestoreDuration, c.save()

View File

@ -205,6 +205,12 @@ type InspectContainerState struct {
Health HealthCheckResults `json:"Health,omitempty"`
Checkpointed bool `json:"Checkpointed,omitempty"`
CgroupPath string `json:"CgroupPath,omitempty"`
CheckpointedAt time.Time `json:"CheckpointedAt,omitempty"`
RestoredAt time.Time `json:"RestoredAt,omitempty"`
CheckpointLog string `json:"CheckpointLog,omitempty"`
CheckpointPath string `json:"CheckpointPath,omitempty"`
RestoreLog string `json:"RestoreLog,omitempty"`
Restored bool `json:"Restored,omitempty"`
}
// Healthcheck returns the HealthCheckResults. This is used for old podman compat