From 8d5e0108d7c8b69abb9821bfe55475ae5d663b3a Mon Sep 17 00:00:00 2001
From: haircommander <pehunt@redhat.com>
Date: Tue, 14 Aug 2018 17:16:22 -0400
Subject: Change batchcontainer to shared

To better reflect it's usage: to share functions between podman and varlink.

Signed-off-by: haircommander <pehunt@redhat.com>

Closes: #1275
Approved by: mheon
---
 cmd/podman/batchcontainer/container.go | 328 ---------------------------------
 cmd/podman/inspect.go                  |   6 +-
 cmd/podman/pod_ps.go                   |  12 +-
 cmd/podman/ps.go                       |  56 +++---
 cmd/podman/shared/.pod.go.swp          | Bin 0 -> 12288 bytes
 cmd/podman/shared/container.go         | 328 +++++++++++++++++++++++++++++++++
 cmd/podman/shared/pod.go               |  62 +++++++
 libpod/pod_api.go                      |  61 +-----
 pkg/varlinkapi/containers.go           |  12 +-
 pkg/varlinkapi/pods.go                 |   6 +-
 pkg/varlinkapi/util.go                 |  14 +-
 11 files changed, 445 insertions(+), 440 deletions(-)
 delete mode 100644 cmd/podman/batchcontainer/container.go
 create mode 100644 cmd/podman/shared/.pod.go.swp
 create mode 100644 cmd/podman/shared/container.go
 create mode 100644 cmd/podman/shared/pod.go

