diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/adapter/containers.go | 82 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 73 | ||||
-rw-r--r-- | pkg/adapter/runtime_remote.go | 17 | ||||
-rw-r--r-- | pkg/adapter/runtime_remote_supported.go | 1 | ||||
-rw-r--r-- | pkg/adapter/sigproxy_linux.go (renamed from pkg/adapter/sigproxy.go) | 0 | ||||
-rw-r--r-- | pkg/adapter/terminal.go | 81 | ||||
-rw-r--r-- | pkg/adapter/terminal_linux.go | 91 | ||||
-rw-r--r-- | pkg/spec/config_linux.go | 6 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 7 | ||||
-rw-r--r-- | pkg/systemdgen/systemdgen.go | 43 | ||||
-rw-r--r-- | pkg/util/utils.go | 72 | ||||
-rw-r--r-- | pkg/util/utils_supported.go | 60 | ||||
-rw-r--r-- | pkg/util/utils_windows.go | 12 | ||||
-rw-r--r-- | pkg/varlinkapi/containers.go | 15 | ||||
-rw-r--r-- | pkg/varlinkapi/generate.go | 22 |
15 files changed, 422 insertions, 160 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 9ec897a60..d575bc9b0 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -18,6 +18,7 @@ import ( "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/adapter/shortcuts" + "github.com/containers/libpod/pkg/systemdgen" "github.com/containers/storage" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -133,6 +134,43 @@ func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillVa return pool.Run() } +// InitContainers initializes container(s) based on CLI inputs. +// Returns list of successful id(s), map of failed id(s) to errors, or a general +// error not from the container. +func (r *LocalRuntime) InitContainers(ctx context.Context, cli *cliconfig.InitValues) ([]string, map[string]error, error) { + maxWorkers := shared.DefaultPoolSize("init") + if cli.GlobalIsSet("max-workers") { + maxWorkers = cli.GlobalFlags.MaxWorks + } + logrus.Debugf("Setting maximum init workers to %d", maxWorkers) + + ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + if err != nil { + return nil, nil, err + } + + pool := shared.NewPool("init", maxWorkers, len(ctrs)) + for _, c := range ctrs { + ctr := c + + pool.Add(shared.Job{ + ctr.ID(), + func() error { + err := ctr.Init(ctx) + if err != nil { + // If we're initializing all containers, ignore invalid state errors + if cli.All && errors.Cause(err) == libpod.ErrCtrStateInvalid { + return nil + } + return err + } + return nil + }, + }) + } + return pool.Run() +} + // RemoveContainers removes container(s) based on CLI inputs. func (r *LocalRuntime) RemoveContainers(ctx context.Context, cli *cliconfig.RmValues) ([]string, map[string]error, error) { var ( @@ -876,3 +914,47 @@ func cleanupContainer(ctx context.Context, ctr *libpod.Container, runtime *Local } return nil } + +// Port displays port information about existing containers +func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) { + var ( + portContainers []*Container + containers []*libpod.Container + err error + ) + + if !c.All { + containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime) + } else { + containers, err = r.Runtime.GetRunningContainers() + } + if err != nil { + return nil, err + } + + //Convert libpod containers to adapter Containers + for _, con := range containers { + if state, _ := con.State(); state != libpod.ContainerStateRunning { + continue + } + portContainers = append(portContainers, &Container{con}) + } + return portContainers, nil +} + +// GenerateSystemd creates a unit file for a container +func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) { + ctr, err := r.Runtime.LookupContainer(c.InputArgs[0]) + if err != nil { + return "", err + } + timeout := int(ctr.StopTimeout()) + if c.StopTimeout >= 0 { + timeout = int(c.StopTimeout) + } + name := ctr.ID() + if c.Name { + name = ctr.Name() + } + return systemdgen.CreateSystemdUnitAsString(name, ctr.ID(), c.RestartPolicy, ctr.Config().StaticDir, timeout) +} diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index a3a48a564..201249fc3 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -18,6 +18,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/inspect" "github.com/containers/libpod/pkg/varlinkapi/virtwriter" + "github.com/cri-o/ocicni/pkg/ocicni" "github.com/docker/docker/pkg/term" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -63,6 +64,19 @@ func (c *Container) Unpause() error { return err } +func (c *Container) PortMappings() ([]ocicni.PortMapping, error) { + // First check if the container belongs to a network namespace (like a pod) + // Taken from libpod portmappings() + if len(c.config.NetNsCtr) > 0 { + netNsCtr, err := c.Runtime.LookupContainer(c.config.NetNsCtr) + if err != nil { + return nil, errors.Wrapf(err, "unable to lookup network namespace for container %s", c.ID()) + } + return netNsCtr.PortMappings() + } + return c.config.PortMappings, nil +} + // Config returns a container config func (r *LocalRuntime) Config(name string) *libpod.ContainerConfig { // TODO the Spec being returned is not populated. Matt and I could not figure out why. Will defer @@ -234,6 +248,40 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa return ok, failures, nil } +// InitContainers initializes container(s) based on Varlink. +// It returns a list of successful ID(s), a map of failed container ID to error, +// or an error if a more general error occurred. +func (r *LocalRuntime) InitContainers(ctx context.Context, cli *cliconfig.InitValues) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ) + + ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs) + if err != nil { + return nil, nil, err + } + + for _, id := range ids { + initialized, err := iopodman.InitContainer().Call(r.Conn, id) + if err != nil { + if cli.All { + switch err.(type) { + case *iopodman.InvalidState: + ok = append(ok, initialized) + default: + failures[id] = err + } + } else { + failures[id] = err + } + } else { + ok = append(ok, initialized) + } + } + return ok, failures, nil +} + // KillContainers sends signal to container(s) based on varlink. // Returns list of successful id(s), map of failed id(s) + error, or error not from container func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) { @@ -888,3 +936,28 @@ func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, force bool) ([ func (r *LocalRuntime) CleanupContainers(ctx context.Context, cli *cliconfig.CleanupValues) ([]string, map[string]error, error) { return nil, nil, errors.New("container cleanup not supported for remote clients") } + +// Port displays port information about existing containers +func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) { + var ( + containers []*Container + err error + ) + // This one is a bit odd because when all is used, we only use running containers. + if !c.All { + containers, err = r.GetContainersByContext(false, c.Latest, c.InputArgs) + } else { + // we need to only use running containers if all + filters := []string{libpod.ContainerStateRunning.String()} + containers, err = r.LookupContainersWithStatus(filters) + } + if err != nil { + return nil, err + } + return containers, nil +} + +// GenerateSystemd creates a systemd until for a container +func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) { + return iopodman.GenerateSystemd().Call(r.Conn, c.InputArgs[0], c.RestartPolicy, int64(c.StopTimeout), c.Name) +} diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index 6102daccf..4986d16f7 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -889,3 +889,20 @@ func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, * err = json.Unmarshal([]byte(reply.Service), &service) return &pod, &service, err } + +// GetContainersByContext looks up containers based on the cli input of all, latest, or a list +func (r *LocalRuntime) GetContainersByContext(all bool, latest bool, namesOrIDs []string) ([]*Container, error) { + var containers []*Container + cids, err := iopodman.GetContainersByContext().Call(r.Conn, all, latest, namesOrIDs) + if err != nil { + return nil, err + } + for _, cid := range cids { + ctr, err := r.LookupContainer(cid) + if err != nil { + return nil, err + } + containers = append(containers, ctr) + } + return containers, nil +} diff --git a/pkg/adapter/runtime_remote_supported.go b/pkg/adapter/runtime_remote_supported.go new file mode 100644 index 000000000..b8e8da308 --- /dev/null +++ b/pkg/adapter/runtime_remote_supported.go @@ -0,0 +1 @@ +package adapter diff --git a/pkg/adapter/sigproxy.go b/pkg/adapter/sigproxy_linux.go index af968cb89..af968cb89 100644 --- a/pkg/adapter/sigproxy.go +++ b/pkg/adapter/sigproxy_linux.go diff --git a/pkg/adapter/terminal.go b/pkg/adapter/terminal.go index 0b608decf..373c78322 100644 --- a/pkg/adapter/terminal.go +++ b/pkg/adapter/terminal.go @@ -2,16 +2,12 @@ package adapter import ( "context" - "fmt" "os" gosignal "os/signal" - "github.com/containers/libpod/libpod" "github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/term" - "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/crypto/ssh/terminal" "k8s.io/client-go/tools/remotecommand" ) @@ -19,83 +15,6 @@ import ( type RawTtyFormatter struct { } -// StartAttachCtr starts and (if required) attaches to a container -func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error { - resize := make(chan remotecommand.TerminalSize) - - haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) - - // Check if we are attached to a terminal. If we are, generate resize - // events, and set the terminal to raw mode - if haveTerminal && ctr.Spec().Process.Terminal { - logrus.Debugf("Handling terminal attach") - - subCtx, cancel := context.WithCancel(ctx) - defer cancel() - - resizeTty(subCtx, resize) - - oldTermState, err := term.SaveState(os.Stdin.Fd()) - if err != nil { - return errors.Wrapf(err, "unable to save terminal state") - } - - logrus.SetFormatter(&RawTtyFormatter{}) - term.SetRawTerminal(os.Stdin.Fd()) - - defer restoreTerminal(oldTermState) - } - - streams := new(libpod.AttachStreams) - streams.OutputStream = stdout - streams.ErrorStream = stderr - streams.InputStream = stdin - streams.AttachOutput = true - streams.AttachError = true - streams.AttachInput = true - - if stdout == nil { - logrus.Debugf("Not attaching to stdout") - streams.AttachOutput = false - } - if stderr == nil { - logrus.Debugf("Not attaching to stderr") - streams.AttachError = false - } - if stdin == nil { - logrus.Debugf("Not attaching to stdin") - streams.AttachInput = false - } - - if !startContainer { - if sigProxy { - ProxySignals(ctr) - } - - return ctr.Attach(streams, detachKeys, resize) - } - - attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, recursive) - if err != nil { - return err - } - - if sigProxy { - ProxySignals(ctr) - } - - if stdout == nil && stderr == nil { - fmt.Printf("%s\n", ctr.ID()) - } - - err = <-attachChan - if err != nil { - return errors.Wrapf(err, "error attaching to container %s", ctr.ID()) - } - - return nil -} - // getResize returns a TerminalSize command matching stdin's current // size on success, and nil on errors. func getResize() *remotecommand.TerminalSize { diff --git a/pkg/adapter/terminal_linux.go b/pkg/adapter/terminal_linux.go new file mode 100644 index 000000000..3c4c3bd38 --- /dev/null +++ b/pkg/adapter/terminal_linux.go @@ -0,0 +1,91 @@ +package adapter + +import ( + "context" + "fmt" + "os" + + "github.com/containers/libpod/libpod" + "github.com/docker/docker/pkg/term" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "golang.org/x/crypto/ssh/terminal" + "k8s.io/client-go/tools/remotecommand" +) + +// StartAttachCtr starts and (if required) attaches to a container +func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error { + resize := make(chan remotecommand.TerminalSize) + + haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) + + // Check if we are attached to a terminal. If we are, generate resize + // events, and set the terminal to raw mode + if haveTerminal && ctr.Spec().Process.Terminal { + logrus.Debugf("Handling terminal attach") + + subCtx, cancel := context.WithCancel(ctx) + defer cancel() + + resizeTty(subCtx, resize) + + oldTermState, err := term.SaveState(os.Stdin.Fd()) + if err != nil { + return errors.Wrapf(err, "unable to save terminal state") + } + + logrus.SetFormatter(&RawTtyFormatter{}) + term.SetRawTerminal(os.Stdin.Fd()) + + defer restoreTerminal(oldTermState) + } + + streams := new(libpod.AttachStreams) + streams.OutputStream = stdout + streams.ErrorStream = stderr + streams.InputStream = stdin + streams.AttachOutput = true + streams.AttachError = true + streams.AttachInput = true + + if stdout == nil { + logrus.Debugf("Not attaching to stdout") + streams.AttachOutput = false + } + if stderr == nil { + logrus.Debugf("Not attaching to stderr") + streams.AttachError = false + } + if stdin == nil { + logrus.Debugf("Not attaching to stdin") + streams.AttachInput = false + } + + if !startContainer { + if sigProxy { + ProxySignals(ctr) + } + + return ctr.Attach(streams, detachKeys, resize) + } + + attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, recursive) + if err != nil { + return err + } + + if sigProxy { + ProxySignals(ctr) + } + + if stdout == nil && stderr == nil { + fmt.Printf("%s\n", ctr.ID()) + } + + err = <-attachChan + if err != nil { + return errors.Wrapf(err, "error attaching to container %s", ctr.ID()) + } + + return nil +} diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index a1873086e..eb2acf984 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -244,3 +244,9 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott } return ltds, nil } + +func getStatFromPath(path string) (unix.Stat_t, error) { + s := unix.Stat_t{} + err := unix.Stat(path, &s) + return s, err +} diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 4d2d8304c..90e7accf3 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -17,7 +17,6 @@ import ( "github.com/opencontainers/runtime-tools/generate" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" ) // Type constants @@ -411,9 +410,3 @@ func NatToOCIPortBindings(ports nat.PortMap) ([]ocicni.PortMapping, error) { func (c *CreateConfig) AddPrivilegedDevices(g *generate.Generator) error { return c.addPrivilegedDevices(g) } - -func getStatFromPath(path string) (unix.Stat_t, error) { - s := unix.Stat_t{} - err := unix.Stat(path, &s) - return s, err -} diff --git a/pkg/systemdgen/systemdgen.go b/pkg/systemdgen/systemdgen.go new file mode 100644 index 000000000..3d1c31b5d --- /dev/null +++ b/pkg/systemdgen/systemdgen.go @@ -0,0 +1,43 @@ +package systemdgen + +import ( + "fmt" + "path/filepath" + + "github.com/pkg/errors" +) + +var template = `[Unit] +Description=%s Podman Container +[Service] +Restart=%s +ExecStart=/usr/bin/podman start %s +ExecStop=/usr/bin/podman stop -t %d %s +KillMode=none +Type=forking +PIDFile=%s +[Install] +WantedBy=multi-user.target` + +var restartPolicies = []string{"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", "always"} + +// ValidateRestartPolicy checks that the user-provided policy is valid +func ValidateRestartPolicy(restart string) error { + for _, i := range restartPolicies { + if i == restart { + return nil + } + } + return errors.Errorf("%s is not a valid restart policy", restart) +} + +// CreateSystemdUnitAsString takes variables to create a systemd unit file used to control +// a libpod container +func CreateSystemdUnitAsString(name, cid, restart, pidPath string, stopTimeout int) (string, error) { + if err := ValidateRestartPolicy(restart); err != nil { + return "", err + } + pidFile := filepath.Join(pidPath, fmt.Sprintf("%s.pid", cid)) + unit := fmt.Sprintf(template, name, restart, name, stopTimeout, name, pidFile) + return unit, nil +} diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 136f8fadd..14b0c2b55 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -6,12 +6,10 @@ import ( "path/filepath" "strings" "sync" - "syscall" "time" "github.com/BurntSushi/toml" "github.com/containers/image/types" - "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" "github.com/opencontainers/image-spec/specs-go/v1" @@ -187,76 +185,6 @@ var ( rootlessRuntimeDir string ) -// GetRootlessRuntimeDir returns the runtime directory when running as non root -func GetRootlessRuntimeDir() (string, error) { - var rootlessRuntimeDirError error - - rootlessRuntimeDirOnce.Do(func() { - runtimeDir := os.Getenv("XDG_RUNTIME_DIR") - uid := fmt.Sprintf("%d", rootless.GetRootlessUID()) - if runtimeDir == "" { - tmpDir := filepath.Join("/run", "user", uid) - os.MkdirAll(tmpDir, 0700) - st, err := os.Stat(tmpDir) - if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { - runtimeDir = tmpDir - } - } - if runtimeDir == "" { - tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid)) - os.MkdirAll(tmpDir, 0700) - st, err := os.Stat(tmpDir) - if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { - runtimeDir = tmpDir - } - } - if runtimeDir == "" { - home := os.Getenv("HOME") - if home == "" { - rootlessRuntimeDirError = fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty") - return - } - resolvedHome, err := filepath.EvalSymlinks(home) - if err != nil { - rootlessRuntimeDirError = errors.Wrapf(err, "cannot resolve %s", home) - return - } - runtimeDir = filepath.Join(resolvedHome, "rundir") - } - rootlessRuntimeDir = runtimeDir - }) - - if rootlessRuntimeDirError != nil { - return "", rootlessRuntimeDirError - } - return rootlessRuntimeDir, nil -} - -// GetRootlessDirInfo returns the parent path of where the storage for containers and -// volumes will be in rootless mode -func GetRootlessDirInfo() (string, string, error) { - rootlessRuntime, err := GetRootlessRuntimeDir() - if err != nil { - return "", "", err - } - - dataDir := os.Getenv("XDG_DATA_HOME") - if dataDir == "" { - home := os.Getenv("HOME") - if home == "" { - return "", "", fmt.Errorf("neither XDG_DATA_HOME nor HOME was set non-empty") - } - // runc doesn't like symlinks in the rootfs path, and at least - // on CoreOS /home is a symlink to /var/home, so resolve any symlink. - resolvedHome, err := filepath.EvalSymlinks(home) - if err != nil { - return "", "", errors.Wrapf(err, "cannot resolve %s", home) - } - dataDir = filepath.Join(resolvedHome, ".local", "share") - } - return dataDir, rootlessRuntime, nil -} - type tomlOptionsConfig struct { MountProgram string `toml:"mount_program"` } diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go new file mode 100644 index 000000000..af5e67fc1 --- /dev/null +++ b/pkg/util/utils_supported.go @@ -0,0 +1,60 @@ +// +build linux darwin + +package util + +// TODO once rootless function is consolidated under libpod, we +// should work to take darwin from this + +import ( + "fmt" + "github.com/containers/libpod/pkg/rootless" + "github.com/pkg/errors" + "os" + "path/filepath" + "syscall" +) + +// GetRootlessRuntimeDir returns the runtime directory when running as non root +func GetRootlessRuntimeDir() (string, error) { + var rootlessRuntimeDirError error + + rootlessRuntimeDirOnce.Do(func() { + runtimeDir := os.Getenv("XDG_RUNTIME_DIR") + uid := fmt.Sprintf("%d", rootless.GetRootlessUID()) + if runtimeDir == "" { + tmpDir := filepath.Join("/run", "user", uid) + os.MkdirAll(tmpDir, 0700) + st, err := os.Stat(tmpDir) + if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { + runtimeDir = tmpDir + } + } + if runtimeDir == "" { + tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid)) + os.MkdirAll(tmpDir, 0700) + st, err := os.Stat(tmpDir) + if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { + runtimeDir = tmpDir + } + } + if runtimeDir == "" { + home := os.Getenv("HOME") + if home == "" { + rootlessRuntimeDirError = fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty") + return + } + resolvedHome, err := filepath.EvalSymlinks(home) + if err != nil { + rootlessRuntimeDirError = errors.Wrapf(err, "cannot resolve %s", home) + return + } + runtimeDir = filepath.Join(resolvedHome, "rundir") + } + rootlessRuntimeDir = runtimeDir + }) + + if rootlessRuntimeDirError != nil { + return "", rootlessRuntimeDirError + } + return rootlessRuntimeDir, nil +} diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go new file mode 100644 index 000000000..1e9ccea90 --- /dev/null +++ b/pkg/util/utils_windows.go @@ -0,0 +1,12 @@ +// +build windows + +package util + +import ( + "github.com/pkg/errors" +) + +// GetRootlessRuntimeDir returns the runtime directory when running as non root +func GetRootlessRuntimeDir() (string, error) { + return "", errors.New("this function is not implemented for windows") +} diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go index 872c7bc26..c8be41636 100644 --- a/pkg/varlinkapi/containers.go +++ b/pkg/varlinkapi/containers.go @@ -365,6 +365,21 @@ func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error return call.ReplyStartContainer(ctr.ID()) } +// InitContainer initializes the container given by Varlink. +func (i *LibpodAPI) InitContainer(call iopodman.VarlinkCall, name string) error { + ctr, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyContainerNotFound(name, err.Error()) + } + if err := ctr.Init(getContext()); err != nil { + if errors.Cause(err) == libpod.ErrCtrStateInvalid { + return call.ReplyInvalidState(ctr.ID(), err.Error()) + } + return call.ReplyErrorOccurred(err.Error()) + } + return call.ReplyInitContainer(ctr.ID()) +} + // StopContainer ... func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeout int64) error { ctr, err := i.Runtime.LookupContainer(name) diff --git a/pkg/varlinkapi/generate.go b/pkg/varlinkapi/generate.go index bc600c397..9dc20d582 100644 --- a/pkg/varlinkapi/generate.go +++ b/pkg/varlinkapi/generate.go @@ -6,6 +6,7 @@ import ( "encoding/json" "github.com/containers/libpod/cmd/podman/shared" iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/pkg/systemdgen" ) // GenerateKube ... @@ -28,3 +29,24 @@ func (i *LibpodAPI) GenerateKube(call iopodman.VarlinkCall, name string, service Service: string(servB), }) } + +// GenerateSystemd ... +func (i *LibpodAPI) GenerateSystemd(call iopodman.VarlinkCall, nameOrID, restart string, stopTimeout int64, useName bool) error { + ctr, err := i.Runtime.LookupContainer(nameOrID) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + timeout := int(ctr.StopTimeout()) + if stopTimeout >= 0 { + timeout = int(stopTimeout) + } + name := ctr.ID() + if useName { + name = ctr.Name() + } + unit, err := systemdgen.CreateSystemdUnitAsString(name, ctr.ID(), restart, ctr.Config().StaticDir, timeout) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + return call.ReplyGenerateSystemd(unit) +} |