Skip to content

Commit 60daa41

Browse files
committed
Allow to checkpoint and restore a container with console
runc already supports this case, so we just need to run it with proper options. Signed-off-by: Andrei Vagin <[email protected]>
1 parent 0846d6f commit 60daa41

2 files changed

Lines changed: 40 additions & 19 deletions

File tree

cmd/ctr/commands/tasks/tasks_unix.go

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,24 @@ func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Consol
6969
// NewTask creates a new task
7070
func NewTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, checkpoint string, tty, nullIO bool, ioOpts []cio.Opt, opts ...containerd.NewTaskOpts) (containerd.Task, error) {
7171
stdio := cio.NewCreator(append([]cio.Opt{cio.WithStdio}, ioOpts...)...)
72-
if checkpoint == "" {
73-
ioCreator := stdio
74-
if tty {
75-
ioCreator = cio.NewCreator(append([]cio.Opt{cio.WithStdio, cio.WithTerminal}, ioOpts...)...)
76-
}
77-
if nullIO {
78-
if tty {
79-
return nil, errors.New("tty and null-io cannot be used together")
80-
}
81-
ioCreator = cio.NullIO
72+
if checkpoint != "" {
73+
im, err := client.GetImage(ctx, checkpoint)
74+
if err != nil {
75+
return nil, err
8276
}
83-
return container.NewTask(ctx, ioCreator, opts...)
77+
opts = append(opts, containerd.WithTaskCheckpoint(im))
8478
}
85-
im, err := client.GetImage(ctx, checkpoint)
86-
if err != nil {
87-
return nil, err
79+
ioCreator := stdio
80+
if tty {
81+
ioCreator = cio.NewCreator(append([]cio.Opt{cio.WithStdio, cio.WithTerminal}, ioOpts...)...)
82+
}
83+
if nullIO {
84+
if tty {
85+
return nil, errors.New("tty and null-io cannot be used together")
86+
}
87+
ioCreator = cio.NullIO
8888
}
89-
opts = append(opts, containerd.WithTaskCheckpoint(im))
90-
return container.NewTask(ctx, stdio, opts...)
89+
return container.NewTask(ctx, ioCreator, opts...)
9190
}
9291

9392
func getNewTaskOpts(context *cli.Context) []containerd.NewTaskOpts {

linux/proc/init_state.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,23 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
194194
s.p.mu.Lock()
195195
defer s.p.mu.Unlock()
196196
p := s.p
197+
sio := p.stdio
198+
199+
var (
200+
err error
201+
socket *runc.Socket
202+
)
203+
if sio.Terminal {
204+
if socket, err = runc.NewTempConsoleSocket(); err != nil {
205+
return errors.Wrap(err, "failed to create OCI runtime console socket")
206+
}
207+
defer socket.Close()
208+
s.opts.ConsoleSocket = socket
209+
}
210+
197211
if _, err := s.p.runtime.Restore(ctx, p.id, p.bundle, s.opts); err != nil {
198212
return p.runtimeError(err, "OCI runtime restore failed")
199213
}
200-
sio := p.stdio
201214
if sio.Stdin != "" {
202215
sc, err := fifo.OpenFifo(ctx, sio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0)
203216
if err != nil {
@@ -207,7 +220,17 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
207220
p.closers = append(p.closers, sc)
208221
}
209222
var copyWaitGroup sync.WaitGroup
210-
if !sio.IsNull() {
223+
if socket != nil {
224+
console, err := socket.ReceiveMaster()
225+
if err != nil {
226+
return errors.Wrap(err, "failed to retrieve console master")
227+
}
228+
console, err = p.platform.CopyConsole(ctx, console, sio.Stdin, sio.Stdout, sio.Stderr, &p.wg, &copyWaitGroup)
229+
if err != nil {
230+
return errors.Wrap(err, "failed to start console copy")
231+
}
232+
p.console = console
233+
} else if !sio.IsNull() {
211234
if err := copyPipes(ctx, p.io, sio.Stdin, sio.Stdout, sio.Stderr, &p.wg, &copyWaitGroup); err != nil {
212235
return errors.Wrap(err, "failed to start io pipe copy")
213236
}
@@ -219,7 +242,6 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
219242
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
220243
}
221244
p.pid = pid
222-
223245
return s.transition("running")
224246
}
225247

0 commit comments

Comments
 (0)