summaryrefslogtreecommitdiff
path: root/pkg/varlinkapi
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2018-04-27 14:00:32 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-05-03 17:31:33 +0000
commit8dfebd4607c1152bd26c4a586e6d56a196c56e54 (patch)
treee4fdfcc0b1813fccd2ee6134931afbf2725a8208 /pkg/varlinkapi
parentfae5033a01b78d3e8f23c1c9438bc5534dfe0fa3 (diff)
downloadpodman-8dfebd4607c1152bd26c4a586e6d56a196c56e54.tar.gz
podman-8dfebd4607c1152bd26c4a586e6d56a196c56e54.tar.bz2
podman-8dfebd4607c1152bd26c4a586e6d56a196c56e54.zip
varlink containers
first pass at adding in the container related endpoints/methods for the libpod backend. Couple of important notes: * endpoints that can use a console are not going to be done until we have "remote" console * several of the container methods should probably be able to stream as opposed to a one-off return Signed-off-by: baude <bbaude@redhat.com> Closes: #708 Approved by: baude
Diffstat (limited to 'pkg/varlinkapi')
-rw-r--r--pkg/varlinkapi/containers.go346
-rw-r--r--pkg/varlinkapi/util.go67
2 files changed, 383 insertions, 30 deletions
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index bd406dda2..ece33556b 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -1,12 +1,67 @@
package varlinkapi
import (
- ioprojectatomicpodman "github.com/projectatomic/libpod/cmd/podman/varlink"
+ "bufio"
+ "encoding/json"
+ "fmt"
+ "os"
+ "syscall"
+
+ "github.com/pkg/errors"
+ "github.com/projectatomic/libpod/cmd/podman/batchcontainer"
+ "github.com/projectatomic/libpod/cmd/podman/libpodruntime"
+ "github.com/projectatomic/libpod/cmd/podman/varlink"
+ "github.com/projectatomic/libpod/libpod"
)
// ListContainers ...
func (i *LibpodAPI) ListContainers(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("ListContainers")
+ var (
+ listContainers []ioprojectatomicpodman.ListContainerData
+ )
+
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ containers, err := runtime.GetAllContainers()
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ opts := batchcontainer.PsOptions{
+ Namespace: true,
+ Size: true,
+ }
+ for _, ctr := range containers {
+ batchInfo, err := batchcontainer.BatchContainerOp(ctr, opts)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+
+ listContainers = append(listContainers, makeListContainer(ctr.ID(), batchInfo))
+ }
+ return call.ReplyListContainers(listContainers)
+}
+
+// GetContainer ...
+func (i *LibpodAPI) GetContainer(call ioprojectatomicpodman.VarlinkCall, name string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ opts := batchcontainer.PsOptions{
+ Namespace: true,
+ Size: true,
+ }
+ batchInfo, err := batchcontainer.BatchContainerOp(ctr, opts)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyGetContainer(makeListContainer(ctr.ID(), batchInfo))
}
// CreateContainer ...
@@ -15,33 +70,158 @@ func (i *LibpodAPI) CreateContainer(call ioprojectatomicpodman.VarlinkCall) erro
}
// InspectContainer ...
-func (i *LibpodAPI) InspectContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("InspectContainer")
+func (i *LibpodAPI) InspectContainer(call ioprojectatomicpodman.VarlinkCall, name string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ inspectInfo, err := ctr.Inspect(true)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ b, err := json.Marshal(inspectInfo)
+ if err != nil {
+ return call.ReplyErrorOccurred(fmt.Sprintf("unable to serialize"))
+ }
+ return call.ReplyInspectContainer(string(b))
}
// ListContainerProcesses ...
-func (i *LibpodAPI) ListContainerProcesses(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("ListContainerProcesses")
+func (i *LibpodAPI) ListContainerProcesses(call ioprojectatomicpodman.VarlinkCall, name string, opts []string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ containerState, err := ctr.State()
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ if containerState != libpod.ContainerStateRunning {
+ return call.ReplyErrorOccurred(fmt.Sprintf("container %s is not running", name))
+ }
+ var psArgs []string
+ psOpts := []string{"-o", "uid,pid,ppid,c,stime,tname,time,cmd"}
+ 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 *LibpodAPI) GetContainerLogs(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("GetContainerLogs")
+func (i *LibpodAPI) GetContainerLogs(call ioprojectatomicpodman.VarlinkCall, name string) error {
+ var logs []string
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ logPath := ctr.LogPath()
+
+ containerState, err := ctr.State()
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ if _, err := os.Stat(logPath); err != nil {
+ if containerState == libpod.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)
+ for {
+ line, err := reader.ReadString('\n')
+ if err != nil {
+ break
+ }
+ logs = append(logs, line)
+ }
+ return call.ReplyGetContainerLogs(logs)
}
// ListContainerChanges ...
-func (i *LibpodAPI) ListContainerChanges(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("ListContianerChanges")
+func (i *LibpodAPI) ListContainerChanges(call ioprojectatomicpodman.VarlinkCall, name string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ changes, err := runtime.GetDiff("", name)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+
+ m := make(map[string]string)
+ for _, change := range changes {
+ m[change.Path] = change.Kind.String()
+ }
+ return call.ReplyListContainerChanges(m)
}
// ExportContainer ...
-func (i *LibpodAPI) ExportContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("ExportContainer")
+func (i *LibpodAPI) ExportContainer(call ioprojectatomicpodman.VarlinkCall, name, path string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ if err := ctr.Export(path); err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyExportContainer(path)
}
// GetContainerStats ...
-func (i *LibpodAPI) GetContainerStats(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("GetContainerStates")
+func (i *LibpodAPI) GetContainerStats(call ioprojectatomicpodman.VarlinkCall, name string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ containerStats, err := ctr.GetContainerStats(&libpod.ContainerStats{})
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ cs := ioprojectatomicpodman.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)
}
// ResizeContainerTty ...
@@ -55,18 +235,56 @@ func (i *LibpodAPI) StartContainer(call ioprojectatomicpodman.VarlinkCall) error
}
// StopContainer ...
-func (i *LibpodAPI) StopContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("StopContainer")
+func (i *LibpodAPI) StopContainer(call ioprojectatomicpodman.VarlinkCall, name string, timeout int64) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ if err := ctr.StopWithTimeout(uint(timeout)); err != nil && err != libpod.ErrCtrStopped {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyStopContainer(ctr.ID())
}
// RestartContainer ...
-func (i *LibpodAPI) RestartContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("RestartContainer")
+func (i *LibpodAPI) RestartContainer(call ioprojectatomicpodman.VarlinkCall, name string, timeout int64) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ if err := ctr.RestartWithTimeout(getContext(), uint(timeout)); err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyRestartContainer(ctr.ID())
}
-// KillContainer ...
-func (i *LibpodAPI) KillContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("KillContainer")
+// KillContainer kills a running container. If you want to use the default SIGTERM signal, just send a -1
+// for the signal arg.
+func (i *LibpodAPI) KillContainer(call ioprojectatomicpodman.VarlinkCall, name string, signal int64) error {
+ var killSignal uint = uint(syscall.SIGTERM)
+ if signal != -1 {
+ killSignal = uint(signal)
+ }
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ if err := ctr.Kill(killSignal); err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyKillContainer(ctr.ID())
}
// UpdateContainer ...
@@ -80,13 +298,35 @@ func (i *LibpodAPI) RenameContainer(call ioprojectatomicpodman.VarlinkCall) erro
}
// PauseContainer ...
-func (i *LibpodAPI) PauseContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("PauseContainer")
+func (i *LibpodAPI) PauseContainer(call ioprojectatomicpodman.VarlinkCall, name string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ if err := ctr.Pause(); err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyPauseContainer(ctr.ID())
}
// UnpauseContainer ...
-func (i *LibpodAPI) UnpauseContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("UnpauseContainer")
+func (i *LibpodAPI) UnpauseContainer(call ioprojectatomicpodman.VarlinkCall, name string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ if err := ctr.Unpause(); err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyUnpauseContainer(ctr.ID())
}
// AttachToContainer ...
@@ -96,16 +336,62 @@ func (i *LibpodAPI) AttachToContainer(call ioprojectatomicpodman.VarlinkCall) er
}
// WaitContainer ...
-func (i *LibpodAPI) WaitContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("WaitContainer")
+func (i *LibpodAPI) WaitContainer(call ioprojectatomicpodman.VarlinkCall, name string) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ exitCode, err := ctr.Wait()
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyWaitContainer(int64(exitCode))
+
}
// RemoveContainer ...
-func (i *LibpodAPI) RemoveContainer(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("RemoveContainer")
+func (i *LibpodAPI) RemoveContainer(call ioprojectatomicpodman.VarlinkCall, name string, force bool) error {
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ return call.ReplyContainerNotFound(name)
+ }
+ if err := runtime.RemoveContainer(ctr, force); err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ return call.ReplyRemoveContainer(ctr.ID())
+
}
// DeleteStoppedContainers ...
func (i *LibpodAPI) DeleteStoppedContainers(call ioprojectatomicpodman.VarlinkCall) error {
- return call.ReplyMethodNotImplemented("DeleteContainer")
+ var deletedContainers []string
+ runtime, err := libpodruntime.GetRuntime(i.Cli)
+ if err != nil {
+ return call.ReplyRuntimeError(err.Error())
+ }
+ containers, err := 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 != libpod.ContainerStateRunning {
+ if err := runtime.RemoveContainer(ctr, false); err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ deletedContainers = append(deletedContainers, ctr.ID())
+ }
+ }
+ return call.ReplyDeleteStoppedContainers(deletedContainers)
}
diff --git a/pkg/varlinkapi/util.go b/pkg/varlinkapi/util.go
index ff0fb6ecb..25ab59801 100644
--- a/pkg/varlinkapi/util.go
+++ b/pkg/varlinkapi/util.go
@@ -2,9 +2,76 @@ package varlinkapi
import (
"context"
+ "strconv"
+ "time"
+
+ "github.com/projectatomic/libpod/cmd/podman/batchcontainer"
+ "github.com/projectatomic/libpod/cmd/podman/varlink"
+ "github.com/projectatomic/libpod/libpod"
)
// getContext returns a non-nil, empty context
func getContext() context.Context {
return context.TODO()
}
+
+func makeListContainer(containerID string, batchInfo batchcontainer.BatchContainerStruct) ioprojectatomicpodman.ListContainerData {
+ var (
+ mounts []ioprojectatomicpodman.ContainerMount
+ ports []ioprojectatomicpodman.ContainerPortMappings
+ )
+ ns := batchcontainer.GetNamespaces(batchInfo.Pid)
+
+ for _, mount := range batchInfo.ConConfig.Spec.Mounts {
+ m := ioprojectatomicpodman.ContainerMount{
+ Destination: mount.Destination,
+ Type: mount.Type,
+ Source: mount.Source,
+ Options: mount.Options,
+ }
+ mounts = append(mounts, m)
+ }
+
+ for _, pm := range batchInfo.ConConfig.PortMappings {
+ p := ioprojectatomicpodman.ContainerPortMappings{
+ Host_port: strconv.Itoa(int(pm.HostPort)),
+ Host_ip: pm.HostIP,
+ Protocol: pm.Protocol,
+ Container_port: strconv.Itoa(int(pm.ContainerPort)),
+ }
+ ports = append(ports, p)
+
+ }
+
+ // If we find this needs to be done for other container endpoints, we should
+ // convert this to a separate function or a generic map from struct function.
+ namespace := ioprojectatomicpodman.ContainerNameSpace{
+ User: ns.User,
+ Uts: ns.UTS,
+ Pidns: ns.PIDNS,
+ Pid: ns.PID,
+ Cgroup: ns.Cgroup,
+ Net: ns.NET,
+ Mnt: ns.MNT,
+ Ipc: ns.IPC,
+ }
+
+ lc := ioprojectatomicpodman.ListContainerData{
+ Id: containerID,
+ Image: batchInfo.ConConfig.RootfsImageName,
+ Imageid: batchInfo.ConConfig.RootfsImageID,
+ Command: batchInfo.ConConfig.Spec.Process.Args,
+ Createdat: batchInfo.ConConfig.CreatedTime.String(),
+ Runningfor: time.Since(batchInfo.ConConfig.CreatedTime).String(),
+ Status: batchInfo.ConState.String(),
+ Ports: ports,
+ Rootfssize: batchInfo.RootFsSize,
+ Rwsize: batchInfo.RwSize,
+ Names: batchInfo.ConConfig.Name,
+ Labels: batchInfo.ConConfig.Labels,
+ Mounts: mounts,
+ Containerrunning: batchInfo.ConState == libpod.ContainerStateRunning,
+ Namespaces: namespace,
+ }
+ return lc
+}