diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_top.go | 135 | ||||
-rw-r--r-- | libpod/container_top_linux.go | 30 | ||||
-rw-r--r-- | libpod/container_top_unsupported.go | 21 |
3 files changed, 51 insertions, 135 deletions
diff --git a/libpod/container_top.go b/libpod/container_top.go deleted file mode 100644 index f5d314d49..000000000 --- a/libpod/container_top.go +++ /dev/null @@ -1,135 +0,0 @@ -package libpod - -import ( - "io/ioutil" - "path/filepath" - "strings" - - "github.com/pkg/errors" - "github.com/projectatomic/libpod/pkg/util" - "github.com/projectatomic/libpod/utils" - "github.com/sirupsen/logrus" -) - -// GetContainerPids reads sysfs to obtain the pids associated with the container's cgroup -// and uses locking -func (c *Container) GetContainerPids() ([]string, error) { - if !c.batched { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return []string{}, errors.Wrapf(err, "error updating container %s state", c.ID()) - } - } - return c.getContainerPids() -} - -// Gets the pids for a container without locking. should only be called from a func where -// locking has already been established. -func (c *Container) getContainerPids() ([]string, error) { - cgroupPath, err := c.CGroupPath() - if err != nil { - return nil, err - } - - taskFile := filepath.Join("/sys/fs/cgroup/pids", cgroupPath, "tasks") - - logrus.Debug("reading pids from ", taskFile) - - content, err := ioutil.ReadFile(taskFile) - if err != nil { - return []string{}, errors.Wrapf(err, "unable to read pids from %s", taskFile) - } - return strings.Fields(string(content)), nil -} - -// GetContainerPidInformation calls ps with the appropriate options and returns -// the results as a string and the container's PIDs as a []string. Note that -// the ps output columns of each string are separated by a '\t\'. Currently, -// the args argument is overwriten with []string{"-ef"} until there is a -// portable library for ps-1 or to parse the procFS to extract all data. -func (c *Container) GetContainerPidInformation(args []string) ([]string, error) { - // XXX(ps-issue): args is overwriten with []{"-ef"} as the ps-1 tool - // doesn't support a generic way of splitting columns, rendering its - // output hard to parse. Docker first deterimes the number of columns - // and merges all exceeding ones into the last one. We believe that - // writing a go library which parses procFS in a ps-compatible way may - // be more beneficial in the long run. Until then, args will be - // ignored. - args = []string{"-ef"} - - if !c.batched { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return []string{}, errors.Wrapf(err, "error updating container %s state", c.ID()) - } - } - pids, err := c.getContainerPids() - if err != nil { - return []string{}, errors.Wrapf(err, "unable to obtain pids for ", c.ID()) - } - args = append(args, "-p", strings.Join(pids, ",")) - logrus.Debug("Executing: ", strings.Join(args, " ")) - results, err := utils.ExecCmd("ps", args...) - if err != nil { - return []string{}, errors.Wrapf(err, "unable to obtain information about pids") - } - - filteredOutput, err := filterPids(results, pids) - if err != nil { - return []string{}, err - } - return filteredOutput, nil -} - -func filterPids(psOutput string, pids []string) ([]string, error) { - var output []string - results := strings.Split(psOutput, "\n") - // The headers are in the first line of the results - headers := fieldsASCII(results[0]) - // We need to make sure PID in headers, so that we can filter - // Pids that don't belong. - - // append the headers back in - output = append(output, strings.Join(headers, "\t")) - - pidIndex := -1 - for i, header := range headers { - if header == "PID" { - pidIndex = i - } - } - if pidIndex == -1 { - return []string{}, errors.Errorf("unable to find PID field in ps output. try a different set of ps arguments") - } - for _, l := range results[1:] { - if l == "" { - continue - } - cols := fieldsASCII(l) - pid := cols[pidIndex] - if util.StringInSlice(pid, pids) { - // XXX(ps-issue): Strip cols down to the header's size - // and merge exceeding fields. This is required to - // "merge" the overhanging CMD entries which can - // contain white spaces. - out := cols[:len(headers)-1] - out = append(out, strings.Join(cols[len(headers)-1:], " ")) - output = append(output, strings.Join(out, "\t")) - } - } - return output, nil -} - -// Detects ascii whitespaces -func fieldsASCII(s string) []string { - fn := func(r rune) bool { - switch r { - case '\t', '\n', '\f', '\r', ' ': - return true - } - return false - } - return strings.FieldsFunc(s, fn) -} diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go new file mode 100644 index 000000000..450130add --- /dev/null +++ b/libpod/container_top_linux.go @@ -0,0 +1,30 @@ +// +build linux + +package libpod + +import ( + "strconv" + "strings" + + "github.com/containers/psgo/ps" +) + +// GetContainerPidInformation returns process-related data of all processes in +// the container. The output data can be controlled via the `descriptors` +// argument which expects format descriptors and supports all AIXformat +// descriptors of ps (1) plus some additional ones to for instance inspect the +// set of effective capabilities. Eeach element in the returned string slice +// is a tab-separated string. +// +// For more details, please refer to github.com/containers/psgo. +func (c *Container) GetContainerPidInformation(descriptors []string) ([]string, error) { + pid := strconv.Itoa(c.state.PID) + format := strings.Join(descriptors, ",") + return ps.JoinNamespaceAndProcessInfo(pid, format) +} + +// GetContainerPidInformationDescriptors returns a string slice of all supported +// format descriptors of GetContainerPidInformation. +func GetContainerPidInformationDescriptors() ([]string, error) { + return ps.ListDescriptors(), nil +} diff --git a/libpod/container_top_unsupported.go b/libpod/container_top_unsupported.go new file mode 100644 index 000000000..1e6fb836d --- /dev/null +++ b/libpod/container_top_unsupported.go @@ -0,0 +1,21 @@ +// +build !linux + +package libpod + +// GetContainerPidInformation returns process-related data of all processes in +// the container. The output data can be controlled via the `descriptors` +// argument which expects format descriptors and supports all AIXformat +// descriptors of ps (1) plus some additional ones to for instance inspect the +// set of effective capabilities. Eeach element in the returned string slice +// is a tab-separated string. +// +// For more details, please refer to github.com/containers/psgo. +func (c *Container) GetContainerPidInformation(descriptors []string) ([]string, error) { + return nil, ErrNotImplemented +} + +// GetContainerPidInformationDescriptors returns a string slice of all supported +// format descriptors of GetContainerPidInformation. +func GetContainerPidInformationDescriptors() ([]string, error) { + return nil, ErrNotImplemented +} |