@@ -19,7 +19,7 @@ import (
19
19
"github.com/checkpoint-restore/go-criu/v7/crit"
20
20
"github.com/containers/storage/pkg/archive"
21
21
"github.com/olekukonko/tablewriter"
22
- spec "github.com/opencontainers/runtime-spec/specs-go"
22
+ specs "github.com/opencontainers/runtime-spec/specs-go"
23
23
)
24
24
25
25
var pageSize = os .Getpagesize ()
@@ -41,20 +41,42 @@ type containerInfo struct {
41
41
42
42
type checkpointInfo struct {
43
43
containerInfo * containerInfo
44
- specDump * spec .Spec
44
+ specDump * specs .Spec
45
45
configDump * metadata.ContainerConfig
46
46
archiveSizes * archiveSizes
47
47
}
48
48
49
- func getPodmanInfo (containerConfig * metadata.ContainerConfig , _ * spec .Spec ) * containerInfo {
50
- return & containerInfo {
49
+ func getPodmanInfo (containerConfig * metadata.ContainerConfig , specDump * specs .Spec , task Task ) * containerInfo {
50
+ info := & containerInfo {
51
51
Name : containerConfig .Name ,
52
52
Created : containerConfig .CreatedTime .Format (time .RFC3339 ),
53
53
Engine : "Podman" ,
54
54
}
55
+
56
+ // Try to get network information from network.status file
57
+ if specDump .Annotations ["io.container.manager" ] == "libpod" {
58
+ // Create temp dir for network status file
59
+ tmpDir , err := os .MkdirTemp ("" , "network-status" )
60
+ if err == nil {
61
+ defer os .RemoveAll (tmpDir )
62
+
63
+ // Extract network.status file
64
+ err = UntarFiles (task .CheckpointFilePath , tmpDir , []string {metadata .NetworkStatusFile })
65
+ if err == nil {
66
+ networkStatusFile := filepath .Join (tmpDir , metadata .NetworkStatusFile )
67
+ ip , mac , err := getPodmanNetworkInfo (networkStatusFile )
68
+ if err == nil {
69
+ info .IP = ip
70
+ info .MAC = mac
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ return info
55
77
}
56
78
57
- func getContainerdInfo (containerConfig * metadata.ContainerConfig , specDump * spec .Spec ) * containerInfo {
79
+ func getContainerdInfo (containerConfig * metadata.ContainerConfig , specDump * specs .Spec ) * containerInfo {
58
80
return & containerInfo {
59
81
Name : specDump .Annotations ["io.kubernetes.cri.container-name" ],
60
82
Created : containerConfig .CreatedTime .Format (time .RFC3339 ),
@@ -64,7 +86,7 @@ func getContainerdInfo(containerConfig *metadata.ContainerConfig, specDump *spec
64
86
}
65
87
}
66
88
67
- func getCRIOInfo (_ * metadata.ContainerConfig , specDump * spec .Spec ) (* containerInfo , error ) {
89
+ func getCRIOInfo (_ * metadata.ContainerConfig , specDump * specs .Spec ) (* containerInfo , error ) {
68
90
cm := containerMetadata {}
69
91
if err := json .Unmarshal ([]byte (specDump .Annotations ["io.kubernetes.cri-o.Metadata" ]), & cm ); err != nil {
70
92
return nil , fmt .Errorf ("failed to read io.kubernetes.cri-o.Metadata: %w" , err )
@@ -86,14 +108,23 @@ func getCheckpointInfo(task Task) (*checkpointInfo, error) {
86
108
87
109
info .configDump , _ , err = metadata .ReadContainerCheckpointConfigDump (task .OutputDir )
88
110
if err != nil {
89
- return nil , err
111
+ if strings .Contains (err .Error (), "unexpected end of JSON input" ) {
112
+ return nil , fmt .Errorf ("config.dump: unexpected end of JSON input" )
113
+ }
114
+ return nil , fmt .Errorf ("config.dump: %w" , err )
90
115
}
91
116
info .specDump , _ , err = metadata .ReadContainerCheckpointSpecDump (task .OutputDir )
92
117
if err != nil {
93
- return nil , err
118
+ if os .IsNotExist (err ) {
119
+ return nil , fmt .Errorf ("spec.dump: no such file or directory" )
120
+ }
121
+ if strings .Contains (err .Error (), "unexpected end of JSON input" ) {
122
+ return nil , fmt .Errorf ("spec.dump: unexpected end of JSON input" )
123
+ }
124
+ return nil , fmt .Errorf ("spec.dump: %w" , err )
94
125
}
95
126
96
- info .containerInfo , err = getContainerInfo (info .specDump , info .configDump )
127
+ info .containerInfo , err = getContainerInfo (info .specDump , info .configDump , task )
97
128
if err != nil {
98
129
return nil , err
99
130
}
@@ -115,18 +146,25 @@ func ShowContainerCheckpoints(tasks []Task) error {
115
146
"Runtime" ,
116
147
"Created" ,
117
148
"Engine" ,
118
- }
119
- // Set all columns in the table header upfront when displaying more than one checkpoint
120
- if len ( tasks ) > 1 {
121
- header = append ( header , "IP" , "MAC" , "CHKPT Size" , " Root Fs Diff Size")
149
+ "IP" ,
150
+ "MAC" ,
151
+ "CHKPT Size" ,
152
+ " Root FS Diff Size",
122
153
}
123
154
124
155
for _ , task := range tasks {
125
156
info , err := getCheckpointInfo (task )
126
157
if err != nil {
158
+ if strings .Contains (err .Error (), "Error: " ) {
159
+ return fmt .Errorf ("%s" , strings .TrimPrefix (err .Error (), "Error: " ))
160
+ }
127
161
return err
128
162
}
129
163
164
+ if len (tasks ) == 1 {
165
+ fmt .Printf ("Displaying container checkpoint data from %s\n " , task .CheckpointFilePath )
166
+ }
167
+
130
168
var row []string
131
169
row = append (row , info .containerInfo .Name )
132
170
row = append (row , info .configDump .RootfsImageName )
@@ -135,37 +173,13 @@ func ShowContainerCheckpoints(tasks []Task) error {
135
173
} else {
136
174
row = append (row , info .configDump .ID )
137
175
}
138
-
139
176
row = append (row , info .configDump .OCIRuntime )
140
177
row = append (row , info .containerInfo .Created )
141
178
row = append (row , info .containerInfo .Engine )
142
-
143
- if len (tasks ) == 1 {
144
- fmt .Printf ("\n Displaying container checkpoint data from %s\n \n " , task .CheckpointFilePath )
145
-
146
- if info .containerInfo .IP != "" {
147
- header = append (header , "IP" )
148
- row = append (row , info .containerInfo .IP )
149
- }
150
- if info .containerInfo .MAC != "" {
151
- header = append (header , "MAC" )
152
- row = append (row , info .containerInfo .MAC )
153
- }
154
-
155
- header = append (header , "CHKPT Size" )
156
- row = append (row , metadata .ByteToString (info .archiveSizes .checkpointSize ))
157
-
158
- // Display root fs diff size if available
159
- if info .archiveSizes .rootFsDiffTarSize != 0 {
160
- header = append (header , "Root Fs Diff Size" )
161
- row = append (row , metadata .ByteToString (info .archiveSizes .rootFsDiffTarSize ))
162
- }
163
- } else {
164
- row = append (row , info .containerInfo .IP )
165
- row = append (row , info .containerInfo .MAC )
166
- row = append (row , metadata .ByteToString (info .archiveSizes .checkpointSize ))
167
- row = append (row , metadata .ByteToString (info .archiveSizes .rootFsDiffTarSize ))
168
- }
179
+ row = append (row , info .containerInfo .IP )
180
+ row = append (row , info .containerInfo .MAC )
181
+ row = append (row , metadata .ByteToString (info .archiveSizes .checkpointSize ))
182
+ row = append (row , metadata .ByteToString (info .archiveSizes .rootFsDiffTarSize ))
169
183
170
184
table .Append (row )
171
185
}
@@ -178,11 +192,11 @@ func ShowContainerCheckpoints(tasks []Task) error {
178
192
return nil
179
193
}
180
194
181
- func getContainerInfo (specDump * spec .Spec , containerConfig * metadata.ContainerConfig ) (* containerInfo , error ) {
195
+ func getContainerInfo (specDump * specs .Spec , containerConfig * metadata.ContainerConfig , task Task ) (* containerInfo , error ) {
182
196
var ci * containerInfo
183
197
switch m := specDump .Annotations ["io.container.manager" ]; m {
184
198
case "libpod" :
185
- ci = getPodmanInfo (containerConfig , specDump )
199
+ ci = getPodmanInfo (containerConfig , specDump , task )
186
200
case "cri-o" :
187
201
var err error
188
202
ci , err = getCRIOInfo (containerConfig , specDump )
@@ -266,7 +280,7 @@ func UntarFiles(src, dest string, files []string) error {
266
280
}
267
281
return nil
268
282
}); err != nil {
269
- return fmt . Errorf ( "unpacking of checkpoint archive failed: %w" , err )
283
+ return err
270
284
}
271
285
272
286
return nil
0 commit comments