-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathmetadata.go
150 lines (127 loc) · 4.43 KB
/
metadata.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// SPDX-License-Identifier: Apache-2.0
package metadata
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"
spec "github.com/opencontainers/runtime-spec/specs-go"
)
const (
// container archive
ConfigDumpFile = "config.dump"
SpecDumpFile = "spec.dump"
StatusDumpFile = "status.dump"
NetworkStatusFile = "network.status"
CheckpointDirectory = "checkpoint"
CheckpointVolumesDirectory = "volumes"
DevShmCheckpointTar = "devshm-checkpoint.tar"
RootFsDiffTar = "rootfs-diff.tar"
DeletedFilesFile = "deleted.files"
DumpLogFile = "dump.log"
RestoreLogFile = "restore.log"
// pod archive
PodOptionsFile = "pod.options"
PodDumpFile = "pod.dump"
// containerd only
StatusFile = "status"
// CRIU Images
PagesPrefix = "pages-"
AmdgpuPagesPrefix = "amdgpu-pages-"
)
// This is a reduced copy of what Podman uses to store checkpoint metadata
type ContainerConfig struct {
ID string `json:"id"`
Name string `json:"name"`
RootfsImage string `json:"rootfsImage,omitempty"`
RootfsImageRef string `json:"rootfsImageRef,omitempty"`
RootfsImageName string `json:"rootfsImageName,omitempty"`
OCIRuntime string `json:"runtime,omitempty"`
CreatedTime time.Time `json:"createdTime"`
CheckpointedAt time.Time `json:"checkpointedTime"`
RestoredAt time.Time `json:"restoredTime"`
Restored bool `json:"restored"`
}
type Spec struct {
Annotations map[string]string `json:"annotations,omitempty"`
}
type ContainerdStatus struct {
CreatedAt int64
StartedAt int64
FinishedAt int64
ExitCode int32
Pid uint32
Reason string
Message string
}
// This structure is used by the KubernetesContainerCheckpointMetadata structure
type KubernetesCheckpoint struct {
Archive string `json:"archive,omitempty"`
Size int64 `json:"size,omitempty"`
Timestamp int64 `json:"timestamp,omitempty"`
}
// This structure is the basis for Kubernetes to track how many checkpoints
// for a certain container have been created.
type KubernetesContainerCheckpointMetadata struct {
PodFullName string `json:"podFullName,omitempty"`
ContainerName string `json:"containerName,omitempty"`
TotalSize int64 `json:"totalSize,omitempty"`
Checkpoints []KubernetesCheckpoint `json:"checkpoints"`
}
func ReadContainerCheckpointSpecDump(checkpointDirectory string) (*spec.Spec, string, error) {
var specDump spec.Spec
specDumpFile, err := ReadJSONFile(&specDump, checkpointDirectory, SpecDumpFile)
return &specDump, specDumpFile, err
}
func ReadContainerCheckpointConfigDump(checkpointDirectory string) (*ContainerConfig, string, error) {
var containerConfig ContainerConfig
configDumpFile, err := ReadJSONFile(&containerConfig, checkpointDirectory, ConfigDumpFile)
return &containerConfig, configDumpFile, err
}
func ReadContainerCheckpointDeletedFiles(checkpointDirectory string) ([]string, string, error) {
var deletedFiles []string
deletedFilesFile, err := ReadJSONFile(&deletedFiles, checkpointDirectory, DeletedFilesFile)
return deletedFiles, deletedFilesFile, err
}
func ReadContainerCheckpointStatusFile(checkpointDirectory string) (*ContainerdStatus, string, error) {
var containerdStatus ContainerdStatus
statusFile, err := ReadJSONFile(&containerdStatus, checkpointDirectory, StatusFile)
return &containerdStatus, statusFile, err
}
// WriteJSONFile marshalls and writes the given data to a JSON file
func WriteJSONFile(v interface{}, dir, file string) (string, error) {
fileJSON, err := json.MarshalIndent(v, "", " ")
if err != nil {
return "", fmt.Errorf("error marshalling JSON: %w", err)
}
file = filepath.Join(dir, file)
if err := os.WriteFile(file, fileJSON, 0o600); err != nil {
return "", err
}
return file, nil
}
func ReadJSONFile(v interface{}, dir, file string) (string, error) {
file = filepath.Join(dir, file)
content, err := os.ReadFile(file)
if err != nil {
return "", err
}
if err = json.Unmarshal(content, v); err != nil {
return "", fmt.Errorf("failed to unmarshal %s: %w", file, err)
}
return file, nil
}
func ByteToString(b int64) string {
const unit = 1024
if b < unit {
return fmt.Sprintf("%d B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %ciB",
float64(b)/float64(div), "KMGTPE"[exp])
}