diff --git a/cmd/podman/batchcontainer/container.go b/cmd/podman/batchcontainer/container.go
deleted file mode 100644
index 364b28d40..000000000
--- a/cmd/podman/batchcontainer/container.go
+++ /dev/null
@@ -1,328 +0,0 @@
-package batchcontainer
-
-import (
-	"encoding/json"
-	"os"
-	"path/filepath"
-	"regexp"
-	"strconv"
-	"strings"
-	"time"
-
-	"github.com/containers/libpod/libpod"
-	"github.com/containers/libpod/pkg/inspect"
-	cc "github.com/containers/libpod/pkg/spec"
-	"github.com/opencontainers/runtime-spec/specs-go"
-	"github.com/pkg/errors"
-	"github.com/sirupsen/logrus"
-)
-
-// PsOptions describes the struct being formed for ps
-type PsOptions struct {
-	All       bool
-	Filter    string
-	Format    string
-	Last      int
-	Latest    bool
-	NoTrunc   bool
-	Pod       bool
-	Quiet     bool
-	Size      bool
-	Sort      string
-	Label     string
-	Namespace bool
-}
-
-// 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
-	StartedTime time.Time
-	ExitedTime  time.Time
-	Size        *ContainerSize
-}
-
-// Namespace describes output for ps namespace
-type Namespace struct {
-	PID    string `json:"pid,omitempty"`
-	Cgroup string `json:"cgroup,omitempty"`
-	IPC    string `json:"ipc,omitempty"`
-	MNT    string `json:"mnt,omitempty"`
-	NET    string `json:"net,omitempty"`
-	PIDNS  string `json:"pidns,omitempty"`
-	User   string `json:"user,omitempty"`
-	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
-		size        *ContainerSize
-		startedTime time.Time
-		exitedTime  time.Time
-	)
-
-	batchErr := ctr.Batch(func(c *libpod.Container) error {
-		conConfig = c.Config()
-		conState, err = c.State()
-		if err != nil {
-			return errors.Wrapf(err, "unable to obtain container state")
-		}
-
-		exitCode, exited, err = c.ExitCode()
-		if err != nil {
-			return errors.Wrapf(err, "unable to obtain container exit code")
-		}
-		startedTime, err = c.StartedTime()
-		if err != nil {
-			logrus.Errorf("error getting started time for %q: %v", c.ID(), err)
-		}
-		exitedTime, err = c.FinishedTime()
-		if err != nil {
-			logrus.Errorf("error getting exited time for %q: %v", c.ID(), err)
-		}
-
-		if !opts.Size && !opts.Namespace {
-			return nil
-		}
-
-		if opts.Namespace {
-			pid, err = c.PID()
-			if err != nil {
-				return errors.Wrapf(err, "unable to obtain container pid")
-			}
-		}
-		if opts.Size {
-			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()
-			if err != nil {
-				logrus.Errorf("error getting rw size for %q: %v", c.ID(), err)
-			}
-
-			size.RootFsSize = rootFsSize
-			size.RwSize = rwSize
-		}
-		return nil
-	})
-	if batchErr != nil {
-		return BatchContainerStruct{}, batchErr
-	}
-	return BatchContainerStruct{
-		ConConfig:   conConfig,
-		ConState:    conState,
-		ExitCode:    exitCode,
-		Exited:      exited,
-		Pid:         pid,
-		StartedTime: startedTime,
-		ExitedTime:  exitedTime,
-		Size:        size,
-	}, nil
-}
-
-// GetNamespaces returns a populated namespace struct
-func GetNamespaces(pid int) *Namespace {
-	ctrPID := strconv.Itoa(pid)
-	cgroup, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup"))
-	ipc, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc"))
-	mnt, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt"))
-	net, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net"))
-	pidns, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid"))
-	user, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user"))
-	uts, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts"))
-
-	return &Namespace{
-		PID:    ctrPID,
-		Cgroup: cgroup,
-		IPC:    ipc,
-		MNT:    mnt,
-		NET:    net,
-		PIDNS:  pidns,
-		User:   user,
-		UTS:    uts,
-	}
-}
-
-func getNamespaceInfo(path string) (string, error) {
-	val, err := os.Readlink(path)
-	if err != nil {
-		return "", errors.Wrapf(err, "error getting info from %q", path)
-	}
-	return getStrFromSquareBrackets(val), nil
-}
-
-// getStrFromSquareBrackets gets the string inside [] from a string
-func getStrFromSquareBrackets(cmd string) string {
-	reg, err := regexp.Compile(".*\\[|\\].*")
-	if err != nil {
-		return ""
-	}
-	arr := strings.Split(reg.ReplaceAllLiteralString(cmd, ""), ",")
-	return strings.Join(arr, ",")
-}
-
-// GetCtrInspectInfo takes container inspect data and collects all its info into a ContainerData
-// structure for inspection related methods
-func GetCtrInspectInfo(ctr *libpod.Container, ctrInspectData *inspect.ContainerInspectData) (*inspect.ContainerData, error) {
-	config := ctr.Config()
-	spec := config.Spec
-
-	cpus, mems, period, quota, realtimePeriod, realtimeRuntime, shares := getCPUInfo(spec)
-	blkioWeight, blkioWeightDevice, blkioReadBps, blkioWriteBps, blkioReadIOPS, blkioeWriteIOPS := getBLKIOInfo(spec)
-	memKernel, memReservation, memSwap, memSwappiness, memDisableOOMKiller := getMemoryInfo(spec)
-	pidsLimit := getPidsInfo(spec)
-	cgroup := getCgroup(spec)
-
-	var createArtifact cc.CreateConfig
-	artifact, err := ctr.GetArtifact("create-config")
-	if err == nil {
-		if err := json.Unmarshal(artifact, &createArtifact); err != nil {
-			return nil, err
-		}
-	} else {
-		logrus.Errorf("couldn't get some inspect information, error getting artifact %q: %v", ctr.ID(), err)
-	}
-
-	data := &inspect.ContainerData{
-		ctrInspectData,
-		&inspect.HostConfig{
-			ConsoleSize:          spec.Process.ConsoleSize,
-			OomScoreAdj:          spec.Process.OOMScoreAdj,
-			CPUShares:            shares,
-			BlkioWeight:          blkioWeight,
-			BlkioWeightDevice:    blkioWeightDevice,
-			BlkioDeviceReadBps:   blkioReadBps,
-			BlkioDeviceWriteBps:  blkioWriteBps,
-			BlkioDeviceReadIOps:  blkioReadIOPS,
-			BlkioDeviceWriteIOps: blkioeWriteIOPS,
-			CPUPeriod:            period,
-			CPUQuota:             quota,
-			CPURealtimePeriod:    realtimePeriod,
-			CPURealtimeRuntime:   realtimeRuntime,
-			CPUSetCPUs:           cpus,
-			CPUSetMems:           mems,
-			Devices:              spec.Linux.Devices,
-			KernelMemory:         memKernel,
-			MemoryReservation:    memReservation,
-			MemorySwap:           memSwap,
-			MemorySwappiness:     memSwappiness,
-			OomKillDisable:       memDisableOOMKiller,
-			PidsLimit:            pidsLimit,
-			Privileged:           config.Privileged,
-			ReadonlyRootfs:       spec.Root.Readonly,
-			Runtime:              ctr.RuntimeName(),
-			NetworkMode:          string(createArtifact.NetMode),
-			IpcMode:              string(createArtifact.IpcMode),
-			Cgroup:               cgroup,
-			UTSMode:              string(createArtifact.UtsMode),
-			UsernsMode:           string(createArtifact.UsernsMode),
-			GroupAdd:             spec.Process.User.AdditionalGids,
-			ContainerIDFile:      createArtifact.CidFile,
-			AutoRemove:           createArtifact.Rm,
-			CapAdd:               createArtifact.CapAdd,
-			CapDrop:              createArtifact.CapDrop,
-			DNS:                  createArtifact.DNSServers,
-			DNSOptions:           createArtifact.DNSOpt,
-			DNSSearch:            createArtifact.DNSSearch,
-			PidMode:              string(createArtifact.PidMode),
-			CgroupParent:         createArtifact.CgroupParent,
-			ShmSize:              createArtifact.Resources.ShmSize,
-			Memory:               createArtifact.Resources.Memory,
-			Ulimits:              createArtifact.Resources.Ulimit,
-			SecurityOpt:          createArtifact.SecurityOpts,
-			Tmpfs:                createArtifact.Tmpfs,
-		},
-		&inspect.CtrConfig{
-			Hostname:    spec.Hostname,
-			User:        spec.Process.User,
-			Env:         spec.Process.Env,
-			Image:       config.RootfsImageName,
-			WorkingDir:  spec.Process.Cwd,
-			Labels:      config.Labels,
-			Annotations: spec.Annotations,
-			Tty:         spec.Process.Terminal,
-			OpenStdin:   config.Stdin,
-			StopSignal:  config.StopSignal,
-			Cmd:         config.Spec.Process.Args,
-			Entrypoint:  strings.Join(createArtifact.Entrypoint, " "),
-		},
-	}
-	return data, nil
-}
-
-func getCPUInfo(spec *specs.Spec) (string, string, *uint64, *int64, *uint64, *int64, *uint64) {
-	if spec.Linux.Resources == nil {
-		return "", "", nil, nil, nil, nil, nil
-	}
-	cpu := spec.Linux.Resources.CPU
-	if cpu == nil {
-		return "", "", nil, nil, nil, nil, nil
-	}
-	return cpu.Cpus, cpu.Mems, cpu.Period, cpu.Quota, cpu.RealtimePeriod, cpu.RealtimeRuntime, cpu.Shares
-}
-
-func getBLKIOInfo(spec *specs.Spec) (*uint16, []specs.LinuxWeightDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice) {
-	if spec.Linux.Resources == nil {
-		return nil, nil, nil, nil, nil, nil
-	}
-	blkio := spec.Linux.Resources.BlockIO
-	if blkio == nil {
-		return nil, nil, nil, nil, nil, nil
-	}
-	return blkio.Weight, blkio.WeightDevice, blkio.ThrottleReadBpsDevice, blkio.ThrottleWriteBpsDevice, blkio.ThrottleReadIOPSDevice, blkio.ThrottleWriteIOPSDevice
-}
-
-func getMemoryInfo(spec *specs.Spec) (*int64, *int64, *int64, *uint64, *bool) {
-	if spec.Linux.Resources == nil {
-		return nil, nil, nil, nil, nil
-	}
-	memory := spec.Linux.Resources.Memory
-	if memory == nil {
-		return nil, nil, nil, nil, nil
-	}
-	return memory.Kernel, memory.Reservation, memory.Swap, memory.Swappiness, memory.DisableOOMKiller
-}
-
-func getPidsInfo(spec *specs.Spec) *int64 {
-	if spec.Linux.Resources == nil {
-		return nil
-	}
-	pids := spec.Linux.Resources.Pids
-	if pids == nil {
-		return nil
-	}
-	return &pids.Limit
-}
-
-func getCgroup(spec *specs.Spec) string {
-	cgroup := "host"
-	for _, ns := range spec.Linux.Namespaces {
-		if ns.Type == specs.CgroupNamespace && ns.Path != "" {
-			cgroup = "container"
-		}
-	}
-	return cgroup
-}
diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go
index 1fa8f55a2..a36f8c7a1 100644
--- a/cmd/podman/inspect.go
+++ b/cmd/podman/inspect.go
@@ -4,9 +4,9 @@ import (
 	"context"
 	"strings"
 
-	"github.com/containers/libpod/cmd/podman/batchcontainer"
 	"github.com/containers/libpod/cmd/podman/formats"
 	"github.com/containers/libpod/cmd/podman/libpodruntime"
+	"github.com/containers/libpod/cmd/podman/shared"
 	"github.com/containers/libpod/libpod"
 	"github.com/containers/libpod/pkg/util"
 	"github.com/pkg/errors"
@@ -121,7 +121,7 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *l
 				inspectError = errors.Wrapf(err, "error getting libpod container inspect data %q", ctr.ID)
 				break
 			}
