diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal_linux.go | 27 | ||||
-rw-r--r-- | libpod/events/journal_linux.go | 7 | ||||
-rw-r--r-- | libpod/filters/containers.go | 239 | ||||
-rw-r--r-- | libpod/filters/helpers.go | 20 | ||||
-rw-r--r-- | libpod/filters/pods.go | 139 | ||||
-rw-r--r-- | libpod/image/image.go | 2 | ||||
-rw-r--r-- | libpod/image/prune.go | 23 | ||||
-rw-r--r-- | libpod/image/utils.go | 3 | ||||
-rw-r--r-- | libpod/networking_linux.go | 5 | ||||
-rw-r--r-- | libpod/oci_conmon_exec_linux.go | 2 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 28 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 27 | ||||
-rw-r--r-- | libpod/runtime_pod_infra_linux.go | 28 | ||||
-rw-r--r-- | libpod/runtime_volume.go | 25 | ||||
-rw-r--r-- | libpod/util.go | 9 | ||||
-rw-r--r-- | libpod/volume.go | 14 |
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 |