Merge pull request #12184 from adrianreber/2021-11-05-stats-dump

Add 'stats-dump' file to exported checkpoint
This commit is contained in:
OpenShift Merge Robot
2021-11-08 09:29:56 +01:00
committed by GitHub
9 changed files with 636 additions and 3 deletions

View File

@ -21,6 +21,7 @@ import (
"time"
metadata "github.com/checkpoint-restore/checkpointctl/lib"
"github.com/checkpoint-restore/go-criu/v5/stats"
cdi "github.com/container-orchestrated-devices/container-device-interface/pkg"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/buildah/pkg/chrootuser"
@ -1013,6 +1014,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
metadata.ConfigDumpFile,
metadata.SpecDumpFile,
metadata.NetworkStatusFile,
stats.StatsDump,
}
if c.LogDriver() == define.KubernetesLogging ||
@ -1197,7 +1199,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
if !options.Keep && !options.PreCheckPoint {
cleanup := []string{
"dump.log",
"stats-dump",
stats.StatsDump,
metadata.ConfigDumpFile,
metadata.SpecDumpFile,
}
@ -1564,8 +1566,8 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
cleanup := [...]string{
"restore.log",
"dump.log",
"stats-dump",
"stats-restore",
stats.StatsDump,
stats.StatsRestore,
metadata.NetworkStatusFile,
metadata.RootFsDiffTar,
metadata.DeletedFilesFile,

View File

@ -6,6 +6,7 @@ import (
"os"
metadata "github.com/checkpoint-restore/checkpointctl/lib"
"github.com/checkpoint-restore/go-criu/v5/stats"
"github.com/containers/common/libimage"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod"
@ -39,6 +40,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
"volumes",
"ctr.log",
"artifacts",
stats.StatsDump,
metadata.RootFsDiffTar,
metadata.DeletedFilesFile,
metadata.NetworkStatusFile,

View File

@ -5,9 +5,11 @@ import (
"net"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/checkpoint-restore/go-criu/v5/stats"
"github.com/containers/podman/v3/pkg/checkpoint/crutils"
"github.com/containers/podman/v3/pkg/criu"
. "github.com/containers/podman/v3/test/utils"
@ -1191,4 +1193,55 @@ var _ = Describe("Podman checkpoint", func() {
// Remove exported checkpoint
os.Remove(fileName)
})
It("podman checkpoint container with export and statistics", func() {
localRunString := getRunString([]string{
"--rm",
ALPINE,
"top",
})
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
cid := session.OutputToString()
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
result := podmanTest.Podman([]string{
"container",
"checkpoint",
"-l", "-e",
fileName,
})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
// Extract checkpoint archive
destinationDirectory, err := CreateTempDirInTempDir()
Expect(err).ShouldNot(HaveOccurred())
tarsession := SystemExec(
"tar",
[]string{
"xf",
fileName,
"-C",
destinationDirectory,
},
)
Expect(tarsession).Should(Exit(0))
_, err = os.Stat(filepath.Join(destinationDirectory, stats.StatsDump))
Expect(err).ShouldNot(HaveOccurred())
Expect(os.RemoveAll(destinationDirectory)).To(BeNil())
// Remove exported checkpoint
os.Remove(fileName)
})
})

View File

@ -0,0 +1,12 @@
package magic
const (
ImgCommonMagic = 0x54564319 /* Sarov (a.k.a. Arzamas-16) */
ImgServiceMagic = 0x55105940 /* Zlatoust */
StatsMagic = 0x57093306 /* Ostashkov */
PrimaryMagicOffset = 0x0
SecondaryMagicOffset = 0x4
SizeOffset = 0x8
PayloadOffset = 0xC
)

View File

@ -0,0 +1,462 @@
// SPDX-License-Identifier: MIT
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.12.4
// source: stats/stats.proto
package stats
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This one contains statistics about dump/restore process
type DumpStatsEntry struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FreezingTime *uint32 `protobuf:"varint,1,req,name=freezing_time,json=freezingTime" json:"freezing_time,omitempty"`
FrozenTime *uint32 `protobuf:"varint,2,req,name=frozen_time,json=frozenTime" json:"frozen_time,omitempty"`
MemdumpTime *uint32 `protobuf:"varint,3,req,name=memdump_time,json=memdumpTime" json:"memdump_time,omitempty"`
MemwriteTime *uint32 `protobuf:"varint,4,req,name=memwrite_time,json=memwriteTime" json:"memwrite_time,omitempty"`
PagesScanned *uint64 `protobuf:"varint,5,req,name=pages_scanned,json=pagesScanned" json:"pages_scanned,omitempty"`
PagesSkippedParent *uint64 `protobuf:"varint,6,req,name=pages_skipped_parent,json=pagesSkippedParent" json:"pages_skipped_parent,omitempty"`
PagesWritten *uint64 `protobuf:"varint,7,req,name=pages_written,json=pagesWritten" json:"pages_written,omitempty"`
IrmapResolve *uint32 `protobuf:"varint,8,opt,name=irmap_resolve,json=irmapResolve" json:"irmap_resolve,omitempty"`
PagesLazy *uint64 `protobuf:"varint,9,req,name=pages_lazy,json=pagesLazy" json:"pages_lazy,omitempty"`
PagePipes *uint64 `protobuf:"varint,10,opt,name=page_pipes,json=pagePipes" json:"page_pipes,omitempty"`
PagePipeBufs *uint64 `protobuf:"varint,11,opt,name=page_pipe_bufs,json=pagePipeBufs" json:"page_pipe_bufs,omitempty"`
ShpagesScanned *uint64 `protobuf:"varint,12,opt,name=shpages_scanned,json=shpagesScanned" json:"shpages_scanned,omitempty"`
ShpagesSkippedParent *uint64 `protobuf:"varint,13,opt,name=shpages_skipped_parent,json=shpagesSkippedParent" json:"shpages_skipped_parent,omitempty"`
ShpagesWritten *uint64 `protobuf:"varint,14,opt,name=shpages_written,json=shpagesWritten" json:"shpages_written,omitempty"`
}
func (x *DumpStatsEntry) Reset() {
*x = DumpStatsEntry{}
if protoimpl.UnsafeEnabled {
mi := &file_stats_stats_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DumpStatsEntry) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DumpStatsEntry) ProtoMessage() {}
func (x *DumpStatsEntry) ProtoReflect() protoreflect.Message {
mi := &file_stats_stats_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DumpStatsEntry.ProtoReflect.Descriptor instead.
func (*DumpStatsEntry) Descriptor() ([]byte, []int) {
return file_stats_stats_proto_rawDescGZIP(), []int{0}
}
func (x *DumpStatsEntry) GetFreezingTime() uint32 {
if x != nil && x.FreezingTime != nil {
return *x.FreezingTime
}
return 0
}
func (x *DumpStatsEntry) GetFrozenTime() uint32 {
if x != nil && x.FrozenTime != nil {
return *x.FrozenTime
}
return 0
}
func (x *DumpStatsEntry) GetMemdumpTime() uint32 {
if x != nil && x.MemdumpTime != nil {
return *x.MemdumpTime
}
return 0
}
func (x *DumpStatsEntry) GetMemwriteTime() uint32 {
if x != nil && x.MemwriteTime != nil {
return *x.MemwriteTime
}
return 0
}
func (x *DumpStatsEntry) GetPagesScanned() uint64 {
if x != nil && x.PagesScanned != nil {
return *x.PagesScanned
}
return 0
}
func (x *DumpStatsEntry) GetPagesSkippedParent() uint64 {
if x != nil && x.PagesSkippedParent != nil {
return *x.PagesSkippedParent
}
return 0
}
func (x *DumpStatsEntry) GetPagesWritten() uint64 {
if x != nil && x.PagesWritten != nil {
return *x.PagesWritten
}
return 0
}
func (x *DumpStatsEntry) GetIrmapResolve() uint32 {
if x != nil && x.IrmapResolve != nil {
return *x.IrmapResolve
}
return 0
}
func (x *DumpStatsEntry) GetPagesLazy() uint64 {
if x != nil && x.PagesLazy != nil {
return *x.PagesLazy
}
return 0
}
func (x *DumpStatsEntry) GetPagePipes() uint64 {
if x != nil && x.PagePipes != nil {
return *x.PagePipes
}
return 0
}
func (x *DumpStatsEntry) GetPagePipeBufs() uint64 {
if x != nil && x.PagePipeBufs != nil {
return *x.PagePipeBufs
}
return 0
}
func (x *DumpStatsEntry) GetShpagesScanned() uint64 {
if x != nil && x.ShpagesScanned != nil {
return *x.ShpagesScanned
}
return 0
}
func (x *DumpStatsEntry) GetShpagesSkippedParent() uint64 {
if x != nil && x.ShpagesSkippedParent != nil {
return *x.ShpagesSkippedParent
}
return 0
}
func (x *DumpStatsEntry) GetShpagesWritten() uint64 {
if x != nil && x.ShpagesWritten != nil {
return *x.ShpagesWritten
}
return 0
}
type RestoreStatsEntry struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PagesCompared *uint64 `protobuf:"varint,1,req,name=pages_compared,json=pagesCompared" json:"pages_compared,omitempty"`
PagesSkippedCow *uint64 `protobuf:"varint,2,req,name=pages_skipped_cow,json=pagesSkippedCow" json:"pages_skipped_cow,omitempty"`
ForkingTime *uint32 `protobuf:"varint,3,req,name=forking_time,json=forkingTime" json:"forking_time,omitempty"`
RestoreTime *uint32 `protobuf:"varint,4,req,name=restore_time,json=restoreTime" json:"restore_time,omitempty"`
PagesRestored *uint64 `protobuf:"varint,5,opt,name=pages_restored,json=pagesRestored" json:"pages_restored,omitempty"`
}
func (x *RestoreStatsEntry) Reset() {
*x = RestoreStatsEntry{}
if protoimpl.UnsafeEnabled {
mi := &file_stats_stats_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RestoreStatsEntry) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RestoreStatsEntry) ProtoMessage() {}
func (x *RestoreStatsEntry) ProtoReflect() protoreflect.Message {
mi := &file_stats_stats_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RestoreStatsEntry.ProtoReflect.Descriptor instead.
func (*RestoreStatsEntry) Descriptor() ([]byte, []int) {
return file_stats_stats_proto_rawDescGZIP(), []int{1}
}
func (x *RestoreStatsEntry) GetPagesCompared() uint64 {
if x != nil && x.PagesCompared != nil {
return *x.PagesCompared
}
return 0
}
func (x *RestoreStatsEntry) GetPagesSkippedCow() uint64 {
if x != nil && x.PagesSkippedCow != nil {
return *x.PagesSkippedCow
}
return 0
}
func (x *RestoreStatsEntry) GetForkingTime() uint32 {
if x != nil && x.ForkingTime != nil {
return *x.ForkingTime
}
return 0
}
func (x *RestoreStatsEntry) GetRestoreTime() uint32 {
if x != nil && x.RestoreTime != nil {
return *x.RestoreTime
}
return 0
}
func (x *RestoreStatsEntry) GetPagesRestored() uint64 {
if x != nil && x.PagesRestored != nil {
return *x.PagesRestored
}
return 0
}
type StatsEntry struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Dump *DumpStatsEntry `protobuf:"bytes,1,opt,name=dump" json:"dump,omitempty"`
Restore *RestoreStatsEntry `protobuf:"bytes,2,opt,name=restore" json:"restore,omitempty"`
}
func (x *StatsEntry) Reset() {
*x = StatsEntry{}
if protoimpl.UnsafeEnabled {
mi := &file_stats_stats_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *StatsEntry) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StatsEntry) ProtoMessage() {}
func (x *StatsEntry) ProtoReflect() protoreflect.Message {
mi := &file_stats_stats_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StatsEntry.ProtoReflect.Descriptor instead.
func (*StatsEntry) Descriptor() ([]byte, []int) {
return file_stats_stats_proto_rawDescGZIP(), []int{2}
}
func (x *StatsEntry) GetDump() *DumpStatsEntry {
if x != nil {
return x.Dump
}
return nil
}
func (x *StatsEntry) GetRestore() *RestoreStatsEntry {
if x != nil {
return x.Restore
}
return nil
}
var File_stats_stats_proto protoreflect.FileDescriptor
var file_stats_stats_proto_rawDesc = []byte{
0x0a, 0x11, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xad, 0x04, 0x0a, 0x10, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x73, 0x74, 0x61,
0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x72, 0x65, 0x65,
0x7a, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x0d, 0x52,
0x0c, 0x66, 0x72, 0x65, 0x65, 0x7a, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a,
0x0b, 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x02,
0x28, 0x0d, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21,
0x0a, 0x0c, 0x6d, 0x65, 0x6d, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03,
0x20, 0x02, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x64, 0x75, 0x6d, 0x70, 0x54, 0x69, 0x6d,
0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x6d, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x69,
0x6d, 0x65, 0x18, 0x04, 0x20, 0x02, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x77, 0x72, 0x69,
0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x67, 0x65, 0x73, 0x5f,
0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x18, 0x05, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0c, 0x70,
0x61, 0x67, 0x65, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x70,
0x61, 0x67, 0x65, 0x73, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x02, 0x28, 0x04, 0x52, 0x12, 0x70, 0x61, 0x67, 0x65, 0x73,
0x53, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a,
0x0d, 0x70, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x18, 0x07,
0x20, 0x02, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x61, 0x67, 0x65, 0x73, 0x57, 0x72, 0x69, 0x74, 0x74,
0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x72, 0x6d, 0x61, 0x70, 0x5f, 0x72, 0x65, 0x73, 0x6f,
0x6c, 0x76, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x69, 0x72, 0x6d, 0x61, 0x70,
0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x73,
0x5f, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x09, 0x20, 0x02, 0x28, 0x04, 0x52, 0x09, 0x70, 0x61, 0x67,
0x65, 0x73, 0x4c, 0x61, 0x7a, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x70,
0x69, 0x70, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65,
0x50, 0x69, 0x70, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x69,
0x70, 0x65, 0x5f, 0x62, 0x75, 0x66, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70,
0x61, 0x67, 0x65, 0x50, 0x69, 0x70, 0x65, 0x42, 0x75, 0x66, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73,
0x68, 0x70, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x18, 0x0c,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x68, 0x70, 0x61, 0x67, 0x65, 0x73, 0x53, 0x63, 0x61,
0x6e, 0x6e, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x68, 0x70, 0x61, 0x67, 0x65, 0x73, 0x5f,
0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x0d,
0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x73, 0x68, 0x70, 0x61, 0x67, 0x65, 0x73, 0x53, 0x6b, 0x69,
0x70, 0x70, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x68,
0x70, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x18, 0x0e, 0x20,
0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x68, 0x70, 0x61, 0x67, 0x65, 0x73, 0x57, 0x72, 0x69, 0x74,
0x74, 0x65, 0x6e, 0x22, 0xd5, 0x01, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f,
0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x70,
0x61, 0x67, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20,
0x02, 0x28, 0x04, 0x52, 0x0d, 0x70, 0x61, 0x67, 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72,
0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x73, 0x6b, 0x69, 0x70,
0x70, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x02, 0x28, 0x04, 0x52, 0x0f, 0x70,
0x61, 0x67, 0x65, 0x73, 0x53, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x43, 0x6f, 0x77, 0x12, 0x21,
0x0a, 0x0c, 0x66, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03,
0x20, 0x02, 0x28, 0x0d, 0x52, 0x0b, 0x66, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d,
0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d,
0x65, 0x18, 0x04, 0x20, 0x02, 0x28, 0x0d, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65,
0x54, 0x69, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x72, 0x65,
0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x70, 0x61,
0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x22, 0x64, 0x0a, 0x0b, 0x73,
0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x04, 0x64, 0x75,
0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x64, 0x75, 0x6d, 0x70, 0x5f,
0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x75, 0x6d,
0x70, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x14, 0x2e, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x74, 0x61,
0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72,
0x65,
}
var (
file_stats_stats_proto_rawDescOnce sync.Once
file_stats_stats_proto_rawDescData = file_stats_stats_proto_rawDesc
)
func file_stats_stats_proto_rawDescGZIP() []byte {
file_stats_stats_proto_rawDescOnce.Do(func() {
file_stats_stats_proto_rawDescData = protoimpl.X.CompressGZIP(file_stats_stats_proto_rawDescData)
})
return file_stats_stats_proto_rawDescData
}
var file_stats_stats_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_stats_stats_proto_goTypes = []interface{}{
(*DumpStatsEntry)(nil), // 0: dump_stats_entry
(*RestoreStatsEntry)(nil), // 1: restore_stats_entry
(*StatsEntry)(nil), // 2: stats_entry
}
var file_stats_stats_proto_depIdxs = []int32{
0, // 0: stats_entry.dump:type_name -> dump_stats_entry
1, // 1: stats_entry.restore:type_name -> restore_stats_entry
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_stats_stats_proto_init() }
func file_stats_stats_proto_init() {
if File_stats_stats_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_stats_stats_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DumpStatsEntry); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_stats_stats_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RestoreStatsEntry); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_stats_stats_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StatsEntry); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_stats_stats_proto_rawDesc,
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_stats_stats_proto_goTypes,
DependencyIndexes: file_stats_stats_proto_depIdxs,
MessageInfos: file_stats_stats_proto_msgTypes,
}.Build()
File_stats_stats_proto = out.File
file_stats_stats_proto_rawDesc = nil
file_stats_stats_proto_goTypes = nil
file_stats_stats_proto_depIdxs = nil
}