-			data, err = batchcontainer.GetCtrInspectInfo(ctr, libpodInspectData)
+			data, err = shared.GetCtrInspectInfo(ctr, libpodInspectData)
 			if err != nil {
 				inspectError = errors.Wrapf(err, "error parsing container data %q", ctr.ID())
 				break
@@ -156,7 +156,7 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *l
 					inspectError = errors.Wrapf(err, "error getting libpod container inspect data %q", ctr.ID)
 					break
 				}
-				data, err = batchcontainer.GetCtrInspectInfo(ctr, libpodInspectData)
+				data, err = shared.GetCtrInspectInfo(ctr, libpodInspectData)
 				if err != nil {
 					inspectError = errors.Wrapf(err, "error parsing container data %q", ctr.ID)
 					break
diff --git a/cmd/podman/pod_ps.go b/cmd/podman/pod_ps.go
index 52fbea6e5..20beae53a 100644
--- a/cmd/podman/pod_ps.go
+++ b/cmd/podman/pod_ps.go
@@ -7,9 +7,9 @@ import (
 	"strings"
 	"time"
 
-	"github.com/containers/libpod/cmd/podman/batchcontainer"
 	"github.com/containers/libpod/cmd/podman/formats"
 	"github.com/containers/libpod/cmd/podman/libpodruntime"
+	"github.com/containers/libpod/cmd/podman/shared"
 	"github.com/containers/libpod/libpod"
 	"github.com/containers/libpod/pkg/util"
 	"github.com/docker/go-units"
@@ -28,7 +28,7 @@ const (
 )
 
 var (
-	bc_opts batchcontainer.PsOptions
+	bc_opts shared.PsOptions
 )
 
 type podPsCtrInfo struct {
@@ -296,7 +296,7 @@ func generatePodFilterFuncs(filter, filterValue string, runtime *libpod.Runtime)
 			return nil, errors.Errorf("%s is not a valid status", filterValue)
 		}
 		return func(p *libpod.Pod) bool {
-			ctr_statuses, err := p.ContainerStatus()
+			ctr_statuses, err := p.Status()
 			if err != nil {
 				return false
 			}
@@ -324,7 +324,7 @@ func generatePodFilterFuncs(filter, filterValue string, runtime *libpod.Runtime)
 			return nil, errors.Errorf("%s is not a valid pod status", filterValue)
 		}
 		return func(p *libpod.Pod) bool {
-			status, err := p.Status()
+			status, err := shared.GetPodStatus(p)
 			if err != nil {
 				return false
 			}
@@ -473,13 +473,13 @@ func getAndSortPodJSONParams(pods []*libpod.Pod, opts podPsOptions, runtime *lib
 			return nil, err
 		}
 		ctrNum := len(ctrs)
-		status, err := pod.Status()
+		status, err := shared.GetPodStatus(pod)
 		if err != nil {
 			return nil, err
 		}
 
 		for _, ctr := range ctrs {
-			batchInfo, err := batchcontainer.BatchContainerOp(ctr, bc_opts)
+			batchInfo, err := shared.BatchContainerOp(ctr, bc_opts)
 			if err != nil {
 				return nil, err
 			}
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index 94e8a4920..0ad511217 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -8,9 +8,9 @@ import (
 	"strings"
 	"time"
 
-	"github.com/containers/libpod/cmd/podman/batchcontainer"
 	"github.com/containers/libpod/cmd/podman/formats"
 	"github.com/containers/libpod/cmd/podman/libpodruntime"
+	"github.com/containers/libpod/cmd/podman/shared"
 	"github.com/containers/libpod/libpod"
 	"github.com/containers/libpod/pkg/util"
 	"github.com/cri-o/ocicni/pkg/ocicni"
@@ -52,25 +52,25 @@ 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"`
-	ExitCode         int32                         `json:"exitCode"`
-	Exited           bool                          `json:"exited"`
-	CreatedAt        time.Time                     `json:"createdAt"`
-	StartedAt        time.Time                     `json:"startedAt"`
-	ExitedAt         time.Time                     `json:"exitedAt"`
-	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"`
-	Pod              string                        `json:"pod,omitempty"`
+	ID               string                `json:"id"`
+	Image            string                `json:"image"`
+	ImageID          string                `json:"image_id"`
+	Command          []string              `json:"command"`
+	ExitCode         int32                 `json:"exitCode"`
+	Exited           bool                  `json:"exited"`
+	CreatedAt        time.Time             `json:"createdAt"`
+	StartedAt        time.Time             `json:"startedAt"`
+	ExitedAt         time.Time             `json:"exitedAt"`
+	Status           string                `json:"status"`
+	PID              int                   `json:"PID"`
+	Ports            []ocicni.PortMapping  `json:"ports"`
+	Size             *shared.ContainerSize `json:"size,omitempty"`
+	Names            string                `json:"names"`
+	Labels           fields.Set            `json:"labels"`
+	Mounts           []string              `json:"mounts"`
+	ContainerRunning bool                  `json:"ctrRunning"`
+	Namespaces       *shared.Namespace     `json:"namespace,omitempty"`
+	Pod              string                `json:"pod,omitempty"`
 }
 
 // Type declaration and functions for sorting the PS output
@@ -218,7 +218,7 @@ func psCmd(c *cli.Context) error {
 
 	format := genPsFormat(c.String("format"), c.Bool("quiet"), c.Bool("size"), c.Bool("namespace"), c.Bool("pod"))
 
-	opts := batchcontainer.PsOptions{
+	opts := shared.PsOptions{
 		All:       c.Bool("all"),
 		Filter:    c.String("filter"),
 		Format:    format,
@@ -497,11 +497,11 @@ func sortPsOutput(sortBy string, psOutput psSorted) (psSorted, error) {
 }
 
 // getTemplateOutput returns the modified container information
-func getTemplateOutput(psParams []psJSONParams, opts batchcontainer.PsOptions) ([]psTemplateParams, error) {
+func getTemplateOutput(psParams []psJSONParams, opts shared.PsOptions) ([]psTemplateParams, error) {
 	var (
 		psOutput          []psTemplateParams
 		pod, status, size string
-		ns                *batchcontainer.Namespace
+		ns                *shared.Namespace
 	)
 	// If the user is trying to filter based on size, or opted to sort on size
 	// the size bool must be set.
@@ -589,13 +589,13 @@ func getTemplateOutput(psParams []psJSONParams, opts batchcontainer.PsOptions) (
 }
 
 // getAndSortJSONOutput returns the container info in its raw, sorted form
-func getAndSortJSONParams(containers []*libpod.Container, opts batchcontainer.PsOptions) ([]psJSONParams, error) {
+func getAndSortJSONParams(containers []*libpod.Container, opts shared.PsOptions) ([]psJSONParams, error) {
 	var (
 		psOutput psSorted
-		ns       *batchcontainer.Namespace
+		ns       *shared.Namespace
 	)
 	for _, ctr := range containers {
-		batchInfo, err := batchcontainer.BatchContainerOp(ctr, opts)
+		batchInfo, err := shared.BatchContainerOp(ctr, opts)
 		if err != nil {
 			if errors.Cause(err) == libpod.ErrNoSuchCtr {
 				logrus.Warn(err)
@@ -605,7 +605,7 @@ func getAndSortJSONParams(containers []*libpod.Container, opts batchcontainer.Ps
 		}
 
 		if opts.Namespace {
-			ns = batchcontainer.GetNamespaces(batchInfo.Pid)
+			ns = shared.GetNamespaces(batchInfo.Pid)
 		}
 		params := psJSONParams{
 			ID:               ctr.ID(),
@@ -634,7 +634,7 @@ func getAndSortJSONParams(containers []*libpod.Container, opts batchcontainer.Ps
 	return sortPsOutput(opts.Sort, psOutput)
 }
 
-func generatePsOutput(containers []*libpod.Container, opts batchcontainer.PsOptions) error {
+func generatePsOutput(containers []*libpod.Container, opts shared.PsOptions) error {
 	if len(containers) == 0 && opts.Format != formats.JSONString {
 		return nil
 	}
diff --git a/cmd/podman/shared/.pod.go.swp b/cmd/podman/shared/.pod.go.swp
new file mode 100644
index 000000000..a8565e752
Binary files /dev/null and b/cmd/podman/shared/.pod.go.swp differ
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
new file mode 100644
index 000000000..7a5455046
--- /dev/null
+++ b/cmd/podman/shared/container.go
@@ -0,0 +1,328 @@
+package shared
+
+import (
+	"encoding/json"
+	"os"
+	"path/filepath"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/containers/libpod/libpod"
+	"github.com/containers/libpod/pkg/inspect"
+	cc "github.com/containers/libpod/pkg/spec"
+	"github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+)
+
+// PsOptions describes the struct being formed for ps
+type PsOptions struct {
+	All       bool
+	Filter    string
+	Format    string
+	Last      int
+	Latest    bool
+	NoTrunc   bool
+	Pod       bool
+	Quiet     bool
+	Size      bool
+	Sort      string
+	Label     string
+	Namespace bool
+}
+
+// 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
+	StartedTime time.Time
+	ExitedTime  time.Time
+	Size        *ContainerSize
+}
+
+// Namespace describes output for ps namespace
+type Namespace struct {
+	PID    string `json:"pid,omitempty"`
+	Cgroup string `json:"cgroup,omitempty"`
+	IPC    string `json:"ipc,omitempty"`
+	MNT    string `json:"mnt,omitempty"`
+	NET    string `json:"net,omitempty"`
+	PIDNS  string `json:"pidns,omitempty"`
+	User   string `json:"user,omitempty"`
+	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
+		size        *ContainerSize
+		startedTime time.Time
+		exitedTime  time.Time
+	)
+
+	batchErr := ctr.Batch(func(c *libpod.Container) error {
+		conConfig = c.Config()
+		conState, err = c.State()
+		if err != nil {
+			return errors.Wrapf(err, "unable to obtain container state")
+		}
+
+		exitCode, exited, err = c.ExitCode()
+		if err != nil {
+			return errors.Wrapf(err, "unable to obtain container exit code")
+		}
+		startedTime, err = c.StartedTime()
+		if err != nil {
+			logrus.Errorf("error getting started time for %q: %v", c.ID(), err)
+		}
+		exitedTime, err = c.FinishedTime()
+		if err != nil {
+			logrus.Errorf("error getting exited time for %q: %v", c.ID(), err)
+		}
+
+		if !opts.Size && !opts.Namespace {
+			return nil
+		}
+
+		if opts.Namespace {
+			pid, err = c.PID()
+			if err != nil {
+				return errors.Wrapf(err, "unable to obtain container pid")
+			}
+		}
+		if opts.Size {
+			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()
+			if err != nil {
+				logrus.Errorf("error getting rw size for %q: %v", c.ID(), err)
+			}
+
+			size.RootFsSize = rootFsSize
+			size.RwSize = rwSize
+		}
+		return nil
+	})
+	if batchErr != nil {
+		return BatchContainerStruct{}, batchErr
+	}
+	return BatchContainerStruct{
+		ConConfig:   conConfig,
+		ConState:    conState,
+		ExitCode:    exitCode,
+		Exited:      exited,
+		Pid:         pid,
+		StartedTime: startedTime,
+		ExitedTime:  exitedTime,
+		Size:        size,
+	}, nil
+}
+
+// GetNamespaces returns a populated namespace struct
+func GetNamespaces(pid int) *Namespace {
+	ctrPID := strconv.Itoa(pid)
+	cgroup, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup"))
+	ipc, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc"))
+	mnt, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt"))
+	net, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net"))
+	pidns, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid"))
+	user, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user"))
+	uts, _ := getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts"))
+
+	return &Namespace{
+		PID:    ctrPID,
+		Cgroup: cgroup,
+		IPC:    ipc,
+		MNT:    mnt,
+		NET:    net,
+		PIDNS:  pidns,
+		User:   user,
+		UTS:    uts,
+	}
+}
+
+func getNamespaceInfo(path string) (string, error) {
+	val, err := os.Readlink(path)
+	if err != nil {
+		return "", errors.Wrapf(err, "error getting info from %q", path)
+	}
+	return getStrFromSquareBrackets(val), nil
+}
+
+// getStrFromSquareBrackets gets the string inside [] from a string
+func getStrFromSquareBrackets(cmd string) string {
+	reg, err := regexp.Compile(".*\\[|\\].*")
+	if err != nil {
+		return ""
+	}
+	arr := strings.Split(reg.ReplaceAllLiteralString(cmd, ""), ",")
+	return strings.Join(arr, ",")
+}
+
+// GetCtrInspectInfo takes container inspect data and collects all its info into a ContainerData
+// structure for inspection related methods
+func GetCtrInspectInfo(ctr *libpod.Container, ctrInspectData *inspect.ContainerInspectData) (*inspect.ContainerData, error) {
+	config := ctr.Config()
+	spec := config.Spec
+
+	cpus, mems, period, quota, realtimePeriod, realtimeRuntime, shares := getCPUInfo(spec)
+	blkioWeight, blkioWeightDevice, blkioReadBps, blkioWriteBps, blkioReadIOPS, blkioeWriteIOPS := getBLKIOInfo(spec)
+	memKernel, memReservation, memSwap, memSwappiness, memDisableOOMKiller := getMemoryInfo(spec)
+	pidsLimit := getPidsInfo(spec)
+	cgroup := getCgroup(spec)
+
+	var createArtifact cc.CreateConfig
+	artifact, err := ctr.GetArtifact("create-config")
+	if err == nil {
+		if err := json.Unmarshal(artifact, &createArtifact); err != nil {
+			return nil, err
+		}
+	} else {
+		logrus.Errorf("couldn't get some inspect information, error getting artifact %q: %v", ctr.ID(), err)
+	}
+
+	data := &inspect.ContainerData{
+		ctrInspectData,
+		&inspect.HostConfig{
+			ConsoleSize:          spec.Process.ConsoleSize,
+			OomScoreAdj:          spec.Process.OOMScoreAdj,
+			CPUShares:            shares,
+			BlkioWeight:          blkioWeight,
+			BlkioWeightDevice:    blkioWeightDevice,
+			BlkioDeviceReadBps:   blkioReadBps,
+			BlkioDeviceWriteBps:  blkioWriteBps,
+			BlkioDeviceReadIOps:  blkioReadIOPS,
+			BlkioDeviceWriteIOps: blkioeWriteIOPS,
+			CPUPeriod:            period,
+			CPUQuota:             quota,
+			CPURealtimePeriod:    realtimePeriod,
+			CPURealtimeRuntime:   realtimeRuntime,
+			CPUSetCPUs:           cpus,
+			CPUSetMems:           mems,
+			Devices:              spec.Linux.Devices,
+			KernelMemory:         memKernel,
+			MemoryReservation:    memReservation,
+			MemorySwap:           memSwap,
+			MemorySwappiness:     memSwappiness,
+			OomKillDisable:       memDisableOOMKiller,
+			PidsLimit:            pidsLimit,
+			Privileged:           config.Privileged,
+			ReadonlyRootfs:       spec.Root.Readonly,
+			Runtime:              ctr.RuntimeName(),
+			NetworkMode:          string(createArtifact.NetMode),
+			IpcMode:              string(createArtifact.IpcMode),
+			Cgroup:               cgroup,
+			UTSMode:              string(createArtifact.UtsMode),
+			UsernsMode:           string(createArtifact.UsernsMode),
+			GroupAdd:             spec.Process.User.AdditionalGids,
+			ContainerIDFile:      createArtifact.CidFile,
+			AutoRemove:           createArtifact.Rm,
+			CapAdd:               createArtifact.CapAdd,
+			CapDrop:              createArtifact.CapDrop,
+			DNS:                  createArtifact.DNSServers,
+			DNSOptions:           createArtifact.DNSOpt,
+			DNSSearch:            createArtifact.DNSSearch,
+			PidMode:              string(createArtifact.PidMode),
+			CgroupParent:         createArtifact.CgroupParent,
+			ShmSize:              createArtifact.Resources.ShmSize,
+			Memory:               createArtifact.Resources.Memory,
+			Ulimits:              createArtifact.Resources.Ulimit,
+			SecurityOpt:          createArtifact.SecurityOpts,
+			Tmpfs:                createArtifact.Tmpfs,
+		},
+		&inspect.CtrConfig{
+			Hostname:    spec.Hostname,
+			User:        spec.Process.User,
+			Env:         spec.Process.Env,
+			Image:       config.RootfsImageName,
+			WorkingDir:  spec.Process.Cwd,
+			Labels:      config.Labels,
+			Annotations: spec.Annotations,
+			Tty:         spec.Process.Terminal,
+			OpenStdin:   config.Stdin,
+			StopSignal:  config.StopSignal,
+			Cmd:         config.Spec.Process.Args,
+			Entrypoint:  strings.Join(createArtifact.Entrypoint, " "),
+		},
+	}
+	return data, nil
+}
+
+func getCPUInfo(spec *specs.Spec) (string, string, *uint64, *int64, *uint64, *int64, *uint64) {
+	if spec.Linux.Resources == nil {
+		return "", "", nil, nil, nil, nil, nil
+	}
+	cpu := spec.Linux.Resources.CPU
+	if cpu == nil {
+		return "", "", nil, nil, nil, nil, nil
+	}
+	return cpu.Cpus, cpu.Mems, cpu.Period, cpu.Quota, cpu.RealtimePeriod, cpu.RealtimeRuntime, cpu.Shares
+}
+
+func getBLKIOInfo(spec *specs.Spec) (*uint16, []specs.LinuxWeightDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice) {
+	if spec.Linux.Resources == nil {
+		return nil, nil, nil, nil, nil, nil
+	}
+	blkio := spec.Linux.Resources.BlockIO
+	if blkio == nil {
+		return nil, nil, nil, nil, nil, nil
+	}
+	return blkio.Weight, blkio.WeightDevice, blkio.ThrottleReadBpsDevice, blkio.ThrottleWriteBpsDevice, blkio.ThrottleReadIOPSDevice, blkio.ThrottleWriteIOPSDevice
+}
+
+func getMemoryInfo(spec *specs.Spec) (*int64, *int64, *int64, *uint64, *bool) {
+	if spec.Linux.Resources == nil {
+		return nil, nil, nil, nil, nil
+	}
+	memory := spec.Linux.Resources.Memory
+	if memory == nil {
+		return nil, nil, nil, nil, nil
+	}
+	return memory.Kernel, memory.Reservation, memory.Swap, memory.Swappiness, memory.DisableOOMKiller
+}
+
+func getPidsInfo(spec *specs.Spec) *int64 {
+	if spec.Linux.Resources == nil {
+		return nil
+	}
+	pids := spec.Linux.Resources.Pids
+	if pids == nil {
+		return nil
+	}
+	return &pids.Limit
+}
+
+func getCgroup(spec *specs.Spec) string {
+	cgroup := "host"
+	for _, ns := range spec.Linux.Namespaces {
+		if ns.Type == specs.CgroupNamespace && ns.Path != "" {
+			cgroup = "container"
+		}
+	}
+	return cgroup
+}
diff --git a/cmd/podman/shared/pod.go b/cmd/podman/shared/pod.go
new file mode 100644
index 000000000..50c642d59
--- /dev/null
+++ b/cmd/podman/shared/pod.go
@@ -0,0 +1,62 @@
+package shared
+
+import (
+	"github.com/projectatomic/libpod/libpod"
+)
+
+const (
+	stopped = "Stopped"
+	running = "Running"
+	paused  = "Paused"
+	exited  = "Exited"
+	errored = "Error"
+	created = "Created"
+)
+
+// GetPodStatus determines the status of the pod based on the
+// statuses of the containers in the pod.
+// Returns a string representation of the pod status
+func GetPodStatus(pod *libpod.Pod) (string, error) {
+	ctrStatuses, err := pod.Status()
+	if err != nil {
+		return errored, err
+	}
+	ctrNum := len(ctrStatuses)
+	if ctrNum == 0 {
+		return created, nil
+	}
+	statuses := map[string]int{
+		stopped: 0,
+		running: 0,
+		paused:  0,
+		created: 0,
+		errored: 0,
+	}
+	for _, ctrStatus := range ctrStatuses {
+		switch ctrStatus {
+		case libpod.ContainerStateStopped:
+			statuses[stopped]++
+		case libpod.ContainerStateRunning:
+			statuses[running]++
+		case libpod.ContainerStatePaused:
+			statuses[paused]++
+		case libpod.ContainerStateCreated, libpod.ContainerStateConfigured:
+			statuses[created]++
+		default:
+			statuses[errored]++
+		}
+	}
+
+	if statuses[running] > 0 {
+		return running, nil
+	} else if statuses[paused] == ctrNum {
+		return paused, nil
+	} else if statuses[stopped] == ctrNum {
+		return exited, nil
+	} else if statuses[stopped] > 0 {
+		return stopped, nil
+	} else if statuses[errored] > 0 {
+		return errored, nil
+	}
+	return created, nil
+}
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 4d404587f..d1e19063c 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -8,15 +8,6 @@ import (
 	"github.com/ulule/deepcopier"
 )
 
-const (
-	stopped = "Stopped"
-	running = "Running"
-	paused  = "Paused"
-	exited  = "Exited"
-	errored = "Error"
-	created = "Created"
-)
-
 // Start starts all containers within a pod
 // It combines the effects of Init() and Start() on a container
 // If a container has already been initialized it will be started,
@@ -371,9 +362,9 @@ func (p *Pod) Kill(signal uint) (map[string]error, error) {
 	return nil, nil
 }
 
-// ContainerStatus gets the status of all containers in the pod
+// Status gets the status of all containers in the pod
 // Returns a map of Container ID to Container Status
-func (p *Pod) ContainerStatus() (map[string]ContainerStatus, error) {
+func (p *Pod) Status() (map[string]ContainerStatus, error) {
 	p.lock.Lock()
 	defer p.lock.Unlock()
 
@@ -405,54 +396,6 @@ func (p *Pod) ContainerStatus() (map[string]ContainerStatus, error) {
 	return status, nil
 }
 
-// Status determines the status of the pod based on the
-// statuses of the containers in the pod.
-// Returns a string representation of the pod status
-func (p *Pod) Status() (string, error) {
-	ctrStatuses, err := p.ContainerStatus()
-	if err != nil {
-		return errored, err
-	}
-	ctrNum := len(ctrStatuses)
-	if ctrNum == 0 {
-		return created, nil
-	}
-	statuses := map[string]int{
-		stopped: 0,
-		running: 0,
-		paused:  0,
-		created: 0,
-		errored: 0,
-	}
-	for _, ctrStatus := range ctrStatuses {
-		switch ctrStatus {
-		case ContainerStateStopped:
-			statuses[stopped]++
-		case ContainerStateRunning:
-			statuses[running]++
-		case ContainerStatePaused:
-			statuses[paused]++
-		case ContainerStateCreated, ContainerStateConfigured:
-			statuses[created]++
-		default:
-			statuses[errored]++
-		}
-	}
-
-	if statuses[running] > 0 {
-		return running, nil
-	} else if statuses[paused] == ctrNum {
-		return paused, nil
-	} else if statuses[stopped] == ctrNum {
-		return exited, nil
-	} else if statuses[stopped] > 0 {
-		return stopped, nil
-	} else if statuses[errored] > 0 {
-		return errored, nil
-	}
-	return created, nil
-}
-
 // Inspect returns a PodInspect struct to describe the pod
 func (p *Pod) Inspect() (*PodInspect, error) {
 	var (
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index df8b66996..58452716a 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -9,7 +9,7 @@ import (
 	"syscall"
 	"time"
 
-	"github.com/containers/libpod/cmd/podman/batchcontainer"
+	"github.com/containers/libpod/cmd/podman/shared"
 	"github.com/containers/libpod/cmd/podman/varlink"
 	"github.com/containers/libpod/libpod"
 	"github.com/containers/storage/pkg/archive"
@@ -26,12 +26,12 @@ func (i *LibpodAPI) ListContainers(call iopodman.VarlinkCall) error {
 	if err != nil {
 		return call.ReplyErrorOccurred(err.Error())
 	}
-	opts := batchcontainer.PsOptions{
+	opts := shared.PsOptions{
 		Namespace: true,
 		Size:      true,
 	}
 	for _, ctr := range containers {
-		batchInfo, err := batchcontainer.BatchContainerOp(ctr, opts)
+		batchInfo, err := shared.BatchContainerOp(ctr, opts)
 		if err != nil {
 			return call.ReplyErrorOccurred(err.Error())
 		}
@@ -47,11 +47,11 @@ func (i *LibpodAPI) GetContainer(call iopodman.VarlinkCall, name string) error {
 	if err != nil {
 		return call.ReplyContainerNotFound(name)
 	}
-	opts := batchcontainer.PsOptions{
+	opts := shared.PsOptions{
 		Namespace: true,
 		Size:      true,
 	}
-	batchInfo, err := batchcontainer.BatchContainerOp(ctr, opts)
+	batchInfo, err := shared.BatchContainerOp(ctr, opts)
 	if err != nil {
 		return call.ReplyErrorOccurred(err.Error())
 	}
@@ -68,7 +68,7 @@ func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) err
 	if err != nil {
 		return call.ReplyErrorOccurred(err.Error())
 	}
-	data, err := batchcontainer.GetCtrInspectInfo(ctr, inspectInfo)
+	data, err := shared.GetCtrInspectInfo(ctr, inspectInfo)
 	if err != nil {
 		return call.ReplyErrorOccurred(err.Error())
 	}
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index 272c348fc..98a622d8a 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -4,7 +4,7 @@ import (
 	"encoding/json"
 	"syscall"
 
-	"github.com/projectatomic/libpod/cmd/podman/batchcontainer"
+	"github.com/projectatomic/libpod/cmd/podman/shared"
 	"github.com/projectatomic/libpod/cmd/podman/varlink"
 	"github.com/projectatomic/libpod/libpod"
 )
@@ -40,7 +40,7 @@ func (i *LibpodAPI) ListPods(call iopodman.VarlinkCall) error {
 	if err != nil {
 		return call.ReplyErrorOccurred(err.Error())
 	}
-	opts := batchcontainer.PsOptions{}
+	opts := shared.PsOptions{}
 	for _, pod := range pods {
 		listPod, err := makeListPod(pod, opts)
 		if err != nil {
@@ -57,7 +57,7 @@ func (i *LibpodAPI) GetPod(call iopodman.VarlinkCall, name string) error {
 	if err != nil {
 		return call.ReplyPodNotFound(name)
 	}
-	opts := batchcontainer.PsOptions{}
+	opts := shared.PsOptions{}
 
 	listPod, err := makeListPod(pod, opts)
 	if err != nil {
diff --git a/pkg/varlinkapi/util.go b/pkg/varlinkapi/util.go
index 74afabd0f..e0b679934 100644
--- a/pkg/varlinkapi/util.go
+++ b/pkg/varlinkapi/util.go
@@ -5,7 +5,7 @@ import (
 	"strconv"
 	"time"
 
-	"github.com/containers/libpod/cmd/podman/batchcontainer"
+	"github.com/containers/libpod/cmd/podman/shared"
 	"github.com/containers/libpod/cmd/podman/varlink"
 	"github.com/containers/libpod/libpod"
 )
@@ -15,12 +15,12 @@ func getContext() context.Context {
 	return context.TODO()
 }
 
-func makeListContainer(containerID string, batchInfo batchcontainer.BatchContainerStruct) iopodman.ListContainerData {
+func makeListContainer(containerID string, batchInfo shared.BatchContainerStruct) iopodman.ListContainerData {
 	var (
 		mounts []iopodman.ContainerMount
 		ports  []iopodman.ContainerPortMappings
 	)
-	ns := batchcontainer.GetNamespaces(batchInfo.Pid)
+	ns := shared.GetNamespaces(batchInfo.Pid)
 
 	for _, mount := range batchInfo.ConConfig.Spec.Mounts {
 		m := iopodman.ContainerMount{
@@ -78,7 +78,7 @@ func makeListContainer(containerID string, batchInfo batchcontainer.BatchContain
 	return lc
 }
 
-func makeListPodContainers(containerID string, batchInfo batchcontainer.BatchContainerStruct) iopodman.ListPodContainerInfo {
+func makeListPodContainers(containerID string, batchInfo shared.BatchContainerStruct) iopodman.ListPodContainerInfo {
 	lc := iopodman.ListPodContainerInfo{
 		Id:     containerID,
 		Status: batchInfo.ConState.String(),
@@ -87,10 +87,10 @@ func makeListPodContainers(containerID string, batchInfo batchcontainer.BatchCon
 	return lc
 }
 
-func makeListPod(pod *libpod.Pod, batchInfo batchcontainer.PsOptions) (iopodman.ListPodData, error) {
+func makeListPod(pod *libpod.Pod, batchInfo shared.PsOptions) (iopodman.ListPodData, error) {
 	var listPodsContainers []iopodman.ListPodContainerInfo
 	var errPodData = iopodman.ListPodData{}
-	status, err := pod.Status()
+	status, err := shared.GetPodStatus(pod)
 	if err != nil {
 		return errPodData, err
 	}
@@ -99,7 +99,7 @@ func makeListPod(pod *libpod.Pod, batchInfo batchcontainer.PsOptions) (iopodman.
 		return errPodData, err
 	}
 	for _, ctr := range containers {
-		batchInfo, err := batchcontainer.BatchContainerOp(ctr, batchInfo)
+		batchInfo, err := shared.BatchContainerOp(ctr, batchInfo)
 		if err != nil {
 			return errPodData, err
 		}
-- 
cgit v1.2.3-54-g00ecf