From 028374b99e5c9dd23236a10495ea0aebe819b51f Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 13 Jul 2018 10:24:17 -0400 Subject: Record whether the container has exited Use this to supplement exit codes returned from containers, to make sure we know when exit codes are invalid (as the container has not yet exited) Signed-off-by: Matthew Heon --- cmd/podman/batchcontainer/container.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd/podman/batchcontainer/container.go') diff --git a/cmd/podman/batchcontainer/container.go b/cmd/podman/batchcontainer/container.go index 09db4f8a2..76b10b633 100644 --- a/cmd/podman/batchcontainer/container.go +++ b/cmd/podman/batchcontainer/container.go @@ -75,7 +75,7 @@ func BatchContainerOp(ctr *libpod.Container, opts PsOptions) (BatchContainerStru return errors.Wrapf(err, "unable to obtain container state") } - exitCode, err = c.ExitCode() + exitCode, _, err = c.ExitCode() if err != nil { return errors.Wrapf(err, "unable to obtain container exit code") } -- cgit v1.2.3-54-g00ecf From 4c44185199299f44425ebd689bf3ac42e4606788 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 13 Jul 2018 11:21:37 -0400 Subject: Major fixes to podman ps --format=json output A number of fields were never being populated. Populate them as best we can. Add a new field, exited, to indicate whether the exit code has meaning (IE, the container has exited). Fix handling of running time - it stops ticking when the container stops. There is further work needed here, I suspect. Signed-off-by: Matthew Heon --- cmd/podman/batchcontainer/container.go | 5 ++++- cmd/podman/ps.go | 33 +++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 15 deletions(-) (limited to 'cmd/podman/batchcontainer/container.go') diff --git a/cmd/podman/batchcontainer/container.go b/cmd/podman/batchcontainer/container.go index 76b10b633..6f002f58a 100644 --- a/cmd/podman/batchcontainer/container.go +++ b/cmd/podman/batchcontainer/container.go @@ -38,6 +38,7 @@ type BatchContainerStruct struct { ConConfig *libpod.ContainerConfig ConState libpod.ContainerStatus ExitCode int32 + Exited bool Pid int RootFsSize, RwSize int64 StartedTime time.Time @@ -63,6 +64,7 @@ func BatchContainerOp(ctr *libpod.Container, opts PsOptions) (BatchContainerStru conState libpod.ContainerStatus err error exitCode int32 + exited bool pid int rootFsSize, rwSize int64 startedTime time.Time @@ -75,7 +77,7 @@ func BatchContainerOp(ctr *libpod.Container, opts PsOptions) (BatchContainerStru return errors.Wrapf(err, "unable to obtain container state") } - exitCode, _, err = c.ExitCode() + exitCode, exited, err = c.ExitCode() if err != nil { return errors.Wrapf(err, "unable to obtain container exit code") } @@ -115,6 +117,7 @@ func BatchContainerOp(ctr *libpod.Container, opts PsOptions) (BatchContainerStru ConConfig: conConfig, ConState: conState, ExitCode: exitCode, + Exited: exited, Pid: pid, RootFsSize: rootFsSize, RwSize: rwSize, diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index a5f417449..b659a91a0 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -58,6 +58,7 @@ type psJSONParams struct { Command []string `json:"command"` CreatedAt time.Time `json:"createdAt"` ExitCode int32 `json:"exitCode"` + Exited bool `json:"exited"` RunningFor time.Duration `json:"runningFor"` Status string `json:"status"` PID int `json:"PID"` @@ -576,22 +577,26 @@ func getAndSortJSONParams(containers []*libpod.Container, opts batchcontainer.Ps ns = batchcontainer.GetNamespaces(batchInfo.Pid) } params := psJSONParams{ - ID: ctr.ID(), - Image: batchInfo.ConConfig.RootfsImageName, - ImageID: batchInfo.ConConfig.RootfsImageID, - Command: batchInfo.ConConfig.Spec.Process.Args, - CreatedAt: batchInfo.ConConfig.CreatedTime, - Status: batchInfo.ConState.String(), - Ports: batchInfo.ConConfig.PortMappings, - RootFsSize: batchInfo.RootFsSize, - RWSize: batchInfo.RwSize, - Names: batchInfo.ConConfig.Name, - Labels: batchInfo.ConConfig.Labels, - Mounts: batchInfo.ConConfig.UserVolumes, - Namespaces: ns, + ID: ctr.ID(), + Image: batchInfo.ConConfig.RootfsImageName, + ImageID: batchInfo.ConConfig.RootfsImageID, + Command: batchInfo.ConConfig.Spec.Process.Args, + CreatedAt: batchInfo.ConConfig.CreatedTime, + ExitCode: batchInfo.ExitCode, + Exited: batchInfo.Exited, + Status: batchInfo.ConState.String(), + PID: batchInfo.Pid, + Ports: batchInfo.ConConfig.PortMappings, + RootFsSize: batchInfo.RootFsSize, + RWSize: batchInfo.RwSize, + Names: batchInfo.ConConfig.Name, + Labels: batchInfo.ConConfig.Labels, + Mounts: batchInfo.ConConfig.UserVolumes, + ContainerRunning: batchInfo.ConState == libpod.ContainerStateRunning, + Namespaces: ns, } - if !batchInfo.StartedTime.IsZero() { + if !batchInfo.StartedTime.IsZero() && batchInfo.ConState == libpod.ContainerStateRunning { params.RunningFor = time.Since(batchInfo.StartedTime) } -- cgit v1.2.3-54-g00ecf From 5b43a6a7ee6638b6d6cdb129321e42ce0dce6975 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 13 Jul 2018 11:51:06 -0400 Subject: Only print container size JSON if --size was requested To do this, move it into a separate struct, and embed that in the JSON we return. Signed-off-by: Matthew Heon --- cmd/podman/batchcontainer/container.go | 48 ++++++++++++++++++++-------------- cmd/podman/ps.go | 48 ++++++++++++++++++---------------- pkg/varlinkapi/util.go | 6 +++-- 3 files changed, 59 insertions(+), 43 deletions(-) (limited to 'cmd/podman/batchcontainer/container.go') diff --git a/cmd/podman/batchcontainer/container.go b/cmd/podman/batchcontainer/container.go index 6f002f58a..017837a96 100644 --- a/cmd/podman/batchcontainer/container.go +++ b/cmd/podman/batchcontainer/container.go @@ -35,13 +35,13 @@ type PsOptions struct { // BatchContainerStruct is the return obkect from BatchContainer and contains // container related information type BatchContainerStruct struct { - ConConfig *libpod.ContainerConfig - ConState libpod.ContainerStatus - ExitCode int32 - Exited bool - Pid int - RootFsSize, RwSize int64 - StartedTime time.Time + ConConfig *libpod.ContainerConfig + ConState libpod.ContainerStatus + ExitCode int32 + Exited bool + Pid int + StartedTime time.Time + Size *ContainerSize } // Namespace describes output for ps namespace @@ -56,18 +56,25 @@ type Namespace struct { UTS string `json:"uts,omitempty"` } +// ContainerSize holds the size of the container's root filesystem and top +// read-write layer +type ContainerSize struct { + RootFsSize int64 `json:"rootFsSize"` + RwSize int64 `json:"rwSize"` +} + // BatchContainer is used in ps to reduce performance hits by "batching" // locks. func BatchContainerOp(ctr *libpod.Container, opts PsOptions) (BatchContainerStruct, error) { var ( - conConfig *libpod.ContainerConfig - conState libpod.ContainerStatus - err error - exitCode int32 - exited bool - pid int - rootFsSize, rwSize int64 - startedTime time.Time + conConfig *libpod.ContainerConfig + conState libpod.ContainerStatus + err error + exitCode int32 + exited bool + pid int + size *ContainerSize + startedTime time.Time ) batchErr := ctr.Batch(func(c *libpod.Container) error { @@ -97,16 +104,20 @@ func BatchContainerOp(ctr *libpod.Container, opts PsOptions) (BatchContainerStru } } if opts.Size { - rootFsSize, err = c.RootFsSize() + size = new(ContainerSize) + + rootFsSize, err := c.RootFsSize() if err != nil { logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err) } - rwSize, err = c.RWSize() + rwSize, err := c.RWSize() if err != nil { logrus.Errorf("error getting rw size for %q: %v", c.ID(), err) } + size.RootFsSize = rootFsSize + size.RwSize = rwSize } return nil }) @@ -119,9 +130,8 @@ func BatchContainerOp(ctr *libpod.Container, opts PsOptions) (BatchContainerStru ExitCode: exitCode, Exited: exited, Pid: pid, - RootFsSize: rootFsSize, - RwSize: rwSize, StartedTime: startedTime, + Size: size, }, nil } diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index f2ea3939b..921490ba9 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -52,24 +52,23 @@ type psTemplateParams struct { // psJSONParams will be populated by data from libpod.Container, // the members of the struct are the sama data types as their sources. type psJSONParams struct { - ID string `json:"id"` - Image string `json:"image"` - ImageID string `json:"image_id"` - Command []string `json:"command"` - CreatedAt time.Time `json:"createdAt"` - ExitCode int32 `json:"exitCode"` - Exited bool `json:"exited"` - RunningFor time.Duration `json:"runningFor"` - Status string `json:"status"` - PID int `json:"PID"` - Ports []ocicni.PortMapping `json:"ports"` - RootFsSize int64 `json:"rootFsSize,omitempty"` - RWSize int64 `json:"rwSize,omitempty"` - Names string `json:"names"` - Labels fields.Set `json:"labels"` - Mounts []string `json:"mounts"` - ContainerRunning bool `json:"ctrRunning"` - Namespaces *batchcontainer.Namespace `json:"namespace,omitempty"` + ID string `json:"id"` + Image string `json:"image"` + ImageID string `json:"image_id"` + Command []string `json:"command"` + CreatedAt time.Time `json:"createdAt"` + ExitCode int32 `json:"exitCode"` + Exited bool `json:"exited"` + RunningFor time.Duration `json:"runningFor"` + Status string `json:"status"` + PID int `json:"PID"` + Ports []ocicni.PortMapping `json:"ports"` + Size *batchcontainer.ContainerSize `json:"size,omitempty"` + Names string `json:"names"` + Labels fields.Set `json:"labels"` + Mounts []string `json:"mounts"` + ContainerRunning bool `json:"ctrRunning"` + Namespaces *batchcontainer.Namespace `json:"namespace,omitempty"` } // Type declaration and functions for sorting the PS output @@ -115,7 +114,10 @@ func (a psSortedStatus) Less(i, j int) bool { return a.psSorted[i].Status < a.ps type psSortedSize struct{ psSorted } func (a psSortedSize) Less(i, j int) bool { - return a.psSorted[i].RootFsSize < a.psSorted[j].RootFsSize + if a.psSorted[i].Size == nil || a.psSorted[j].Size == nil { + return false + } + return a.psSorted[i].Size.RootFsSize < a.psSorted[j].Size.RootFsSize } var ( @@ -497,7 +499,10 @@ func getTemplateOutput(psParams []psJSONParams, opts batchcontainer.PsOptions) ( ns = psParam.Namespaces } if opts.Size { - size = units.HumanSizeWithPrecision(float64(psParam.RWSize), 3) + " (virtual " + units.HumanSizeWithPrecision(float64(psParam.RootFsSize), 3) + ")" + if psParam.Size == nil { + return nil, errors.Errorf("Container %s does not have a size struct", psParam.ID) + } + size = units.HumanSizeWithPrecision(float64(psParam.Size.RwSize), 3) + " (virtual " + units.HumanSizeWithPrecision(float64(psParam.Size.RootFsSize), 3) + ")" } runningFor := units.HumanDuration(psParam.RunningFor) @@ -587,8 +592,7 @@ func getAndSortJSONParams(containers []*libpod.Container, opts batchcontainer.Ps Status: batchInfo.ConState.String(), PID: batchInfo.Pid, Ports: batchInfo.ConConfig.PortMappings, - RootFsSize: batchInfo.RootFsSize, - RWSize: batchInfo.RwSize, + Size: batchInfo.Size, Names: batchInfo.ConConfig.Name, Labels: batchInfo.ConConfig.Labels, Mounts: batchInfo.ConConfig.UserVolumes, diff --git a/pkg/varlinkapi/util.go b/pkg/varlinkapi/util.go index 25ab59801..ad5c8c19d 100644 --- a/pkg/varlinkapi/util.go +++ b/pkg/varlinkapi/util.go @@ -65,13 +65,15 @@ func makeListContainer(containerID string, batchInfo batchcontainer.BatchContain 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, } + if batchInfo.Size != nil { + lc.Rootfssize = batchInfo.Size.RootFsSize + lc.Rwsize = batchInfo.Size.RwSize + } return lc } -- cgit v1.2.3-54-g00ecf