mirror of
https://github.com/containers/podman.git
synced 2025-06-12 11:02:00 +08:00

Close #3578 Add `size` field to PsOpts in podman remote to receive size as an option. Signed-off-by: Qi Wang <qiwan@redhat.com>
239 lines
6.4 KiB
Go
239 lines
6.4 KiB
Go
// +build varlink
|
|
|
|
package varlinkapi
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/containers/buildah"
|
|
"github.com/containers/libpod/cmd/podman/shared"
|
|
"github.com/containers/libpod/cmd/podman/varlink"
|
|
"github.com/containers/libpod/libpod"
|
|
"github.com/containers/libpod/libpod/define"
|
|
"github.com/containers/libpod/pkg/channelwriter"
|
|
"github.com/containers/storage/pkg/archive"
|
|
)
|
|
|
|
// getContext returns a non-nil, empty context
|
|
func getContext() context.Context {
|
|
return context.TODO()
|
|
}
|
|
|
|
func makeListContainer(containerID string, batchInfo shared.BatchContainerStruct) iopodman.Container {
|
|
var (
|
|
mounts []iopodman.ContainerMount
|
|
ports []iopodman.ContainerPortMappings
|
|
)
|
|
ns := shared.GetNamespaces(batchInfo.Pid)
|
|
|
|
for _, mount := range batchInfo.ConConfig.Spec.Mounts {
|
|
m := iopodman.ContainerMount{
|
|
Destination: mount.Destination,
|
|
Type: mount.Type,
|
|
Source: mount.Source,
|
|
Options: mount.Options,
|
|
}
|
|
mounts = append(mounts, m)
|
|
}
|
|
|
|
for _, pm := range batchInfo.ConConfig.PortMappings {
|
|
p := iopodman.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 := iopodman.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 := iopodman.Container{
|
|
Id: containerID,
|
|
Image: batchInfo.ConConfig.RootfsImageName,
|
|
Imageid: batchInfo.ConConfig.RootfsImageID,
|
|
Command: batchInfo.ConConfig.Spec.Process.Args,
|
|
Createdat: batchInfo.ConConfig.CreatedTime.Format(time.RFC3339),
|
|
Runningfor: time.Since(batchInfo.ConConfig.CreatedTime).String(),
|
|
Status: batchInfo.ConState.String(),
|
|
Ports: ports,
|
|
Names: batchInfo.ConConfig.Name,
|
|
Labels: batchInfo.ConConfig.Labels,
|
|
Mounts: mounts,
|
|
Containerrunning: batchInfo.ConState == define.ContainerStateRunning,
|
|
Namespaces: namespace,
|
|
}
|
|
if batchInfo.Size != nil {
|
|
lc.Rootfssize = batchInfo.Size.RootFsSize
|
|
lc.Rwsize = batchInfo.Size.RwSize
|
|
}
|
|
return lc
|
|
}
|
|
|
|
func makeListPodContainers(containerID string, batchInfo shared.BatchContainerStruct) iopodman.ListPodContainerInfo {
|
|
lc := iopodman.ListPodContainerInfo{
|
|
Id: containerID,
|
|
Status: batchInfo.ConState.String(),
|
|
Name: batchInfo.ConConfig.Name,
|
|
}
|
|
return lc
|
|
}
|
|
|
|
func makeListPod(pod *libpod.Pod, batchInfo shared.PsOptions) (iopodman.ListPodData, error) {
|
|
var listPodsContainers []iopodman.ListPodContainerInfo
|
|
var errPodData = iopodman.ListPodData{}
|
|
status, err := shared.GetPodStatus(pod)
|
|
if err != nil {
|
|
return errPodData, err
|
|
}
|
|
containers, err := pod.AllContainers()
|
|
if err != nil {
|
|
return errPodData, err
|
|
}
|
|
for _, ctr := range containers {
|
|
batchInfo, err := shared.BatchContainerOp(ctr, batchInfo)
|
|
if err != nil {
|
|
return errPodData, err
|
|
}
|
|
|
|
listPodsContainers = append(listPodsContainers, makeListPodContainers(ctr.ID(), batchInfo))
|
|
}
|
|
listPod := iopodman.ListPodData{
|
|
Createdat: pod.CreatedTime().Format(time.RFC3339),
|
|
Id: pod.ID(),
|
|
Name: pod.Name(),
|
|
Status: status,
|
|
Cgroup: pod.CgroupParent(),
|
|
Numberofcontainers: strconv.Itoa(len(listPodsContainers)),
|
|
Containersinfo: listPodsContainers,
|
|
}
|
|
return listPod, nil
|
|
}
|
|
|
|
func handlePodCall(call iopodman.VarlinkCall, pod *libpod.Pod, ctrErrs map[string]error, err error) error {
|
|
if err != nil && ctrErrs == nil {
|
|
return call.ReplyErrorOccurred(err.Error())
|
|
}
|
|
if ctrErrs != nil {
|
|
containerErrs := make([]iopodman.PodContainerErrorData, len(ctrErrs))
|
|
for ctr, reason := range ctrErrs {
|
|
ctrErr := iopodman.PodContainerErrorData{Containerid: ctr, Reason: reason.Error()}
|
|
containerErrs = append(containerErrs, ctrErr)
|
|
}
|
|
return call.ReplyPodContainerError(pod.ID(), containerErrs)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func stringCompressionToArchiveType(s string) archive.Compression {
|
|
switch strings.ToUpper(s) {
|
|
case "BZIP2":
|
|
return archive.Bzip2
|
|
case "GZIP":
|
|
return archive.Gzip
|
|
case "XZ":
|
|
return archive.Xz
|
|
}
|
|
return archive.Uncompressed
|
|
}
|
|
|
|
func stringPullPolicyToType(s string) buildah.PullPolicy {
|
|
switch strings.ToUpper(s) {
|
|
case "PULLIFMISSING":
|
|
return buildah.PullIfMissing
|
|
case "PULLALWAYS":
|
|
return buildah.PullAlways
|
|
case "PULLNEVER":
|
|
return buildah.PullNever
|
|
}
|
|
return buildah.PullIfMissing
|
|
}
|
|
|
|
func derefBool(inBool *bool) bool {
|
|
if inBool == nil {
|
|
return false
|
|
}
|
|
return *inBool
|
|
}
|
|
|
|
func derefString(in *string) string {
|
|
if in == nil {
|
|
return ""
|
|
}
|
|
return *in
|
|
}
|
|
|
|
func makePsOpts(inOpts iopodman.PsOpts) shared.PsOptions {
|
|
last := 0
|
|
if inOpts.Last != nil {
|
|
lastT := *inOpts.Last
|
|
last = int(lastT)
|
|
}
|
|
return shared.PsOptions{
|
|
All: inOpts.All,
|
|
Last: last,
|
|
Latest: derefBool(inOpts.Latest),
|
|
NoTrunc: derefBool(inOpts.NoTrunc),
|
|
Pod: derefBool(inOpts.Pod),
|
|
Size: derefBool(inOpts.Size),
|
|
Sort: derefString(inOpts.Sort),
|
|
Namespace: true,
|
|
Sync: derefBool(inOpts.Sync),
|
|
}
|
|
}
|
|
|
|
// forwardOutput is a helper method for varlink endpoints that employ both more and without
|
|
// more. it is capable of sending updates as the output writer gets them or append them
|
|
// all to a log. the chan error is the error from the libpod call so we can honor
|
|
// and error event in that case.
|
|
func forwardOutput(log []string, c chan error, wantsMore bool, output *channelwriter.Writer, reply func(br iopodman.MoreResponse) error) ([]string, error) {
|
|
done := false
|
|
for {
|
|
select {
|
|
// We need to check if the libpod func being called has returned an
|
|
// error yet
|
|
case err := <-c:
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
done = true
|
|
// if no error is found, we pull what we can from the log writer and
|
|
// append it to log string slice
|
|
case line := <-output.ByteChannel:
|
|
log = append(log, string(line))
|
|
// If the end point is being used in more mode, send what we have
|
|
if wantsMore {
|
|
br := iopodman.MoreResponse{
|
|
Logs: log,
|
|
}
|
|
if err := reply(br); err != nil {
|
|
return nil, err
|
|
}
|
|
// "reset" the log to empty because we are sending what we
|
|
// get as we get it
|
|
log = []string{}
|
|
}
|
|
}
|
|
if done {
|
|
break
|
|
}
|
|
}
|
|
return log, nil
|
|
}
|