summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_internal_linux.go27
-rw-r--r--libpod/events/journal_linux.go7
-rw-r--r--libpod/filters/containers.go239
-rw-r--r--libpod/filters/helpers.go20
-rw-r--r--libpod/filters/pods.go139
-rw-r--r--libpod/image/image.go2
-rw-r--r--libpod/image/prune.go23
-rw-r--r--libpod/image/utils.go3
-rw-r--r--libpod/networking_linux.go5
-rw-r--r--libpod/oci_conmon_exec_linux.go2
-rw-r--r--libpod/oci_conmon_linux.go28
-rw-r--r--libpod/runtime_ctr.go27
-rw-r--r--libpod/runtime_pod_infra_linux.go28
-rw-r--r--libpod/runtime_volume.go25
-rw-r--r--libpod/util.go9
-rw-r--r--libpod/volume.go14
16 files changed, 161 insertions, 437 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 05b149e03..cefe12209 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -529,14 +529,37 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
+ // Hostname handling:
+ // If we have a UTS namespace, set Hostname in the OCI spec.
+ // Set the HOSTNAME environment variable unless explicitly overridden by
+ // the user (already present in OCI spec). If we don't have a UTS ns,
+ // set it to the host's hostname instead.
+ hostname := c.Hostname()
+ foundUTS := false
for _, i := range c.config.Spec.Linux.Namespaces {
if i.Type == spec.UTSNamespace && i.Path == "" {
- hostname := c.Hostname()
+ foundUTS = true
g.SetHostname(hostname)
- g.AddProcessEnv("HOSTNAME", hostname)
break
}
}
+ if !foundUTS {
+ tmpHostname, err := os.Hostname()
+ if err != nil {
+ return nil, err
+ }
+ hostname = tmpHostname
+ }
+ needEnv := true
+ for _, checkEnv := range g.Config.Process.Env {
+ if strings.SplitN(checkEnv, "=", 2)[0] == "HOSTNAME" {
+ needEnv = false
+ break
+ }
+ }
+ if needEnv {
+ g.AddProcessEnv("HOSTNAME", hostname)
+ }
if c.config.UTSNsCtr != "" {
if err := c.addNamespaceContainer(&g, UTSNS, c.config.UTSNsCtr, spec.UTSNamespace); err != nil {
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index 71c638017..8b7e448b1 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -84,7 +84,11 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
if err != nil {
return err
}
-
+ defer func() {
+ if err := j.Close(); err != nil {
+ logrus.Errorf("Unable to close journal :%v", err)
+ }
+ }()
// match only podman journal entries
podmanJournal := sdjournal.Match{Field: "SYSLOG_IDENTIFIER", Value: "podman"}
if err := j.AddMatch(podmanJournal.String()); err != nil {
@@ -112,7 +116,6 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
if err != nil {
return errors.Wrap(err, "failed to get journal cursor")
}
-
for {
select {
case <-ctx.Done():
diff --git a/libpod/filters/containers.go b/libpod/filters/containers.go
deleted file mode 100644
index 505429de6..000000000
--- a/libpod/filters/containers.go
+++ /dev/null
@@ -1,239 +0,0 @@
-package lpfilters
-
-import (
- "strconv"
- "strings"
- "time"
-
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/pkg/timetype"
- "github.com/containers/podman/v2/pkg/util"
- "github.com/pkg/errors"
-)
-
-// GenerateContainerFilterFuncs return ContainerFilter functions based of filter.
-func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
- switch filter {
- case "id":
- // we only have to match one ID
- return func(c *libpod.Container) bool {
- return util.StringMatchRegexSlice(c.ID(), filterValues)
- }, nil
- case "label":
- // we have to match that all given labels exits on that container
- return func(c *libpod.Container) bool {
- labels := c.Labels()
- for _, filterValue := range filterValues {
- matched := false
- filterArray := strings.SplitN(filterValue, "=", 2)
- filterKey := filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
- for labelKey, labelValue := range labels {
- if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
- matched = true
- break
- }
- }
- if !matched {
- return false
- }
- }
- return true
- }, nil
- case "name":
- // we only have to match one name
- return func(c *libpod.Container) bool {
- return util.StringMatchRegexSlice(c.Name(), filterValues)
- }, nil
- case "exited":
- var exitCodes []int32
- for _, exitCode := range filterValues {
- ec, err := strconv.ParseInt(exitCode, 10, 32)
- if err != nil {
- return nil, errors.Wrapf(err, "exited code out of range %q", ec)
- }
- exitCodes = append(exitCodes, int32(ec))
- }
- return func(c *libpod.Container) bool {
- ec, exited, err := c.ExitCode()
- if err == nil && exited {
- for _, exitCode := range exitCodes {
- if ec == exitCode {
- return true
- }
- }
- }
- return false
- }, nil
- case "status":
- for _, filterValue := range filterValues {
- if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) {
- return nil, errors.Errorf("%s is not a valid status", filterValue)
- }
- }
- return func(c *libpod.Container) bool {
- status, err := c.State()
- if err != nil {
- return false
- }
- state := status.String()
- if status == define.ContainerStateConfigured {
- state = "created"
- } else if status == define.ContainerStateStopped {
- state = "exited"
- }
- for _, filterValue := range filterValues {
- if filterValue == "stopped" {
- filterValue = "exited"
- }
- if state == filterValue {
- return true
- }
- }
- return false
- }, nil
- case "ancestor":
- // This needs to refine to match docker
- // - ancestor=(<image-name>[:tag]|<image-id>| ⟨image@digest⟩) - containers created from an image or a descendant.
- return func(c *libpod.Container) bool {
- for _, filterValue := range filterValues {
- containerConfig := c.Config()
- if strings.Contains(containerConfig.RootfsImageID, filterValue) || strings.Contains(containerConfig.RootfsImageName, filterValue) {
- return true
- }
- }
- return false
- }, nil
- case "before":
- var createTime time.Time
- for _, filterValue := range filterValues {
- ctr, err := r.LookupContainer(filterValue)
- if err != nil {
- return nil, err
- }
- containerConfig := ctr.Config()
- if createTime.IsZero() || createTime.After(containerConfig.CreatedTime) {
- createTime = containerConfig.CreatedTime
- }
- }
- return func(c *libpod.Container) bool {
- cc := c.Config()
- return createTime.After(cc.CreatedTime)
- }, nil
- case "since":
- var createTime time.Time
- for _, filterValue := range filterValues {
- ctr, err := r.LookupContainer(filterValue)
- if err != nil {
- return nil, err
- }
- containerConfig := ctr.Config()
- if createTime.IsZero() || createTime.After(containerConfig.CreatedTime) {
- createTime = containerConfig.CreatedTime
- }
- }
- return func(c *libpod.Container) bool {
- cc := c.Config()
- return createTime.Before(cc.CreatedTime)
- }, nil
- case "volume":
- //- volume=(<volume-name>|<mount-point-destination>)
- return func(c *libpod.Container) bool {
- containerConfig := c.Config()
- var dest string
- for _, filterValue := range filterValues {
- arr := strings.SplitN(filterValue, ":", 2)
- source := arr[0]
- if len(arr) == 2 {
- dest = arr[1]
- }
- for _, mount := range containerConfig.Spec.Mounts {
- if dest != "" && (mount.Source == source && mount.Destination == dest) {
- return true
- }
- if dest == "" && mount.Source == source {
- return true
- }
- }
- for _, vname := range containerConfig.NamedVolumes {
- if dest != "" && (vname.Name == source && vname.Dest == dest) {
- return true
- }
- if dest == "" && vname.Name == source {
- return true
- }
- }
- }
- return false
- }, nil
- case "health":
- return func(c *libpod.Container) bool {
- hcStatus, err := c.HealthCheckStatus()
- if err != nil {
- return false
- }
- for _, filterValue := range filterValues {
- if hcStatus == filterValue {
- return true
- }
- }
- return false
- }, nil
- case "until":
- if len(filterValues) != 1 {
- return nil, errors.Errorf("specify exactly one timestamp for %s", filter)
- }
- ts, err := timetype.GetTimestamp(filterValues[0], time.Now())
- if err != nil {
- return nil, err
- }
- seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
- if err != nil {
- return nil, err
- }
- until := time.Unix(seconds, nanoseconds)
- return func(c *libpod.Container) bool {
- if !until.IsZero() && c.CreatedTime().After((until)) {
- return true
- }
- return false
- }, nil
- case "pod":
- var pods []*libpod.Pod
- for _, podNameOrID := range filterValues {
- p, err := r.LookupPod(podNameOrID)
- if err != nil {
- if errors.Cause(err) == define.ErrNoSuchPod {
- continue
- }
- return nil, err
- }
- pods = append(pods, p)
- }
- return func(c *libpod.Container) bool {
- // if no pods match, quick out
- if len(pods) < 1 {
- return false
- }
- // if the container has no pod id, quick out
- if len(c.PodID()) < 1 {
- return false
- }
- for _, p := range pods {
- // we already looked up by name or id, so id match
- // here is ok
- if p.ID() == c.PodID() {
- return true
- }
- }
- return false
- }, nil
-
- }
- return nil, errors.Errorf("%s is an invalid filter", filter)
-}
diff --git a/libpod/filters/helpers.go b/libpod/filters/helpers.go
deleted file mode 100644
index 859db3a9a..000000000
--- a/libpod/filters/helpers.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package lpfilters
-
-import (
- "net/url"
- "strings"
-
- "github.com/pkg/errors"
-)
-
-func ParseFilterArgumentsIntoFilters(filters []string) (url.Values, error) {
- parsedFilters := make(url.Values)
- for _, f := range filters {
- t := strings.SplitN(f, "=", 2)
- if len(t) < 2 {
- return parsedFilters, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
- }
- parsedFilters.Add(t[0], t[1])
- }
- return parsedFilters, nil
-}
diff --git a/libpod/filters/pods.go b/libpod/filters/pods.go
deleted file mode 100644
index 17b3f3ca9..000000000
--- a/libpod/filters/pods.go
+++ /dev/null
@@ -1,139 +0,0 @@
-package lpfilters
-
-import (
- "strconv"
- "strings"
-
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/pkg/util"
- "github.com/pkg/errors"
-)
-
-// GeneratePodFilterFunc takes a filter and filtervalue (key, value)
-// and generates a libpod function that can be used to filter
-// pods
-func GeneratePodFilterFunc(filter string, filterValues []string) (
- func(pod *libpod.Pod) bool, error) {
- switch filter {
- case "ctr-ids":
- return func(p *libpod.Pod) bool {
- ctrIds, err := p.AllContainersByID()
- if err != nil {
- return false
- }
- for _, id := range ctrIds {
- return util.StringMatchRegexSlice(id, filterValues)
- }
- return false
- }, nil
- case "ctr-names":
- return func(p *libpod.Pod) bool {
- ctrs, err := p.AllContainers()
- if err != nil {
- return false
- }
- for _, ctr := range ctrs {
- return util.StringMatchRegexSlice(ctr.Name(), filterValues)
- }
- return false
- }, nil
- case "ctr-number":
- return func(p *libpod.Pod) bool {
- ctrIds, err := p.AllContainersByID()
- if err != nil {
- return false
- }
- for _, filterValue := range filterValues {
- fVint, err2 := strconv.Atoi(filterValue)
- if err2 != nil {
- return false
- }
- if len(ctrIds) == fVint {
- return true
- }
- }
- return false
- }, nil
- case "ctr-status":
- for _, filterValue := range filterValues {
- if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) {
- return nil, errors.Errorf("%s is not a valid status", filterValue)
- }
- }
- return func(p *libpod.Pod) bool {
- ctrStatuses, err := p.Status()
- if err != nil {
- return false
- }
- for _, ctrStatus := range ctrStatuses {
- state := ctrStatus.String()
- if ctrStatus == define.ContainerStateConfigured {
- state = "created"
- } else if ctrStatus == define.ContainerStateStopped {
- state = "exited"
- }
- for _, filterValue := range filterValues {
- if filterValue == "stopped" {
- filterValue = "exited"
- }
- if state == filterValue {
- return true
- }
- }
- }
- return false
- }, nil
- case "id":
- return func(p *libpod.Pod) bool {
- return util.StringMatchRegexSlice(p.ID(), filterValues)
- }, nil
- case "name":
- return func(p *libpod.Pod) bool {
- return util.StringMatchRegexSlice(p.Name(), filterValues)
- }, nil
- case "status":
- for _, filterValue := range filterValues {
- if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) {
- return nil, errors.Errorf("%s is not a valid pod status", filterValue)
- }
- }
- return func(p *libpod.Pod) bool {
- status, err := p.GetPodStatus()
- if err != nil {
- return false
- }
- for _, filterValue := range filterValues {
- if strings.ToLower(status) == filterValue {
- return true
- }
- }
- return false
- }, nil
- case "label":
- return func(p *libpod.Pod) bool {
- labels := p.Labels()
- for _, filterValue := range filterValues {
- matched := false
- filterArray := strings.SplitN(filterValue, "=", 2)
- filterKey := filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
- for labelKey, labelValue := range labels {
- if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
- matched = true
- break
- }
- }
- if !matched {
- return false
- }
- }
- return true
- }, nil
- }
- return nil, errors.Errorf("%s is an invalid filter", filter)
-}
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 5c3f3b9e4..a9082b2c6 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -497,7 +497,7 @@ func (ir *Runtime) getLocalImage(inputName string) (string, *storage.Image, erro
return inputName, repoImage, nil
}
- return "", nil, errors.Wrapf(ErrNoSuchImage, err.Error())
+ return "", nil, err
}
// ID returns the image ID as a string
diff --git a/libpod/image/prune.go b/libpod/image/prune.go
index b38265a7e..3c06a89c2 100644
--- a/libpod/image/prune.go
+++ b/libpod/image/prune.go
@@ -6,6 +6,7 @@ import (
"time"
"github.com/containers/podman/v2/libpod/events"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/timetype"
"github.com/containers/storage"
"github.com/pkg/errors"
@@ -110,7 +111,8 @@ func (ir *Runtime) GetPruneImages(ctx context.Context, all bool, filterFuncs []I
// PruneImages prunes dangling and optionally all unused images from the local
// image store
-func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ([]string, error) {
+func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ([]*reports.PruneReport, error) {
+ preports := make([]*reports.PruneReport, 0)
filterFuncs := make([]ImageFilter, 0, len(filter))
for _, f := range filter {
filterSplit := strings.SplitN(f, "=", 2)
@@ -125,7 +127,6 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
filterFuncs = append(filterFuncs, generatedFunc)
}
- pruned := []string{}
prev := 0
for {
toPrune, err := ir.GetPruneImages(ctx, all, filterFuncs)
@@ -143,6 +144,13 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
if err != nil {
return nil, err
}
+ nameOrID := img.ID()
+ s, err := img.Size(ctx)
+ imgSize := *s
+ if err != nil {
+ logrus.Warnf("Failed to collect image size for: %s, %s", nameOrID, err)
+ imgSize = 0
+ }
if err := img.Remove(ctx, false); err != nil {
if errors.Cause(err) == storage.ErrImageUsedByContainer {
logrus.Warnf("Failed to prune image %s as it is in use: %v.\nA container associated with containers/storage (e.g., Buildah, CRI-O, etc.) maybe associated with this image.\nUsing the rmi command with the --force option will remove the container and image, but may cause failures for other dependent systems.", img.ID(), err)
@@ -151,13 +159,18 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
return nil, errors.Wrap(err, "failed to prune image")
}
defer img.newImageEvent(events.Prune)
- nameOrID := img.ID()
+
if len(repotags) > 0 {
nameOrID = repotags[0]
}
- pruned = append(pruned, nameOrID)
+
+ preports = append(preports, &reports.PruneReport{
+ Id: nameOrID,
+ Err: nil,
+ Size: uint64(imgSize),
+ })
}
}
- return pruned, nil
+ return preports, nil
}
diff --git a/libpod/image/utils.go b/libpod/image/utils.go
index 727c73a71..5e7fed5c6 100644
--- a/libpod/image/utils.go
+++ b/libpod/image/utils.go
@@ -45,7 +45,8 @@ func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, er
}
}
if len(candidates) == 0 {
- return nil, errors.Errorf("unable to find a name and tag match for %s in repotags", searchName)
+
+ return nil, errors.Wrapf(define.ErrNoSuchImage, "unable to find a name and tag match for %s in repotags", searchName)
}
// If more then one candidate and the candidates all have same name
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 863e82efd..be6867399 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -247,6 +247,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
func (r *Runtime) setupSlirp4netns(ctr *Container) error {
path := r.config.Engine.NetworkCmdPath
slirpOptions := r.config.Engine.NetworkCmdOptions
+ noPivotRoot := r.config.Engine.NoPivotRoot
if path == "" {
var err error
path, err = exec.LookPath("slirp4netns")
@@ -351,7 +352,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
if slirpFeatures.HasMTU {
cmdArgs = append(cmdArgs, "--mtu", "65520")
}
- if slirpFeatures.HasEnableSandbox {
+ if !noPivotRoot && slirpFeatures.HasEnableSandbox {
cmdArgs = append(cmdArgs, "--enable-sandbox")
}
if slirpFeatures.HasEnableSeccomp {
@@ -424,7 +425,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
}
// workaround for https://github.com/rootless-containers/slirp4netns/pull/153
- if slirpFeatures.HasEnableSandbox {
+ if !noPivotRoot && slirpFeatures.HasEnableSandbox {
cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWNS
cmd.SysProcAttr.Unshareflags = syscall.CLONE_NEWNS
}
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index f8e7020f7..4546acefb 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -387,7 +387,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
finalEnv = append(finalEnv, fmt.Sprintf("%s=%s", k, v))
}
- processFile, err := prepareProcessExec(c, options.Cmd, finalEnv, options.Terminal, options.Cwd, options.User, sessionID)
+ processFile, err := prepareProcessExec(c, options, finalEnv, sessionID)
if err != nil {
return nil, nil, err
}
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index c99086b33..e7cb5a802 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -193,6 +193,11 @@ func hasCurrentUserMapped(ctr *Container) bool {
// CreateContainer creates a container.
func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) error {
+ // always make the run dir accessible to the current user so that the PID files can be read without
+ // being in the rootless user namespace.
+ if err := makeAccessible(ctr.state.RunDir, 0, 0); err != nil {
+ return err
+ }
if !hasCurrentUserMapped(ctr) {
for _, i := range []string{ctr.state.RunDir, ctr.runtime.config.Engine.TmpDir, ctr.config.StaticDir, ctr.state.Mountpoint, ctr.runtime.config.Engine.VolumePath} {
if err := makeAccessible(i, ctr.RootUID(), ctr.RootGID()); err != nil {
@@ -1185,26 +1190,36 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
// prepareProcessExec returns the path of the process.json used in runc exec -p
// caller is responsible to close the returned *os.File if needed.
-func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, sessionID string) (*os.File, error) {
+func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessionID string) (*os.File, error) {
f, err := ioutil.TempFile(c.execBundlePath(sessionID), "exec-process-")
if err != nil {
return nil, err
}
- pspec := c.config.Spec.Process
+ pspec := new(spec.Process)
+ if err := JSONDeepCopy(c.config.Spec.Process, pspec); err != nil {
+ return nil, err
+ }
pspec.SelinuxLabel = c.config.ProcessLabel
- pspec.Args = cmd
+ pspec.Args = options.Cmd
+ for _, cap := range options.CapAdd {
+ pspec.Capabilities.Bounding = append(pspec.Capabilities.Bounding, cap)
+ pspec.Capabilities.Effective = append(pspec.Capabilities.Effective, cap)
+ pspec.Capabilities.Inheritable = append(pspec.Capabilities.Inheritable, cap)
+ pspec.Capabilities.Permitted = append(pspec.Capabilities.Permitted, cap)
+ pspec.Capabilities.Ambient = append(pspec.Capabilities.Ambient, cap)
+ }
// We need to default this to false else it will inherit terminal as true
// from the container.
pspec.Terminal = false
- if tty {
+ if options.Terminal {
pspec.Terminal = true
}
if len(env) > 0 {
pspec.Env = append(pspec.Env, env...)
}
- if cwd != "" {
- pspec.Cwd = cwd
+ if options.Cwd != "" {
+ pspec.Cwd = options.Cwd
}
@@ -1212,6 +1227,7 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se
var sgids []uint32
// if the user is empty, we should inherit the user that the container is currently running with
+ user := options.User
if user == "" {
user = c.config.User
addGroups = c.config.Groups
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 14b537ca2..f22e48746 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/podman/v2/libpod/events"
"github.com/containers/podman/v2/libpod/shutdown"
"github.com/containers/podman/v2/pkg/cgroups"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/rootless"
"github.com/containers/storage"
"github.com/containers/storage/pkg/stringid"
@@ -884,9 +885,8 @@ func (r *Runtime) GetExecSessionContainer(id string) (*Container, error) {
// PruneContainers removes stopped and exited containers from localstorage. A set of optional filters
// can be provided to be more granular.
-func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) (map[string]int64, map[string]error, error) {
- pruneErrors := make(map[string]error)
- prunedContainers := make(map[string]int64)
+func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) ([]*reports.PruneReport, error) {
+ preports := make([]*reports.PruneReport, 0)
// We add getting the exited and stopped containers via a filter
containerStateFilter := func(c *Container) bool {
if c.PodID() != "" {
@@ -906,23 +906,28 @@ func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) (map[string]int
filterFuncs = append(filterFuncs, containerStateFilter)
delContainers, err := r.GetContainers(filterFuncs...)
if err != nil {
- return nil, nil, err
+ return nil, err
}
for _, c := range delContainers {
- ctr := c
- size, err := ctr.RWSize()
+ report := new(reports.PruneReport)
+ report.Id = c.ID()
+ report.Err = nil
+ report.Size = 0
+ size, err := c.RWSize()
if err != nil {
- pruneErrors[ctr.ID()] = err
+ report.Err = err
+ preports = append(preports, report)
continue
}
- err = r.RemoveContainer(context.Background(), ctr, false, false)
+ err = r.RemoveContainer(context.Background(), c, false, false)
if err != nil {
- pruneErrors[ctr.ID()] = err
+ report.Err = err
} else {
- prunedContainers[ctr.ID()] = size
+ report.Size = (uint64)(size)
}
+ preports = append(preports, report)
}
- return prunedContainers, pruneErrors, nil
+ return preports, nil
}
// MountStorageContainer mounts the storage container's root filesystem
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index 3e4185db1..dd957527d 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -159,6 +159,34 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
g.AddMount(devPts)
}
+ // Add default sysctls from containers.conf
+ defaultSysctls, err := util.ValidateSysctls(r.config.Sysctls())
+ if err != nil {
+ return nil, err
+ }
+ for sysctlKey, sysctlVal := range defaultSysctls {
+ // Ignore mqueue sysctls if not sharing IPC
+ if !p.config.UsePodIPC && strings.HasPrefix(sysctlKey, "fs.mqueue.") {
+ logrus.Infof("Sysctl %s=%s ignored in containers.conf, since IPC Namespace for pod is unused", sysctlKey, sysctlVal)
+
+ continue
+ }
+
+ // Ignore net sysctls if host network or not sharing network
+ if (p.config.InfraContainer.HostNetwork || !p.config.UsePodNet) && strings.HasPrefix(sysctlKey, "net.") {
+ logrus.Infof("Sysctl %s=%s ignored in containers.conf, since Network Namespace for pod is unused", sysctlKey, sysctlVal)
+ continue
+ }
+
+ // Ignore uts sysctls if not sharing UTS
+ if !p.config.UsePodUTS && (strings.HasPrefix(sysctlKey, "kernel.domainname") || strings.HasPrefix(sysctlKey, "kernel.hostname")) {
+ logrus.Infof("Sysctl %s=%s ignored in containers.conf, since UTS Namespace for pod is unused", sysctlKey, sysctlVal)
+ continue
+ }
+
+ g.AddLinuxSysctl(sysctlKey, sysctlVal)
+ }
+
containerName := p.ID()[:IDTruncLength] + "-infra"
options = append(options, r.WithPod(p))
options = append(options, WithRootFSFromImage(imgID, imgName, rawImageName))
diff --git a/libpod/runtime_volume.go b/libpod/runtime_volume.go
index 10c32a119..9d985f905 100644
--- a/libpod/runtime_volume.go
+++ b/libpod/runtime_volume.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
+ "github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/pkg/errors"
)
@@ -133,22 +134,32 @@ func (r *Runtime) GetAllVolumes() ([]*Volume, error) {
}
// PruneVolumes removes unused volumes from the system
-func (r *Runtime) PruneVolumes(ctx context.Context, filterFuncs []VolumeFilter) (map[string]error, error) {
- reports := make(map[string]error)
+func (r *Runtime) PruneVolumes(ctx context.Context, filterFuncs []VolumeFilter) ([]*reports.PruneReport, error) {
+ preports := make([]*reports.PruneReport, 0)
vols, err := r.Volumes(filterFuncs...)
if err != nil {
return nil, err
}
for _, vol := range vols {
+ report := new(reports.PruneReport)
+ volSize, err := vol.Size()
+ if err != nil {
+ volSize = 0
+ }
+ report.Size = volSize
+ report.Id = vol.Name()
if err := r.RemoveVolume(ctx, vol, false); err != nil {
if errors.Cause(err) != define.ErrVolumeBeingUsed && errors.Cause(err) != define.ErrVolumeRemoved {
- reports[vol.Name()] = err
+ report.Err = err
+ } else {
+ // We didn't remove the volume for some reason
+ continue
}
- continue
+ } else {
+ vol.newVolumeEvent(events.Prune)
}
- vol.newVolumeEvent(events.Prune)
- reports[vol.Name()] = nil
+ preports = append(preports, report)
}
- return reports, nil
+ return preports, nil
}
diff --git a/libpod/util.go b/libpod/util.go
index 8faf665e7..bf9bf2542 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -153,6 +153,10 @@ func queryPackageVersion(cmdArg ...string) string {
return strings.Trim(output, "\n")
}
+func equeryVersion(path string) string {
+ return queryPackageVersion("/usr/bin/equery", "b", path)
+}
+
func pacmanVersion(path string) string {
return queryPackageVersion("/usr/bin/pacman", "-Qo", path)
}
@@ -172,7 +176,10 @@ func packageVersion(program string) string {
if out := dpkgVersion(program); out != unknownPackage {
return out
}
- return pacmanVersion(program)
+ if out := pacmanVersion(program); out != unknownPackage {
+ return out
+ }
+ return equeryVersion(program)
}
func programVersion(mountProgram string) (string, error) {
diff --git a/libpod/volume.go b/libpod/volume.go
index 0535bf4db..ed08d375f 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -1,6 +1,8 @@
package libpod
import (
+ "os"
+ "path/filepath"
"time"
"github.com/containers/podman/v2/libpod/define"
@@ -79,6 +81,18 @@ func (v *Volume) Name() string {
return v.config.Name
}
+// Returns the size on disk of volume
+func (v *Volume) Size() (uint64, error) {
+ var size uint64
+ err := filepath.Walk(v.config.MountPoint, func(path string, info os.FileInfo, err error) error {
+ if err == nil && !info.IsDir() {
+ size += (uint64)(info.Size())
+ }
+ return err
+ })
+ return size, err
+}
+
// Driver retrieves the volume's driver.
func (v *Volume) Driver() string {
return v.config.Driver