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  }