View File

@ -0,0 +1,40 @@
// SPDX-License-Identifier: MIT
syntax = "proto2";
// This one contains statistics about dump/restore process
message dump_stats_entry {
required uint32 freezing_time = 1;
required uint32 frozen_time = 2;
required uint32 memdump_time = 3;
required uint32 memwrite_time = 4;
required uint64 pages_scanned = 5;
required uint64 pages_skipped_parent = 6;
required uint64 pages_written = 7;
optional uint32 irmap_resolve = 8;
required uint64 pages_lazy = 9;
optional uint64 page_pipes = 10;
optional uint64 page_pipe_bufs = 11;
optional uint64 shpages_scanned = 12;
optional uint64 shpages_skipped_parent = 13;
optional uint64 shpages_written = 14;
}
message restore_stats_entry {
required uint64 pages_compared = 1;
required uint64 pages_skipped_cow = 2;
required uint32 forking_time = 3;
required uint32 restore_time = 4;
optional uint64 pages_restored = 5;
}
message stats_entry {
optional dump_stats_entry dump = 1;
optional restore_stats_entry restore = 2;
}

View File

@ -0,0 +1,6 @@
package stats
const (
StatsDump = "stats-dump"
StatsRestore = "stats-restore"
)

View File

@ -0,0 +1,54 @@
package stats
import (
"encoding/binary"
"errors"
"io/ioutil"
"os"
"path/filepath"
"github.com/checkpoint-restore/go-criu/v5/magic"
"google.golang.org/protobuf/proto"
)
func readStatisticsFile(imgDir *os.File, fileName string) (*StatsEntry, error) {
buf, err := ioutil.ReadFile(filepath.Join(imgDir.Name(), fileName))
if err != nil {
return nil, err
}
if binary.LittleEndian.Uint32(buf[magic.PrimaryMagicOffset:magic.SecondaryMagicOffset]) != magic.ImgServiceMagic {
return nil, errors.New("Primary magic not found")
}
if binary.LittleEndian.Uint32(buf[magic.SecondaryMagicOffset:magic.SizeOffset]) != magic.StatsMagic {
return nil, errors.New("Secondary magic not found")
}
payloadSize := binary.LittleEndian.Uint32(buf[magic.SizeOffset:magic.PayloadOffset])
st := &StatsEntry{}
if err := proto.Unmarshal(buf[magic.PayloadOffset:magic.PayloadOffset+payloadSize], st); err != nil {
return nil, err
}
return st, nil
}
func CriuGetDumpStats(imgDir *os.File) (*DumpStatsEntry, error) {
st, err := readStatisticsFile(imgDir, StatsDump)
if err != nil {
return nil, err
}
return st.GetDump(), nil
}
func CriuGetRestoreStats(imgDir *os.File) (*RestoreStatsEntry, error) {
st, err := readStatisticsFile(imgDir, StatsRestore)
if err != nil {
return nil, err
}
return st.GetRestore(), nil
}

2
vendor/modules.txt vendored
View File

@ -47,7 +47,9 @@ github.com/cespare/xxhash/v2
github.com/checkpoint-restore/checkpointctl/lib
# github.com/checkpoint-restore/go-criu/v5 v5.2.0
github.com/checkpoint-restore/go-criu/v5
github.com/checkpoint-restore/go-criu/v5/magic
github.com/checkpoint-restore/go-criu/v5/rpc
github.com/checkpoint-restore/go-criu/v5/stats
# github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/chzyer/readline
# github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9