github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/libcontainerd/client_liverestore_linux.go (about) 1 // +build experimental 2 3 package libcontainerd 4 5 import ( 6 "fmt" 7 8 "github.com/Sirupsen/logrus" 9 containerd "github.com/docker/containerd/api/grpc/types" 10 ) 11 12 func (clnt *client) restore(cont *containerd.Container, options ...CreateOption) (err error) { 13 clnt.lock(cont.Id) 14 defer clnt.unlock(cont.Id) 15 16 logrus.Debugf("restore container %s state %s", cont.Id, cont.Status) 17 18 containerID := cont.Id 19 if _, err := clnt.getContainer(containerID); err == nil { 20 return fmt.Errorf("container %s is already active", containerID) 21 } 22 23 defer func() { 24 if err != nil { 25 clnt.deleteContainer(cont.Id) 26 } 27 }() 28 29 container := clnt.newContainer(cont.BundlePath, options...) 30 container.systemPid = systemPid(cont) 31 32 var terminal bool 33 for _, p := range cont.Processes { 34 if p.Pid == InitFriendlyName { 35 terminal = p.Terminal 36 } 37 } 38 39 iopipe, err := container.openFifos(terminal) 40 if err != nil { 41 return err 42 } 43 44 if err := clnt.backend.AttachStreams(containerID, *iopipe); err != nil { 45 return err 46 } 47 48 clnt.appendContainer(container) 49 50 err = clnt.backend.StateChanged(containerID, StateInfo{ 51 CommonStateInfo: CommonStateInfo{ 52 State: StateRestore, 53 Pid: container.systemPid, 54 }}) 55 56 if err != nil { 57 return err 58 } 59 60 if event, ok := clnt.remote.pastEvents[containerID]; ok { 61 // This should only be a pause or resume event 62 if event.Type == StatePause || event.Type == StateResume { 63 return clnt.backend.StateChanged(containerID, StateInfo{ 64 CommonStateInfo: CommonStateInfo{ 65 State: event.Type, 66 Pid: container.systemPid, 67 }}) 68 } 69 70 logrus.Warnf("unexpected backlog event: %#v", event) 71 } 72 73 return nil 74 } 75 76 func (clnt *client) Restore(containerID string, options ...CreateOption) error { 77 cont, err := clnt.getContainerdContainer(containerID) 78 if err == nil && cont.Status != "stopped" { 79 if err := clnt.restore(cont, options...); err != nil { 80 logrus.Errorf("error restoring %s: %v", containerID, err) 81 } 82 return nil 83 } 84 return clnt.setExited(containerID) 85 }