Merge pull request #3375 from kolyshkin/rm-container-iface

libct: rm BaseContainer and Container interfaces
This commit is contained in:
Sebastiaan van Stijn
2022-03-23 21:23:50 +01:00
committed by GitHub
12 changed files with 128 additions and 194 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ import (
"golang.org/x/sys/unix"
)
func killContainer(container libcontainer.Container) error {
func killContainer(container *libcontainer.Container) error {
_ = container.Signal(unix.SIGKILL, false)
for i := 0; i < 100; i++ {
time.Sleep(100 * time.Millisecond)
-67
View File
@@ -5,11 +5,9 @@
package libcontainer
import (
"os"
"time"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runtime-spec/specs-go"
)
// Status is the status of a container.
@@ -59,68 +57,3 @@ type BaseState struct {
// Config is the container's configuration.
Config configs.Config `json:"config"`
}
// BaseContainer is a libcontainer container object.
//
// Each container is thread-safe within the same process. Since a container can
// be destroyed by a separate process, any function may return that the container
// was not found. BaseContainer includes methods that are platform agnostic.
type BaseContainer interface {
// Returns the ID of the container
ID() string
// Returns the current status of the container.
Status() (Status, error)
// State returns the current container's state information.
State() (*State, error)
// OCIState returns the current container's state information.
OCIState() (*specs.State, error)
// Returns the current config of the container.
Config() configs.Config
// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
//
// Some of the returned PIDs may no longer refer to processes in the Container, unless
// the Container state is PAUSED in which case every PID in the slice is valid.
Processes() ([]int, error)
// Returns statistics for the container.
Stats() (*Stats, error)
// Set resources of container as configured
//
// We can use this to change resources when containers are running.
//
Set(config configs.Config) error
// Start a process inside the container. Returns error if process fails to
// start. You can track process lifecycle with passed Process structure.
Start(process *Process) (err error)
// Run immediately starts the process inside the container. Returns error if process
// fails to start. It does not block waiting for the exec fifo after start returns but
// opens the fifo after start returns.
Run(process *Process) (err error)
// Destroys the container, if its in a valid state, after killing any
// remaining running processes.
//
// Any event registrations are removed before the container is destroyed.
// No error is returned if the container is already destroyed.
//
// Running containers must first be stopped using Signal(..).
// Paused containers must first be resumed using Resume(..).
Destroy() error
// Signal sends the provided signal code to the container's initial process.
//
// If all is specified the signal is sent to all processes in the container
// including the initial process.
Signal(s os.Signal, all bool) error
// Exec signals the container to exec the users process at the end of the init.
Exec() error
}
+97 -92
View File
@@ -36,7 +36,8 @@ import (
const stdioFdCount = 3
type linuxContainer struct {
// Container is a libcontainer container object.
type Container struct {
id string
root string
config *configs.Config
@@ -80,69 +81,44 @@ type State struct {
IntelRdtPath string `json:"intel_rdt_path"`
}
// Container is a libcontainer container object.
//
// Each container is thread-safe within the same process. Since a container can
// be destroyed by a separate process, any function may return that the container
// was not found.
type Container interface {
BaseContainer
// Methods below here are platform specific
// Checkpoint checkpoints the running container's state to disk using the criu(8) utility.
Checkpoint(criuOpts *CriuOpts) error
// Restore restores the checkpointed container to a running state using the criu(8) utility.
Restore(process *Process, criuOpts *CriuOpts) error
// If the Container state is RUNNING or CREATED, sets the Container state to PAUSED and pauses
// the execution of any user processes. Asynchronously, when the container finished being paused the
// state is changed to PAUSED.
// If the Container state is PAUSED, do nothing.
Pause() error
// If the Container state is PAUSED, resumes the execution of any user processes in the
// Container before setting the Container state to RUNNING.
// If the Container state is RUNNING, do nothing.
Resume() error
// NotifyOOM returns a read-only channel signaling when the container receives an OOM notification.
NotifyOOM() (<-chan struct{}, error)
// NotifyMemoryPressure returns a read-only channel signaling when the container reaches a given pressure level
NotifyMemoryPressure(level PressureLevel) (<-chan struct{}, error)
}
// ID returns the container's unique ID
func (c *linuxContainer) ID() string {
func (c *Container) ID() string {
return c.id
}
// Config returns the container's configuration
func (c *linuxContainer) Config() configs.Config {
func (c *Container) Config() configs.Config {
return *c.config
}
func (c *linuxContainer) Status() (Status, error) {
// Status returns the current status of the container.
func (c *Container) Status() (Status, error) {
c.m.Lock()
defer c.m.Unlock()
return c.currentStatus()
}
func (c *linuxContainer) State() (*State, error) {
// State returns the current container's state information.
func (c *Container) State() (*State, error) {
c.m.Lock()
defer c.m.Unlock()
return c.currentState()
}
func (c *linuxContainer) OCIState() (*specs.State, error) {
// OCIState returns the current container's state information.
func (c *Container) OCIState() (*specs.State, error) {
c.m.Lock()
defer c.m.Unlock()
return c.currentOCIState()
}
func (c *linuxContainer) Processes() ([]int, error) {
// Processes returns the PIDs inside this container. The PIDs are in the
// namespace of the calling process.
//
// Some of the returned PIDs may no longer refer to processes in the container,
// unless the container state is PAUSED in which case every PID in the slice is
// valid.
func (c *Container) Processes() ([]int, error) {
var pids []int
status, err := c.currentStatus()
if err != nil {
@@ -160,7 +136,8 @@ func (c *linuxContainer) Processes() ([]int, error) {
return pids, nil
}
func (c *linuxContainer) Stats() (*Stats, error) {
// Stats returns statistics for the container.
func (c *Container) Stats() (*Stats, error) {
var (
err error
stats = &Stats{}
@@ -186,7 +163,9 @@ func (c *linuxContainer) Stats() (*Stats, error) {
return stats, nil
}
func (c *linuxContainer) Set(config configs.Config) error {
// Set resources of container as configured. Can be used to change resources
// when the container is running.
func (c *Container) Set(config configs.Config) error {
c.m.Lock()
defer c.m.Unlock()
status, err := c.currentStatus()
@@ -221,7 +200,9 @@ func (c *linuxContainer) Set(config configs.Config) error {
return err
}
func (c *linuxContainer) Start(process *Process) error {
// Start starts a process inside the container. Returns error if process fails
// to start. You can track process lifecycle with passed Process structure.
func (c *Container) Start(process *Process) error {
c.m.Lock()
defer c.m.Unlock()
if c.config.Cgroups.Resources.SkipDevices {
@@ -241,7 +222,10 @@ func (c *linuxContainer) Start(process *Process) error {
return nil
}
func (c *linuxContainer) Run(process *Process) error {
// Run immediately starts the process inside the container. Returns an error if
// the process fails to start. It does not block waiting for the exec fifo
// after start returns but opens the fifo after start returns.
func (c *Container) Run(process *Process) error {
if err := c.Start(process); err != nil {
return err
}
@@ -251,13 +235,14 @@ func (c *linuxContainer) Run(process *Process) error {
return nil
}
func (c *linuxContainer) Exec() error {
// Exec signals the container to exec the users process at the end of the init.
func (c *Container) Exec() error {
c.m.Lock()
defer c.m.Unlock()
return c.exec()
}
func (c *linuxContainer) exec() error {
func (c *Container) exec() error {
path := filepath.Join(c.root, execFifoFilename)
pid := c.initProcess.pid()
blockingFifoOpenCh := awaitFifoOpen(path)
@@ -329,7 +314,7 @@ type openResult struct {
err error
}
func (c *linuxContainer) start(process *Process) (retErr error) {
func (c *Container) start(process *Process) (retErr error) {
parent, err := c.newParentProcess(process)
if err != nil {
return fmt.Errorf("unable to create new parent process: %w", err)
@@ -370,7 +355,7 @@ func (c *linuxContainer) start(process *Process) (retErr error) {
return nil
}
func (c *linuxContainer) Signal(s os.Signal, all bool) error {
func (c *Container) Signal(s os.Signal, all bool) error {
c.m.Lock()
defer c.m.Unlock()
status, err := c.currentStatus()
@@ -402,7 +387,7 @@ func (c *linuxContainer) Signal(s os.Signal, all bool) error {
return ErrNotRunning
}
func (c *linuxContainer) createExecFifo() error {
func (c *Container) createExecFifo() error {
rootuid, err := c.Config().HostRootUID()
if err != nil {
return err
@@ -425,7 +410,7 @@ func (c *linuxContainer) createExecFifo() error {
return os.Chown(fifoName, rootuid, rootgid)
}
func (c *linuxContainer) deleteExecFifo() {
func (c *Container) deleteExecFifo() {
fifoName := filepath.Join(c.root, execFifoFilename)
os.Remove(fifoName)
}
@@ -434,7 +419,7 @@ func (c *linuxContainer) deleteExecFifo() {
// container cannot access the statedir (and the FIFO itself remains
// un-opened). It then adds the FifoFd to the given exec.Cmd as an inherited
// fd, with _LIBCONTAINER_FIFOFD set to its fd number.
func (c *linuxContainer) includeExecFifo(cmd *exec.Cmd) error {
func (c *Container) includeExecFifo(cmd *exec.Cmd) error {
fifoName := filepath.Join(c.root, execFifoFilename)
fifo, err := os.OpenFile(fifoName, unix.O_PATH|unix.O_CLOEXEC, 0)
if err != nil {
@@ -448,7 +433,7 @@ func (c *linuxContainer) includeExecFifo(cmd *exec.Cmd) error {
return nil
}
func (c *linuxContainer) newParentProcess(p *Process) (parentProcess, error) {
func (c *Container) newParentProcess(p *Process) (parentProcess, error) {
parentInitPipe, childInitPipe, err := utils.NewSockPair("init")
if err != nil {
return nil, fmt.Errorf("unable to create init pipe: %w", err)
@@ -477,7 +462,7 @@ func (c *linuxContainer) newParentProcess(p *Process) (parentProcess, error) {
return c.newInitProcess(p, cmd, messageSockPair, logFilePair)
}
func (c *linuxContainer) commandTemplate(p *Process, childInitPipe *os.File, childLogPipe *os.File) *exec.Cmd {
func (c *Container) commandTemplate(p *Process, childInitPipe *os.File, childLogPipe *os.File) *exec.Cmd {
cmd := exec.Command("/proc/self/exe", "init")
cmd.Args[0] = os.Args[0]
cmd.Stdin = p.Stdin
@@ -519,7 +504,7 @@ func (c *linuxContainer) commandTemplate(p *Process, childInitPipe *os.File, chi
// shouldSendMountSources says whether the child process must setup bind mounts with
// the source pre-opened (O_PATH) in the host user namespace.
// See https://github.com/opencontainers/runc/issues/2484
func (c *linuxContainer) shouldSendMountSources() bool {
func (c *Container) shouldSendMountSources() bool {
// Passing the mount sources via SCM_RIGHTS is only necessary when
// both userns and mntns are active.
if !c.config.Namespaces.Contains(configs.NEWUSER) ||
@@ -543,7 +528,7 @@ func (c *linuxContainer) shouldSendMountSources() bool {
return false
}
func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, messageSockPair, logFilePair filePair) (*initProcess, error) {
func (c *Container) newInitProcess(p *Process, cmd *exec.Cmd, messageSockPair, logFilePair filePair) (*initProcess, error) {
cmd.Env = append(cmd.Env, "_LIBCONTAINER_INITTYPE="+string(initStandard))
nsMaps := make(map[configs.NamespaceType]string)
for _, ns := range c.config.Namespaces {
@@ -602,7 +587,7 @@ func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, messageSockPa
return init, nil
}
func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, messageSockPair, logFilePair filePair) (*setnsProcess, error) {
func (c *Container) newSetnsProcess(p *Process, cmd *exec.Cmd, messageSockPair, logFilePair filePair) (*setnsProcess, error) {
cmd.Env = append(cmd.Env, "_LIBCONTAINER_INITTYPE="+string(initSetns))
state, err := c.currentState()
if err != nil {
@@ -659,7 +644,7 @@ func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, messageSockP
return proc, nil
}
func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
func (c *Container) newInitConfig(process *Process) *initConfig {
cfg := &initConfig{
Config: c.config,
Args: process.Args,
@@ -699,13 +684,23 @@ func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
return cfg
}
func (c *linuxContainer) Destroy() error {
// Destroy destroys the container, if its in a valid state, after killing any
// remaining running processes.
//
// Any event registrations are removed before the container is destroyed.
// No error is returned if the container is already destroyed.
//
// Running containers must first be stopped using Signal.
// Paused containers must first be resumed using Resume.
func (c *Container) Destroy() error {
c.m.Lock()
defer c.m.Unlock()
return c.state.destroy()
}
func (c *linuxContainer) Pause() error {
// Pause pauses the container, if its state is RUNNING or CREATED, changing
// its state to PAUSED. If the state is already PAUSED, does nothing.
func (c *Container) Pause() error {
c.m.Lock()
defer c.m.Unlock()
status, err := c.currentStatus()
@@ -724,7 +719,11 @@ func (c *linuxContainer) Pause() error {
return ErrNotRunning
}
func (c *linuxContainer) Resume() error {
// Resume resumes the execution of any user processes in the
// container before setting the container state to RUNNING.
// This is only performed if the current state is PAUSED.
// If the Container state is RUNNING, does nothing.
func (c *Container) Resume() error {
c.m.Lock()
defer c.m.Unlock()
status, err := c.currentStatus()
@@ -742,7 +741,9 @@ func (c *linuxContainer) Resume() error {
})
}
func (c *linuxContainer) NotifyOOM() (<-chan struct{}, error) {
// NotifyOOM returns a read-only channel signaling when the container receives
// an OOM notification.
func (c *Container) NotifyOOM() (<-chan struct{}, error) {
// XXX(cyphar): This requires cgroups.
if c.config.RootlessCgroups {
logrus.Warn("getting OOM notifications may fail if you don't have the full access to cgroups")
@@ -754,7 +755,9 @@ func (c *linuxContainer) NotifyOOM() (<-chan struct{}, error) {
return notifyOnOOM(path)
}
func (c *linuxContainer) NotifyMemoryPressure(level PressureLevel) (<-chan struct{}, error) {
// NotifyMemoryPressure returns a read-only channel signaling when the
// container reaches a given pressure level.
func (c *Container) NotifyMemoryPressure(level PressureLevel) (<-chan struct{}, error) {
// XXX(cyphar): This requires cgroups.
if c.config.RootlessCgroups {
logrus.Warn("getting memory pressure notifications may fail if you don't have the full access to cgroups")
@@ -764,7 +767,7 @@ func (c *linuxContainer) NotifyMemoryPressure(level PressureLevel) (<-chan struc
var criuFeatures *criurpc.CriuFeatures
func (c *linuxContainer) checkCriuFeatures(criuOpts *CriuOpts, rpcOpts *criurpc.CriuOpts, criuFeat *criurpc.CriuFeatures) error {
func (c *Container) checkCriuFeatures(criuOpts *CriuOpts, rpcOpts *criurpc.CriuOpts, criuFeat *criurpc.CriuFeatures) error {
t := criurpc.CriuReqType_FEATURE_CHECK
// make sure the features we are looking for are really not from
@@ -824,8 +827,8 @@ func compareCriuVersion(criuVersion int, minVersion int) error {
return nil
}
// checkCriuVersion checks Criu version greater than or equal to minVersion
func (c *linuxContainer) checkCriuVersion(minVersion int) error {
// checkCriuVersion checks CRIU version greater than or equal to minVersion.
func (c *Container) checkCriuVersion(minVersion int) error {
// If the version of criu has already been determined there is no need
// to ask criu for the version again. Use the value from c.criuVersion.
if c.criuVersion != 0 {
@@ -844,7 +847,7 @@ func (c *linuxContainer) checkCriuVersion(minVersion int) error {
const descriptorsFilename = "descriptors.json"
func (c *linuxContainer) addCriuDumpMount(req *criurpc.CriuReq, m *configs.Mount) {
func (c *Container) addCriuDumpMount(req *criurpc.CriuReq, m *configs.Mount) {
mountDest := strings.TrimPrefix(m.Destination, c.config.Rootfs)
if dest, err := securejoin.SecureJoin(c.config.Rootfs, mountDest); err == nil {
mountDest = dest[len(c.config.Rootfs):]
@@ -856,7 +859,7 @@ func (c *linuxContainer) addCriuDumpMount(req *criurpc.CriuReq, m *configs.Mount
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
}
func (c *linuxContainer) addMaskPaths(req *criurpc.CriuReq) error {
func (c *Container) addMaskPaths(req *criurpc.CriuReq) error {
for _, path := range c.config.MaskPaths {
fi, err := os.Stat(fmt.Sprintf("/proc/%d/root/%s", c.initProcess.pid(), path))
if err != nil {
@@ -878,7 +881,7 @@ func (c *linuxContainer) addMaskPaths(req *criurpc.CriuReq) error {
return nil
}
func (c *linuxContainer) handleCriuConfigurationFile(rpcOpts *criurpc.CriuOpts) {
func (c *Container) handleCriuConfigurationFile(rpcOpts *criurpc.CriuOpts) {
// CRIU will evaluate a configuration starting with release 3.11.
// Settings in the configuration file will overwrite RPC settings.
// Look for annotations. The annotation 'org.criu.config'
@@ -903,7 +906,7 @@ func (c *linuxContainer) handleCriuConfigurationFile(rpcOpts *criurpc.CriuOpts)
}
}
func (c *linuxContainer) criuSupportsExtNS(t configs.NamespaceType) bool {
func (c *Container) criuSupportsExtNS(t configs.NamespaceType) bool {
var minVersion int
switch t {
case configs.NEWNET:
@@ -923,7 +926,7 @@ func criuNsToKey(t configs.NamespaceType) string {
return "extRoot" + strings.Title(configs.NsName(t)) + "NS" //nolint:staticcheck // SA1019: strings.Title is deprecated
}
func (c *linuxContainer) handleCheckpointingExternalNamespaces(rpcOpts *criurpc.CriuOpts, t configs.NamespaceType) error {
func (c *Container) handleCheckpointingExternalNamespaces(rpcOpts *criurpc.CriuOpts, t configs.NamespaceType) error {
if !c.criuSupportsExtNS(t) {
return nil
}
@@ -945,7 +948,7 @@ func (c *linuxContainer) handleCheckpointingExternalNamespaces(rpcOpts *criurpc.
return nil
}
func (c *linuxContainer) handleRestoringNamespaces(rpcOpts *criurpc.CriuOpts, extraFiles *[]*os.File) error {
func (c *Container) handleRestoringNamespaces(rpcOpts *criurpc.CriuOpts, extraFiles *[]*os.File) error {
for _, ns := range c.config.Namespaces {
switch ns.Type {
case configs.NEWNET, configs.NEWPID:
@@ -983,7 +986,7 @@ func (c *linuxContainer) handleRestoringNamespaces(rpcOpts *criurpc.CriuOpts, ex
return nil
}
func (c *linuxContainer) handleRestoringExternalNamespaces(rpcOpts *criurpc.CriuOpts, extraFiles *[]*os.File, t configs.NamespaceType) error {
func (c *Container) handleRestoringExternalNamespaces(rpcOpts *criurpc.CriuOpts, extraFiles *[]*os.File, t configs.NamespaceType) error {
if !c.criuSupportsExtNS(t) {
return nil
}
@@ -1014,7 +1017,7 @@ func (c *linuxContainer) handleRestoringExternalNamespaces(rpcOpts *criurpc.Criu
return nil
}
func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
c.m.Lock()
defer c.m.Unlock()
@@ -1222,7 +1225,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
return nil
}
func (c *linuxContainer) addCriuRestoreMount(req *criurpc.CriuReq, m *configs.Mount) {
func (c *Container) addCriuRestoreMount(req *criurpc.CriuReq, m *configs.Mount) {
mountDest := strings.TrimPrefix(m.Destination, c.config.Rootfs)
if dest, err := securejoin.SecureJoin(c.config.Rootfs, mountDest); err == nil {
mountDest = dest[len(c.config.Rootfs):]
@@ -1234,7 +1237,7 @@ func (c *linuxContainer) addCriuRestoreMount(req *criurpc.CriuReq, m *configs.Mo
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
}
func (c *linuxContainer) restoreNetwork(req *criurpc.CriuReq, criuOpts *CriuOpts) {
func (c *Container) restoreNetwork(req *criurpc.CriuReq, criuOpts *CriuOpts) {
for _, iface := range c.config.Networks {
switch iface.Type {
case "veth":
@@ -1257,7 +1260,7 @@ func (c *linuxContainer) restoreNetwork(req *criurpc.CriuReq, criuOpts *CriuOpts
// makeCriuRestoreMountpoints makes the actual mountpoints for the
// restore using CRIU. This function is inspired from the code in
// rootfs_linux.go
func (c *linuxContainer) makeCriuRestoreMountpoints(m *configs.Mount) error {
func (c *Container) makeCriuRestoreMountpoints(m *configs.Mount) error {
switch m.Device {
case "cgroup":
// No mount point(s) need to be created:
@@ -1309,7 +1312,7 @@ func isPathInPrefixList(path string, prefix []string) bool {
// runc modifies the rootfs to add mountpoints which do not exist.
// This function also creates missing mountpoints as long as they
// are not on top of a tmpfs, as CRIU will restore tmpfs content anyway.
func (c *linuxContainer) prepareCriuRestoreMounts(mounts []*configs.Mount) error {
func (c *Container) prepareCriuRestoreMounts(mounts []*configs.Mount) error {
// First get a list of a all tmpfs mounts
tmpfs := []string{}
for _, m := range mounts {
@@ -1366,7 +1369,9 @@ func (c *linuxContainer) prepareCriuRestoreMounts(mounts []*configs.Mount) error
return nil
}
func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
// Restore restores the checkpointed container to a running state using the
// criu(8) utility.
func (c *Container) Restore(process *Process, criuOpts *CriuOpts) error {
c.m.Lock()
defer c.m.Unlock()
@@ -1540,7 +1545,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
return err
}
func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
func (c *Container) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
// need to apply cgroups only on restore
if req.GetType() != criurpc.CriuReqType_RESTORE {
return nil
@@ -1577,7 +1582,7 @@ func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
return nil
}
func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts, extraFiles []*os.File) error {
func (c *Container) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts, extraFiles []*os.File) error {
fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_SEQPACKET|unix.SOCK_CLOEXEC, 0)
if err != nil {
return err
@@ -1795,7 +1800,7 @@ func unlockNetwork(config *configs.Config) error {
return nil
}
func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Process, cmd *exec.Cmd, opts *CriuOpts, fds []string, oob []byte) error {
func (c *Container) criuNotifications(resp *criurpc.CriuResp, process *Process, cmd *exec.Cmd, opts *CriuOpts, fds []string, oob []byte) error {
notify := resp.GetNotify()
if notify == nil {
return fmt.Errorf("invalid response: %s", resp.String())
@@ -1893,7 +1898,7 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
return nil
}
func (c *linuxContainer) updateState(process parentProcess) (*State, error) {
func (c *Container) updateState(process parentProcess) (*State, error) {
if process != nil {
c.initProcess = process
}
@@ -1908,7 +1913,7 @@ func (c *linuxContainer) updateState(process parentProcess) (*State, error) {
return state, nil
}
func (c *linuxContainer) saveState(s *State) (retErr error) {
func (c *Container) saveState(s *State) (retErr error) {
tmpFile, err := os.CreateTemp(c.root, "state-")
if err != nil {
return err
@@ -1934,7 +1939,7 @@ func (c *linuxContainer) saveState(s *State) (retErr error) {
return os.Rename(tmpFile.Name(), stateFilePath)
}
func (c *linuxContainer) currentStatus() (Status, error) {
func (c *Container) currentStatus() (Status, error) {
if err := c.refreshState(); err != nil {
return -1, err
}
@@ -1945,7 +1950,7 @@ func (c *linuxContainer) currentStatus() (Status, error) {
// container is what is true. Because consumers of libcontainer can use it
// out of process we need to verify the container's status based on runtime
// information and not rely on our in process info.
func (c *linuxContainer) refreshState() error {
func (c *Container) refreshState() error {
paused, err := c.isPaused()
if err != nil {
return err
@@ -1963,7 +1968,7 @@ func (c *linuxContainer) refreshState() error {
return c.state.transition(&stoppedState{c: c})
}
func (c *linuxContainer) runType() Status {
func (c *Container) runType() Status {
if c.initProcess == nil {
return Stopped
}
@@ -1983,7 +1988,7 @@ func (c *linuxContainer) runType() Status {
return Running
}
func (c *linuxContainer) isPaused() (bool, error) {
func (c *Container) isPaused() (bool, error) {
state, err := c.cgroupManager.GetFreezerState()
if err != nil {
return false, err
@@ -1991,7 +1996,7 @@ func (c *linuxContainer) isPaused() (bool, error) {
return state == configs.Frozen, nil
}
func (c *linuxContainer) currentState() (*State, error) {
func (c *Container) currentState() (*State, error) {
var (
startTime uint64
externalDescriptors []string
@@ -2038,7 +2043,7 @@ func (c *linuxContainer) currentState() (*State, error) {
return state, nil
}
func (c *linuxContainer) currentOCIState() (*specs.State, error) {
func (c *Container) currentOCIState() (*specs.State, error) {
bundle, annotations := utils.Annotations(c.config.Labels)
state := &specs.State{
Version: specs.Version,
@@ -2061,7 +2066,7 @@ func (c *linuxContainer) currentOCIState() (*specs.State, error) {
// orderNamespacePaths sorts namespace paths into a list of paths that we
// can setns in order.
func (c *linuxContainer) orderNamespacePaths(namespaces map[configs.NamespaceType]string) ([]string, error) {
func (c *Container) orderNamespacePaths(namespaces map[configs.NamespaceType]string) ([]string, error) {
paths := []string{}
for _, ns := range configs.NamespaceTypes() {
@@ -2114,7 +2119,7 @@ type netlinkError struct{ error }
// such as one that uses nsenter package to bootstrap the container's
// init process correctly, i.e. with correct namespaces, uid/gid
// mapping etc.
func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.NamespaceType]string, it initType) (_ io.Reader, Err error) {
func (c *Container) bootstrapData(cloneFlags uintptr, nsMaps map[configs.NamespaceType]string, it initType) (_ io.Reader, Err error) {
// create the netlink message
r := nl.NewNetlinkRequest(int(InitMsg), 0)
+3 -3
View File
@@ -115,7 +115,7 @@ func TestGetContainerPids(t *testing.T) {
if err != nil {
t.Fatalf("can't stat pid %d, got %v", pid, err)
}
container := &linuxContainer{
container := &Container{
id: "myid",
config: &configs.Config{},
cgroupManager: &mockCgroupManager{
@@ -148,7 +148,7 @@ func TestGetContainerState(t *testing.T) {
expectedMemoryPath = "/sys/fs/cgroup/memory/myid"
expectedNetworkPath = fmt.Sprintf("/proc/%d/ns/net", pid)
)
container := &linuxContainer{
container := &Container{
id: "myid",
config: &configs.Config{
Namespaces: []configs.Namespace{
@@ -232,7 +232,7 @@ func TestGetContainerStateAfterUpdate(t *testing.T) {
t.Fatal(err)
}
container := &linuxContainer{
container := &Container{
root: t.TempDir(),
id: "myid",
config: &configs.Config{
+4 -4
View File
@@ -37,7 +37,7 @@ var idRegex = regexp.MustCompile(`^[\w+-\.]+$`)
// The id must not be empty and consist of only the following characters:
// ASCII letters, digits, underscore, plus, minus, period. The id must be
// unique and non-existent for the given root path.
func Create(root, id string, config *configs.Config) (Container, error) {
func Create(root, id string, config *configs.Config) (*Container, error) {
if root == "" {
return nil, errors.New("root not set")
}
@@ -98,7 +98,7 @@ func Create(root, id string, config *configs.Config) (Container, error) {
if err := os.Mkdir(containerRoot, 0o711); err != nil {
return nil, err
}
c := &linuxContainer{
c := &Container{
id: id,
root: containerRoot,
config: config,
@@ -112,7 +112,7 @@ func Create(root, id string, config *configs.Config) (Container, error) {
// Load takes a path to the state directory (root) and an id of an existing
// container, and returns a Container object reconstructed from the saved
// state. This presents a read only view of the container.
func Load(root, id string) (Container, error) {
func Load(root, id string) (*Container, error) {
if root == "" {
return nil, errors.New("root not set")
}
@@ -137,7 +137,7 @@ func Load(root, id string) (Container, error) {
if err != nil {
return nil, err
}
c := &linuxContainer{
c := &Container{
initProcess: r,
initProcessStartTime: state.InitProcessStartTime,
id: id,
+2 -6
View File
@@ -75,12 +75,8 @@ func TestFactoryLoadContainer(t *testing.T) {
if !reflect.DeepEqual(config.Hooks, expectedHooks) {
t.Fatalf("expects hooks %q but received %q", expectedHooks, config.Hooks)
}
lcontainer, ok := container.(*linuxContainer)
if !ok {
t.Fatal("expected linux container on linux based systems")
}
if lcontainer.initProcess.pid() != expectedState.InitProcessPid {
t.Fatalf("expected init pid %d but received %d", expectedState.InitProcessPid, lcontainer.initProcess.pid())
if container.initProcess.pid() != expectedState.InitProcessPid {
t.Fatalf("expected init pid %d but received %d", expectedState.InitProcessPid, container.initProcess.pid())
}
}
+2 -2
View File
@@ -165,7 +165,7 @@ func copyBusybox(dest string) error {
return nil
}
func newContainer(t *testing.T, config *configs.Config) (libcontainer.Container, error) {
func newContainer(t *testing.T, config *configs.Config) (*libcontainer.Container, error) {
name := strings.ReplaceAll(t.Name(), "/", "_") + strconv.FormatInt(-int64(time.Now().Nanosecond()), 35)
root := t.TempDir()
@@ -212,6 +212,6 @@ func runContainer(t *testing.T, config *configs.Config, args ...string) (buffers
return
}
func destroyContainer(container libcontainer.Container) {
func destroyContainer(container *libcontainer.Container) {
_ = container.Destroy()
}
+1 -1
View File
@@ -300,7 +300,7 @@ type initProcess struct {
config *initConfig
manager cgroups.Manager
intelRdtManager *intelrdt.Manager
container *linuxContainer
container *Container
fds []string
process *Process
bootstrapData io.Reader
+8 -8
View File
@@ -35,7 +35,7 @@ type containerState interface {
status() Status
}
func destroy(c *linuxContainer) error {
func destroy(c *Container) error {
if !c.config.Namespaces.Contains(configs.NEWPID) ||
c.config.Namespaces.PathOf(configs.NEWPID) != "" {
if err := signalAllProcesses(c.cgroupManager, unix.SIGKILL); err != nil {
@@ -59,7 +59,7 @@ func destroy(c *linuxContainer) error {
return err
}
func runPoststopHooks(c *linuxContainer) error {
func runPoststopHooks(c *Container) error {
hooks := c.config.Hooks
if hooks == nil {
return nil
@@ -80,7 +80,7 @@ func runPoststopHooks(c *linuxContainer) error {
// stoppedState represents a container is a stopped/destroyed state.
type stoppedState struct {
c *linuxContainer
c *Container
}
func (b *stoppedState) status() Status {
@@ -104,7 +104,7 @@ func (b *stoppedState) destroy() error {
// runningState represents a container that is currently running.
type runningState struct {
c *linuxContainer
c *Container
}
func (r *runningState) status() Status {
@@ -136,7 +136,7 @@ func (r *runningState) destroy() error {
}
type createdState struct {
c *linuxContainer
c *Container
}
func (i *createdState) status() Status {
@@ -162,7 +162,7 @@ func (i *createdState) destroy() error {
// pausedState represents a container that is currently pause. It cannot be destroyed in a
// paused state and must transition back to running first.
type pausedState struct {
c *linuxContainer
c *Container
}
func (p *pausedState) status() Status {
@@ -195,7 +195,7 @@ func (p *pausedState) destroy() error {
// information that maybe need destroyed when the container is stopped and destroy is called.
type restoredState struct {
imageDir string
c *linuxContainer
c *Container
}
func (r *restoredState) status() Status {
@@ -222,7 +222,7 @@ func (r *restoredState) destroy() error {
// loadedState is used whenever a container is restored, loaded, or setting additional
// processes inside and it should not be destroyed when it is exiting.
type loadedState struct {
c *linuxContainer
c *Container
s Status
}
+5 -5
View File
@@ -53,7 +53,7 @@ func testTransitions(t *testing.T, initialState containerState, valid []containe
func TestStoppedStateTransition(t *testing.T) {
testTransitions(
t,
&stoppedState{c: &linuxContainer{}},
&stoppedState{c: &Container{}},
[]containerState{
&stoppedState{},
&runningState{},
@@ -65,7 +65,7 @@ func TestStoppedStateTransition(t *testing.T) {
func TestPausedStateTransition(t *testing.T) {
testTransitions(
t,
&pausedState{c: &linuxContainer{}},
&pausedState{c: &Container{}},
[]containerState{
&pausedState{},
&runningState{},
@@ -77,7 +77,7 @@ func TestPausedStateTransition(t *testing.T) {
func TestRestoredStateTransition(t *testing.T) {
testTransitions(
t,
&restoredState{c: &linuxContainer{}},
&restoredState{c: &Container{}},
[]containerState{
&stoppedState{},
&runningState{},
@@ -88,7 +88,7 @@ func TestRestoredStateTransition(t *testing.T) {
func TestRunningStateTransition(t *testing.T) {
testTransitions(
t,
&runningState{c: &linuxContainer{}},
&runningState{c: &Container{}},
[]containerState{
&stoppedState{},
&pausedState{},
@@ -100,7 +100,7 @@ func TestRunningStateTransition(t *testing.T) {
func TestCreatedStateTransition(t *testing.T) {
testTransitions(
t,
&createdState{c: &linuxContainer{}},
&createdState{c: &Container{}},
[]containerState{
&stoppedState{},
&pausedState{},
+1 -1
View File
@@ -91,7 +91,7 @@ func notifySocketStart(context *cli.Context, notifySocketHost, id string) (*noti
return notifySocket, nil
}
func (s *notifySocket) waitForContainer(container libcontainer.Container) error {
func (s *notifySocket) waitForContainer(container *libcontainer.Container) error {
state, err := container.State()
if err != nil {
return err
+4 -4
View File
@@ -25,7 +25,7 @@ var errEmptyID = errors.New("container id cannot be empty")
// getContainer returns the specified container instance by loading it from
// a state directory (root).
func getContainer(context *cli.Context) (libcontainer.Container, error) {
func getContainer(context *cli.Context) (*libcontainer.Container, error) {
id := context.Args().First()
if id == "" {
return nil, errEmptyID
@@ -82,7 +82,7 @@ func newProcess(p specs.Process) (*libcontainer.Process, error) {
return lp, nil
}
func destroy(container libcontainer.Container) {
func destroy(container *libcontainer.Container) {
if err := container.Destroy(); err != nil {
logrus.Error(err)
}
@@ -162,7 +162,7 @@ func createPidFile(path string, process *libcontainer.Process) error {
return os.Rename(tmpName, path)
}
func createContainer(context *cli.Context, id string, spec *specs.Spec) (libcontainer.Container, error) {
func createContainer(context *cli.Context, id string, spec *specs.Spec) (*libcontainer.Container, error) {
rootlessCg, err := shouldUseRootlessCgroupManager(context)
if err != nil {
return nil, err
@@ -193,7 +193,7 @@ type runner struct {
preserveFDs int
pidFile string
consoleSocket string
container libcontainer.Container
container *libcontainer.Container
action CtAct
notifySocket *notifySocket
criuOpts *libcontainer.CriuOpts