summaryrefslogtreecommitdiff
path: root/pkg/varlinkapi/containers.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/varlinkapi/containers.go')
-rw-r--r--pkg/varlinkapi/containers.go912
1 files changed, 0 insertions, 912 deletions
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
deleted file mode 100644
index fef3b6476..000000000
--- a/pkg/varlinkapi/containers.go
+++ /dev/null
@@ -1,912 +0,0 @@
-// +build varlink
-
-package varlinkapi
-
-import (
- "bufio"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "strings"
- "sync"
- "syscall"
- "time"
-
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/libpod/logs"
- "github.com/containers/podman/v2/pkg/cgroups"
- "github.com/containers/podman/v2/pkg/rootless"
- iopodman "github.com/containers/podman/v2/pkg/varlink"
- "github.com/containers/podman/v2/pkg/varlinkapi/virtwriter"
- "github.com/containers/storage/pkg/archive"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- "k8s.io/client-go/tools/remotecommand"
-)
-
-// ListContainers ...
-func (i *VarlinkAPI) ListContainers(call iopodman.VarlinkCall) error {
- var (
- listContainers []iopodman.Container
- )
-
- containers, err := i.Runtime.GetAllContainers()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- opts := PsOptions{
- Namespace: true,
- Size: true,
- }
- for _, ctr := range containers {
- batchInfo, err := BatchContainerOp(ctr, opts)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- listContainers = append(listContainers, makeListContainer(ctr.ID(), batchInfo))
- }
- return call.ReplyListContainers(listContainers)
-}
-
-func (i *VarlinkAPI) Ps(call iopodman.VarlinkCall, opts iopodman.PsOpts) error {
- var (
- containers []iopodman.PsContainer
- )
- maxWorkers := Parallelize("ps")
- psOpts := makePsOpts(opts)
- filters := []string{}
- if opts.Filters != nil {
- filters = *opts.Filters
- }
- psContainerOutputs, err := GetPsContainerOutput(i.Runtime, psOpts, filters, maxWorkers)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- for _, ctr := range psContainerOutputs {
- container := iopodman.PsContainer{
- Id: ctr.ID,
- Image: ctr.Image,
- Command: ctr.Command,
- Created: ctr.Created,
- Ports: ctr.Ports,
- Names: ctr.Names,
- IsInfra: ctr.IsInfra,
- Status: ctr.Status,
- State: ctr.State.String(),
- PidNum: int64(ctr.Pid),
- Pod: ctr.Pod,
- CreatedAt: ctr.CreatedAt.Format(time.RFC3339Nano),
- ExitedAt: ctr.ExitedAt.Format(time.RFC3339Nano),
- StartedAt: ctr.StartedAt.Format(time.RFC3339Nano),
- Labels: ctr.Labels,
- NsPid: ctr.PID,
- Cgroup: ctr.Cgroup,
- Ipc: ctr.Cgroup,
- Mnt: ctr.MNT,
- Net: ctr.NET,
- PidNs: ctr.PIDNS,
- User: ctr.User,
- Uts: ctr.UTS,
- Mounts: ctr.Mounts,
- }
- if ctr.Size != nil {
- container.RootFsSize = ctr.Size.RootFsSize
- container.RwSize = ctr.Size.RwSize
- }
- containers = append(containers, container)
- }
- return call.ReplyPs(containers)
-}
-
-// GetContainer ...
-func (i *VarlinkAPI) GetContainer(call iopodman.VarlinkCall, id string) error {
- ctr, err := i.Runtime.LookupContainer(id)
- if err != nil {
- return call.ReplyContainerNotFound(id, err.Error())
- }
- opts := PsOptions{
- Namespace: true,
- Size: true,
- }
- batchInfo, err := BatchContainerOp(ctr, opts)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyGetContainer(makeListContainer(ctr.ID(), batchInfo))
-}
-
-// getContainersByContext returns a slice of container ids based on all, latest, or a list
-func (i *VarlinkAPI) GetContainersByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error {
- var ids []string
-
- ctrs, err := getContainersByContext(all, latest, input, i.Runtime)
- if err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- return call.ReplyContainerNotFound("", err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
-
- for _, c := range ctrs {
- ids = append(ids, c.ID())
- }
- return call.ReplyGetContainersByContext(ids)
-}
-
-// GetContainersByStatus returns a slice of containers filtered by a libpod status
-func (i *VarlinkAPI) GetContainersByStatus(call iopodman.VarlinkCall, statuses []string) error {
- var (
- filterFuncs []libpod.ContainerFilter
- containers []iopodman.Container
- )
- for _, status := range statuses {
- lpstatus, err := define.StringToContainerStatus(status)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
- state, _ := c.State()
- return state == lpstatus
- })
- }
- filteredContainers, err := i.Runtime.GetContainers(filterFuncs...)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- opts := PsOptions{Size: true, Namespace: true}
- for _, ctr := range filteredContainers {
- batchInfo, err := BatchContainerOp(ctr, opts)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- containers = append(containers, makeListContainer(ctr.ID(), batchInfo))
- }
- return call.ReplyGetContainersByStatus(containers)
-}
-
-// InspectContainer ...
-func (i *VarlinkAPI) InspectContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- data, err := ctr.Inspect(true)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- b, err := json.Marshal(data)
- if err != nil {
- return call.ReplyErrorOccurred(fmt.Sprintf("unable to serialize"))
- }
- return call.ReplyInspectContainer(string(b))
-}
-
-// ListContainerProcesses ...
-func (i *VarlinkAPI) ListContainerProcesses(call iopodman.VarlinkCall, name string, opts []string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- containerState, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if containerState != define.ContainerStateRunning {
- return call.ReplyErrorOccurred(fmt.Sprintf("container %s is not running", name))
- }
- var psArgs []string
- psOpts := []string{"user", "pid", "ppid", "pcpu", "etime", "tty", "time", "comm"}
- if len(opts) > 1 {
- psOpts = opts
- }
- psArgs = append(psArgs, psOpts...)
- psOutput, err := ctr.GetContainerPidInformation(psArgs)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- return call.ReplyListContainerProcesses(psOutput)
-}
-
-// GetContainerLogs ...
-func (i *VarlinkAPI) GetContainerLogs(call iopodman.VarlinkCall, name string) error {
- var logs []string
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- logPath := ctr.LogPath()
-
- containerState, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if _, err := os.Stat(logPath); err != nil {
- if containerState == define.ContainerStateConfigured {
- return call.ReplyGetContainerLogs(logs)
- }
- }
- file, err := os.Open(logPath)
- if err != nil {
- return errors.Wrapf(err, "unable to read container log file")
- }
- defer file.Close()
- reader := bufio.NewReader(file)
- if call.WantsMore() {
- call.Continues = true
- }
- for {
- line, err := reader.ReadString('\n')
- // We've read the entire file
- if err == io.EOF {
- if !call.WantsMore() {
- // If this is a non-following log request, we return what we have
- break
- } else {
- // If we want to follow, return what we have, wipe the slice, and make
- // sure the container is still running before iterating.
- call.ReplyGetContainerLogs(logs)
- logs = []string{}
- time.Sleep(1 * time.Second)
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if state != define.ContainerStateRunning && state != define.ContainerStatePaused {
- return call.ReplyErrorOccurred(fmt.Sprintf("%s is no longer running", ctr.ID()))
- }
-
- }
- } else if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- } else {
- logs = append(logs, line)
- }
- }
-
- call.Continues = false
-
- return call.ReplyGetContainerLogs(logs)
-}
-
-// ListContainerChanges ...
-func (i *VarlinkAPI) ListContainerChanges(call iopodman.VarlinkCall, name string) error {
- changes, err := i.Runtime.GetDiff("", name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- result := iopodman.ContainerChanges{}
- for _, change := range changes {
- switch change.Kind {
- case archive.ChangeModify:
- result.Changed = append(result.Changed, change.Path)
- case archive.ChangeDelete:
- result.Deleted = append(result.Deleted, change.Path)
- case archive.ChangeAdd:
- result.Added = append(result.Added, change.Path)
- }
- }
- return call.ReplyListContainerChanges(result)
-}
-
-// ExportContainer ...
-func (i *VarlinkAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- outputFile, err := ioutil.TempFile("", "varlink_recv")
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- defer outputFile.Close()
- if outPath == "" {
- outPath = outputFile.Name()
- }
- if err := ctr.Export(outPath); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyExportContainer(outPath)
-
-}
-
-// GetContainerStats ...
-func (i *VarlinkAPI) GetContainerStats(call iopodman.VarlinkCall, name string) error {
- if rootless.IsRootless() {
- cgroupv2, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if !cgroupv2 {
- return call.ReplyErrRequiresCgroupsV2ForRootless("rootless containers cannot report container stats")
- }
- }
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- containerStats, err := ctr.GetContainerStats(&define.ContainerStats{})
- if err != nil {
- if errors.Cause(err) == define.ErrCtrStateInvalid {
- return call.ReplyNoContainerRunning()
- }
- return call.ReplyErrorOccurred(err.Error())
- }
- cs := iopodman.ContainerStats{
- Id: ctr.ID(),
- Name: ctr.Name(),
- Cpu: containerStats.CPU,
- Cpu_nano: int64(containerStats.CPUNano),
- System_nano: int64(containerStats.SystemNano),
- Mem_usage: int64(containerStats.MemUsage),
- Mem_limit: int64(containerStats.MemLimit),
- Mem_perc: containerStats.MemPerc,
- Net_input: int64(containerStats.NetInput),
- Net_output: int64(containerStats.NetOutput),
- Block_input: int64(containerStats.BlockInput),
- Block_output: int64(containerStats.BlockOutput),
- Pids: int64(containerStats.PIDs),
- }
- return call.ReplyGetContainerStats(cs)
-}
-
-// StartContainer ...
-func (i *VarlinkAPI) StartContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if state == define.ContainerStateRunning || state == define.ContainerStatePaused {
- return call.ReplyErrorOccurred("container is already running or paused")
- }
- recursive := false
- if ctr.PodID() != "" {
- recursive = true
- }
- if err := ctr.Start(getContext(), recursive); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyStartContainer(ctr.ID())
-}
-
-// InitContainer initializes the container given by Varlink.
-func (i *VarlinkAPI) 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(), false); err != nil {
- if errors.Cause(err) == define.ErrCtrStateInvalid {
- return call.ReplyInvalidState(ctr.ID(), err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyInitContainer(ctr.ID())
-}
-
-// StopContainer ...
-func (i *VarlinkAPI) StopContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.StopWithTimeout(uint(timeout)); err != nil {
- if errors.Cause(err) == define.ErrCtrStopped {
- return call.ReplyErrCtrStopped(ctr.ID())
- }
- if errors.Cause(err) == define.ErrCtrStateInvalid {
- return call.ReplyInvalidState(ctr.ID(), err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyStopContainer(ctr.ID())
-}
-
-// RestartContainer ...
-func (i *VarlinkAPI) RestartContainer(call iopodman.VarlinkCall, name string, timeout int64) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.RestartWithTimeout(getContext(), uint(timeout)); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyRestartContainer(ctr.ID())
-}
-
-// ContainerExists looks in local storage for the existence of a container
-func (i *VarlinkAPI) ContainerExists(call iopodman.VarlinkCall, name string) error {
- _, err := i.Runtime.LookupContainer(name)
- if errors.Cause(err) == define.ErrNoSuchCtr {
- return call.ReplyContainerExists(1)
- }
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyContainerExists(0)
-}
-
-// KillContainer kills a running container. If you want to use the default SIGTERM signal, just send a -1
-// for the signal arg.
-func (i *VarlinkAPI) KillContainer(call iopodman.VarlinkCall, name string, signal int64) error {
- killSignal := uint(syscall.SIGTERM)
- if signal != -1 {
- killSignal = uint(signal)
- }
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.Kill(killSignal); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyKillContainer(ctr.ID())
-}
-
-// PauseContainer ...
-func (i *VarlinkAPI) PauseContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.Pause(); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyPauseContainer(ctr.ID())
-}
-
-// UnpauseContainer ...
-func (i *VarlinkAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := ctr.Unpause(); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyUnpauseContainer(ctr.ID())
-}
-
-// WaitContainer ...
-func (i *VarlinkAPI) WaitContainer(call iopodman.VarlinkCall, name string, interval int64) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- exitCode, err := ctr.WaitWithInterval(time.Duration(interval))
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyWaitContainer(int64(exitCode))
-}
-
-// RemoveContainer ...
-func (i *VarlinkAPI) RemoveContainer(call iopodman.VarlinkCall, name string, force bool, removeVolumes bool) error {
- ctx := getContext()
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- if err := i.Runtime.RemoveContainer(ctx, ctr, force, removeVolumes); err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- return call.ReplyContainerExists(1)
- }
- if errors.Cause(err) == define.ErrCtrStateInvalid {
- return call.ReplyInvalidState(ctr.ID(), err.Error())
- }
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyRemoveContainer(ctr.ID())
-}
-
-// EvictContainer ...
-func (i *VarlinkAPI) EvictContainer(call iopodman.VarlinkCall, name string, removeVolumes bool) error {
- ctx := getContext()
- id, err := i.Runtime.EvictContainer(ctx, name, removeVolumes)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyEvictContainer(id)
-}
-
-// DeleteStoppedContainers ...
-func (i *VarlinkAPI) DeleteStoppedContainers(call iopodman.VarlinkCall) error {
- ctx := getContext()
- var deletedContainers []string
- containers, err := i.Runtime.GetAllContainers()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- for _, ctr := range containers {
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if state != define.ContainerStateRunning {
- if err := i.Runtime.RemoveContainer(ctx, ctr, false, false); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- deletedContainers = append(deletedContainers, ctr.ID())
- }
- }
- return call.ReplyDeleteStoppedContainers(deletedContainers)
-}
-
-// GetAttachSockets ...
-func (i *VarlinkAPI) GetAttachSockets(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
-
- status, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- // If the container hasn't been run, we need to run init
- // so the conmon sockets get created.
- if status == define.ContainerStateConfigured || status == define.ContainerStateStopped {
- if err := ctr.Init(getContext(), false); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- }
-
- sockPath, err := ctr.AttachSocketPath()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- s := iopodman.Sockets{
- Container_id: ctr.ID(),
- Io_socket: sockPath,
- Control_socket: ctr.ControlSocketPath(),
- }
- return call.ReplyGetAttachSockets(s)
-}
-
-// ContainerCheckpoint ...
-func (i *VarlinkAPI) ContainerCheckpoint(call iopodman.VarlinkCall, name string, keep, leaveRunning, tcpEstablished bool) error {
- ctx := getContext()
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
-
- options := libpod.ContainerCheckpointOptions{
- Keep: keep,
- TCPEstablished: tcpEstablished,
- KeepRunning: leaveRunning,
- }
- if err := ctr.Checkpoint(ctx, options); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyContainerCheckpoint(ctr.ID())
-}
-
-// ContainerRestore ...
-func (i *VarlinkAPI) ContainerRestore(call iopodman.VarlinkCall, name string, keep, tcpEstablished bool) error {
- ctx := getContext()
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
-
- options := libpod.ContainerCheckpointOptions{
- Keep: keep,
- TCPEstablished: tcpEstablished,
- }
- if err := ctr.Restore(ctx, options); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyContainerRestore(ctr.ID())
-}
-
-// ContainerConfig returns just the container.config struct
-func (i *VarlinkAPI) ContainerConfig(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- config := ctr.Config()
- b, err := json.Marshal(config)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize container config")
- }
- return call.ReplyContainerConfig(string(b))
-}
-
-// ContainerArtifacts returns an untouched container's artifact in string format
-func (i *VarlinkAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifactName string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- artifacts, err := ctr.GetArtifact(artifactName)
- if err != nil {
- return call.ReplyErrorOccurred("unable to get container artifacts")
- }
- b, err := json.Marshal(artifacts)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize container artifacts")
- }
- return call.ReplyContainerArtifacts(string(b))
-}
-
-// ContainerInspectData returns the inspect data of a container in string format
-func (i *VarlinkAPI) ContainerInspectData(call iopodman.VarlinkCall, name string, size bool) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- data, err := ctr.Inspect(size)
- if err != nil {
- return call.ReplyErrorOccurred("unable to inspect container")
- }
- b, err := json.Marshal(data)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize container inspect data")
- }
- return call.ReplyContainerInspectData(string(b))
-
-}
-
-// ContainerStateData returns a container's state data in string format
-func (i *VarlinkAPI) ContainerStateData(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyContainerNotFound(name, err.Error())
- }
- data, err := ctr.ContainerState()
- if err != nil {
- return call.ReplyErrorOccurred("unable to obtain container state")
- }
- b, err := json.Marshal(data)
- if err != nil {
- return call.ReplyErrorOccurred("unable to serialize container inspect data")
- }
- return call.ReplyContainerStateData(string(b))
-}
-
-// GetContainerStatsWithHistory is a varlink endpoint that returns container stats based on current and
-// previous statistics
-func (i *VarlinkAPI) GetContainerStatsWithHistory(call iopodman.VarlinkCall, prevStats iopodman.ContainerStats) error {
- con, err := i.Runtime.LookupContainer(prevStats.Id)
- if err != nil {
- return call.ReplyContainerNotFound(prevStats.Id, err.Error())
- }
- previousStats := ContainerStatsToLibpodContainerStats(prevStats)
- stats, err := con.GetContainerStats(&previousStats)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- cStats := iopodman.ContainerStats{
- Id: stats.ContainerID,
- Name: stats.Name,
- Cpu: stats.CPU,
- Cpu_nano: int64(stats.CPUNano),
- System_nano: int64(stats.SystemNano),
- Mem_usage: int64(stats.MemUsage),
- Mem_limit: int64(stats.MemLimit),
- Mem_perc: stats.MemPerc,
- Net_input: int64(stats.NetInput),
- Net_output: int64(stats.NetOutput),
- Block_input: int64(stats.BlockInput),
- Block_output: int64(stats.BlockOutput),
- Pids: int64(stats.PIDs),
- }
- return call.ReplyGetContainerStatsWithHistory(cStats)
-}
-
-// Spec ...
-func (i *VarlinkAPI) Spec(call iopodman.VarlinkCall, name string) error {
- ctr, err := i.Runtime.LookupContainer(name)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- spec := ctr.Spec()
- b, err := json.Marshal(spec)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- return call.ReplySpec(string(b))
-}
-
-// GetContainersLogs is the varlink endpoint to obtain one or more container logs
-func (i *VarlinkAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, follow, latest bool, since string, tail int64, timestamps bool) error {
- var wg sync.WaitGroup
- if call.WantsMore() {
- call.Continues = true
- }
- sinceTime, err := time.Parse(time.RFC3339Nano, since)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- options := logs.LogOptions{
- Follow: follow,
- Since: sinceTime,
- Tail: tail,
- Timestamps: timestamps,
- }
-
- options.WaitGroup = &wg
- if len(names) > 1 {
- options.Multi = true
- }
- tailLen := int(tail)
- if tailLen < 0 {
- tailLen = 0
- }
- logChannel := make(chan *logs.LogLine, tailLen*len(names)+1)
- containers, err := getContainersByContext(false, latest, names, i.Runtime)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if err := i.Runtime.Log(getContext(), containers, &options, logChannel); err != nil {
- return err
- }
- go func() {
- wg.Wait()
- close(logChannel)
- }()
- for line := range logChannel {
- call.ReplyGetContainersLogs(newPodmanLogLine(line))
- if !call.Continues {
- break
- }
-
- }
- return call.ReplyGetContainersLogs(iopodman.LogLine{})
-}
-
-func newPodmanLogLine(line *logs.LogLine) iopodman.LogLine {
- return iopodman.LogLine{
- Device: line.Device,
- ParseLogType: line.ParseLogType,
- Time: line.Time.Format(time.RFC3339Nano),
- Msg: line.Msg,
- Cid: line.CID,
- }
-}
-
-// Top displays information about a container's running processes
-func (i *VarlinkAPI) Top(call iopodman.VarlinkCall, nameOrID string, descriptors []string) error {
- ctr, err := i.Runtime.LookupContainer(nameOrID)
- if err != nil {
- return call.ReplyContainerNotFound(ctr.ID(), err.Error())
- }
- topInfo, err := ctr.Top(descriptors)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- return call.ReplyTop(topInfo)
-}
-
-// ExecContainer is the varlink endpoint to execute a command in a container
-func (i *VarlinkAPI) ExecContainer(call iopodman.VarlinkCall, opts iopodman.ExecOpts) error {
- if !call.WantsUpgrade() {
- return call.ReplyErrorOccurred("client must use upgraded connection to exec")
- }
-
- ctr, err := i.Runtime.LookupContainer(opts.Name)
- if err != nil {
- return call.ReplyContainerNotFound(opts.Name, err.Error())
- }
-
- state, err := ctr.State()
- if err != nil {
- return call.ReplyErrorOccurred(
- fmt.Sprintf("exec failed to obtain container %s state: %s", ctr.ID(), err.Error()))
- }
-
- if state != define.ContainerStateRunning {
- return call.ReplyErrorOccurred(
- fmt.Sprintf("exec requires a running container, %s is %s", ctr.ID(), state.String()))
- }
-
- // ACK the client upgrade request
- call.ReplyExecContainer()
-
- envs := make(map[string]string)
- if opts.Env != nil {
- // HACK: The Varlink API uses the old []string format for env,
- // storage as "k=v". Split on the = and turn into the new map
- // format.
- for _, env := range *opts.Env {
- splitEnv := strings.SplitN(env, "=", 2)
- if len(splitEnv) == 1 {
- logrus.Errorf("Got badly-formatted environment variable %q in exec", env)
- continue
- }
- envs[splitEnv[0]] = splitEnv[1]
- }
- }
-
- var user string
- if opts.User != nil {
- user = *opts.User
- }
-
- var workDir string
- if opts.Workdir != nil {
- workDir = *opts.Workdir
- }
-
- resizeChan := make(chan remotecommand.TerminalSize)
-
- reader, writer, _, pipeWriter, streams := setupStreams(call)
-
- type ExitCodeError struct {
- ExitCode uint32
- Error error
- }
- ecErrChan := make(chan ExitCodeError, 1)
-
- go func() {
- if err := virtwriter.Reader(reader, nil, nil, pipeWriter, resizeChan, nil); err != nil {
- ecErrChan <- ExitCodeError{
- define.ExecErrorCodeGeneric,
- err,
- }
- }
- }()
-
- execConfig := new(libpod.ExecConfig)
- execConfig.Command = opts.Cmd
- execConfig.Terminal = opts.Tty
- execConfig.Privileged = opts.Privileged
- execConfig.Environment = envs
- execConfig.User = user
- execConfig.WorkDir = workDir
- execConfig.DetachKeys = opts.DetachKeys
-
- go func() {
- ec, err := ctr.Exec(execConfig, streams, resizeChan)
- if err != nil {
- logrus.Errorf(err.Error())
- }
- ecErrChan <- ExitCodeError{
- uint32(ec),
- err,
- }
- }()
-
- ecErr := <-ecErrChan
-
- exitCode := define.TranslateExecErrorToExitCode(int(ecErr.ExitCode), ecErr.Error)
-
- if err = virtwriter.HangUp(writer, uint32(exitCode)); err != nil {
- logrus.Errorf("ExecContainer failed to HANG-UP on %s: %s", ctr.ID(), err.Error())
- }
-
- if err := call.Writer.Flush(); err != nil {
- logrus.Errorf("Exec Container err: %s", err.Error())
- }
-
- return ecErr.Error
-}
-
-// HealthCheckRun executes defined container's healthcheck command and returns the container's health status.
-func (i *VarlinkAPI) HealthCheckRun(call iopodman.VarlinkCall, nameOrID string) error {
- hcStatus, err := i.Runtime.HealthCheck(nameOrID)
- if err != nil && hcStatus != define.HealthCheckFailure {
- return call.ReplyErrorOccurred(err.Error())
- }
- status := define.HealthCheckUnhealthy
- if hcStatus == define.HealthCheckSuccess {
- status = define.HealthCheckHealthy
- }
- return call.ReplyHealthCheckRun(status)
-}