diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_commit.go | 2 | ||||
-rw-r--r-- | libpod/container_inspect.go | 3 | ||||
-rw-r--r-- | libpod/define/podstate.go | 19 | ||||
-rw-r--r-- | libpod/image/config.go | 6 | ||||
-rw-r--r-- | libpod/image/image.go | 12 | ||||
-rw-r--r-- | libpod/image/parts.go | 2 | ||||
-rw-r--r-- | libpod/options.go | 11 | ||||
-rw-r--r-- | libpod/pod_status.go | 59 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 47 | ||||
-rw-r--r-- | libpod/runtime_pod.go | 28 | ||||
-rw-r--r-- | libpod/runtime_pod_linux.go | 2 | ||||
-rw-r--r-- | libpod/volume.go | 14 | ||||
-rw-r--r-- | libpod/volume_inspect.go | 10 |
13 files changed, 189 insertions, 26 deletions
diff --git a/libpod/container_commit.go b/libpod/container_commit.go index ccc23621e..fa6e95b38 100644 --- a/libpod/container_commit.go +++ b/libpod/container_commit.go @@ -137,7 +137,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai if err != nil { return nil, errors.Wrapf(err, "volume %s used in container %s has been removed", v.Name, c.ID()) } - if vol.IsCtrSpecific() { + if vol.Anonymous() { importBuilder.AddVolume(v.Dest) } } diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 01f2d93bd..641bc8a91 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -1014,6 +1014,9 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named hostConfig.ShmSize = c.config.ShmSize hostConfig.Runtime = "oci" + // Default CPUShares is 1024, but we may overwrite below. + hostConfig.CpuShares = 1024 + // This is very expensive to initialize. // So we don't want to initialize it unless we absolutely have to - IE, // there are things that require a major:minor to path translation. diff --git a/libpod/define/podstate.go b/libpod/define/podstate.go new file mode 100644 index 000000000..2b59aabfb --- /dev/null +++ b/libpod/define/podstate.go @@ -0,0 +1,19 @@ +package define + +const ( + // PodStateCreated indicates the pod is created but has not been started + PodStateCreated = "Created" + // PodStateErrored indicates the pod is in an errored state where + // information about it can no longer be retrieved + PodStateErrored = "Error" + // PodStateExited indicates the pod ran but has been stopped + PodStateExited = "Exited" + // PodStatePaused indicates the pod has been paused + PodStatePaused = "Paused" + // PodStateRunning indicates that one or more of the containers in + // the pod is running + PodStateRunning = "Running" + // PodStateStopped indicates all of the containers belonging to the pod + // are stopped. + PodStateStopped = "Stopped" +) diff --git a/libpod/image/config.go b/libpod/image/config.go index bb84175a3..efd83d343 100644 --- a/libpod/image/config.go +++ b/libpod/image/config.go @@ -1,5 +1,11 @@ package image +const ( + // LatestTag describes the tag used to refer to the latest version + // of an image + LatestTag = "latest" +) + // ImageDeleteResponse is the response for removing an image from storage and containers // what was untagged vs actually removed type ImageDeleteResponse struct { //nolint diff --git a/libpod/image/image.go b/libpod/image/image.go index 6ea49e2a9..355249b12 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -831,7 +831,8 @@ func (i *Image) History(ctx context.Context) ([]*History, error) { id := "<missing>" if x == numHistories { id = i.ID() - } else if layer != nil { + } + if layer != nil { if !oci.History[x].EmptyLayer { size = layer.UncompressedSize } @@ -1012,6 +1013,15 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { History: ociv1Img.History, NamesHistory: i.NamesHistory(), } + if manifestType == manifest.DockerV2Schema2MediaType { + hc, err := i.GetHealthCheck(ctx) + if err != nil { + return nil, err + } + if hc != nil { + data.HealthCheck = hc + } + } return data, nil } diff --git a/libpod/image/parts.go b/libpod/image/parts.go index d4677f935..d6c98783b 100644 --- a/libpod/image/parts.go +++ b/libpod/image/parts.go @@ -67,7 +67,7 @@ func (ip *imageParts) suspiciousRefNameTagValuesForSearch() (string, string, str } else if _, hasDigest := ip.unnormalizedRef.(reference.Digested); hasDigest { tag = "none" } else { - tag = "latest" + tag = LatestTag } return registry, imageName, tag } diff --git a/libpod/options.go b/libpod/options.go index 593037382..923e7292c 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1546,17 +1546,16 @@ func WithVolumeGID(gid int) VolumeCreateOption { } } -// withSetCtrSpecific sets a bool notifying libpod that a volume was created -// specifically for a container. -// These volumes will be removed when the container is removed and volumes are -// also specified for removal. -func withSetCtrSpecific() VolumeCreateOption { +// withSetAnon sets a bool notifying libpod that this volume is anonymous and +// should be removed when containers using it are removed and volumes are +// specified for removal. +func withSetAnon() VolumeCreateOption { return func(volume *Volume) error { if volume.valid { return define.ErrVolumeFinalized } - volume.config.IsCtrSpecific = true + volume.config.IsAnon = true return nil } diff --git a/libpod/pod_status.go b/libpod/pod_status.go new file mode 100644 index 000000000..3a44c4457 --- /dev/null +++ b/libpod/pod_status.go @@ -0,0 +1,59 @@ +package libpod + +import "github.com/containers/libpod/libpod/define" + +// 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 (p *Pod) GetPodStatus() (string, error) { + ctrStatuses, err := p.Status() + if err != nil { + return define.PodStateErrored, err + } + return CreatePodStatusResults(ctrStatuses) +} + +func CreatePodStatusResults(ctrStatuses map[string]define.ContainerStatus) (string, error) { + ctrNum := len(ctrStatuses) + if ctrNum == 0 { + return define.PodStateCreated, nil + } + statuses := map[string]int{ + define.PodStateStopped: 0, + define.PodStateRunning: 0, + define.PodStatePaused: 0, + define.PodStateCreated: 0, + define.PodStateErrored: 0, + } + for _, ctrStatus := range ctrStatuses { + switch ctrStatus { + case define.ContainerStateExited: + fallthrough + case define.ContainerStateStopped: + statuses[define.PodStateStopped]++ + case define.ContainerStateRunning: + statuses[define.PodStateRunning]++ + case define.ContainerStatePaused: + statuses[define.PodStatePaused]++ + case define.ContainerStateCreated, define.ContainerStateConfigured: + statuses[define.PodStateCreated]++ + default: + statuses[define.PodStateErrored]++ + } + } + + switch { + case statuses[define.PodStateRunning] > 0: + return define.PodStateRunning, nil + case statuses[define.PodStatePaused] == ctrNum: + return define.PodStatePaused, nil + case statuses[define.PodStateStopped] == ctrNum: + return define.PodStateExited, nil + case statuses[define.PodStateStopped] > 0: + return define.PodStateStopped, nil + case statuses[define.PodStateErrored] > 0: + return define.PodStateErrored, nil + default: + return define.PodStateCreated, nil + } +} diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index de7cfd3b8..3ad09f27c 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -319,7 +319,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (c *Contai // The volume does not exist, so we need to create it. volOptions := []VolumeCreateOption{WithVolumeName(vol.Name), WithVolumeUID(ctr.RootUID()), WithVolumeGID(ctr.RootGID())} if isAnonymous { - volOptions = append(volOptions, withSetCtrSpecific()) + volOptions = append(volOptions, withSetAnon()) } newVol, err := r.newVolume(ctx, volOptions...) if err != nil { @@ -569,7 +569,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool, for _, v := range c.config.NamedVolumes { if volume, err := runtime.state.Volume(v.Name); err == nil { - if !volume.IsCtrSpecific() { + if !volume.Anonymous() { continue } if err := runtime.removeVolume(ctx, volume, false); err != nil && errors.Cause(err) != define.ErrNoSuchVolume { @@ -707,7 +707,7 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol for _, v := range c.config.NamedVolumes { if volume, err := r.state.Volume(v.Name); err == nil { - if !volume.IsCtrSpecific() { + if !volume.Anonymous() { continue } if err := r.removeVolume(ctx, volume, false); err != nil && err != define.ErrNoSuchVolume && err != define.ErrVolumeBeingUsed { @@ -836,3 +836,44 @@ func (r *Runtime) GetLatestContainer() (*Container, error) { } return ctrs[lastCreatedIndex], nil } + +// 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) + // We add getting the exited and stopped containers via a filter + containerStateFilter := func(c *Container) bool { + if c.PodID() != "" { + return false + } + state, err := c.State() + if err != nil { + logrus.Error(err) + return false + } + if state == define.ContainerStateStopped || state == define.ContainerStateExited { + return true + } + return false + } + filterFuncs = append(filterFuncs, containerStateFilter) + delContainers, err := r.GetContainers(filterFuncs...) + if err != nil { + return nil, nil, err + } + for _, c := range delContainers { + ctr := c + size, err := ctr.RWSize() + if err != nil { + pruneErrors[ctr.ID()] = err + continue + } + err = r.RemoveContainer(context.Background(), ctr, false, false) + pruneErrors[ctr.ID()] = err + if err != nil { + prunedContainers[ctr.ID()] = size + } + } + return prunedContainers, pruneErrors, nil +} diff --git a/libpod/runtime_pod.go b/libpod/runtime_pod.go index 66f9b10c9..e1dc31391 100644 --- a/libpod/runtime_pod.go +++ b/libpod/runtime_pod.go @@ -182,3 +182,31 @@ func (r *Runtime) GetRunningPods() ([]*Pod, error) { } return runningPods, nil } + +// PrunePods removes unused pods and their containers from local storage. +// If force is given, then running pods are also included in the pruning. +func (r *Runtime) PrunePods() (map[string]error, error) { + response := make(map[string]error) + states := []string{define.PodStateStopped, define.PodStateExited} + filterFunc := func(p *Pod) bool { + state, _ := p.GetPodStatus() + for _, status := range states { + if state == status { + return true + } + } + return false + } + pods, err := r.Pods(filterFunc) + if err != nil { + return nil, err + } + if len(pods) < 1 { + return response, nil + } + for _, pod := range pods { + err := r.removePod(context.TODO(), pod, true, false) + response[pod.ID()] = err + } + return response, nil +} diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 450c64d24..5b0111b85 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -261,7 +261,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) logrus.Errorf("Error retrieving volume %s: %v", volName, err) continue } - if !volume.IsCtrSpecific() { + if !volume.Anonymous() { continue } if err := r.removeVolume(ctx, volume, false); err != nil { diff --git a/libpod/volume.go b/libpod/volume.go index c4771bbb8..1ffed872e 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -38,9 +38,8 @@ type VolumeConfig struct { // a list of mount options. For other drivers, they are passed to the // volume driver handling the volume. Options map[string]string `json:"volumeOptions,omitempty"` - // Whether this volume was created for a specific container and will be - // removed with it. - IsCtrSpecific bool `json:"ctrSpecific"` + // Whether this volume is anonymous (will be removed on container exit) + IsAnon bool `json:"isAnon"` // UID the volume will be created as. UID int `json:"uid"` // GID the volume will be created as. @@ -106,11 +105,10 @@ func (v *Volume) Options() map[string]string { return options } -// IsCtrSpecific returns whether this volume was created specifically for a -// given container. Images with this set to true will be removed when the -// container is removed with the Volumes parameter set to true. -func (v *Volume) IsCtrSpecific() bool { - return v.config.IsCtrSpecific +// Anonymous returns whether this volume is anonymous. Anonymous volumes were +// created with a container, and will be removed when that container is removed. +func (v *Volume) Anonymous() bool { + return v.config.IsAnon } // UID returns the UID the volume will be created as. diff --git a/libpod/volume_inspect.go b/libpod/volume_inspect.go index c333b8961..136f9da5e 100644 --- a/libpod/volume_inspect.go +++ b/libpod/volume_inspect.go @@ -37,10 +37,10 @@ type InspectVolumeData struct { UID int `json:"UID,omitempty"` // GID is the GID that the volume was created with. GID int `json:"GID,omitempty"` - // ContainerSpecific indicates that the volume was created as part of a - // specific container, and will be removed when that container is - // removed. - ContainerSpecific bool `json:"ContainerSpecific,omitempty"` + // Anonymous indicates that the volume was created as an anonymous + // volume for a specific container, and will be be removed when any + // container using it is removed. + Anonymous bool `json:"Anonymous,omitempty"` } // Inspect provides detailed information about the configuration of the given @@ -67,7 +67,7 @@ func (v *Volume) Inspect() (*InspectVolumeData, error) { } data.UID = v.config.UID data.GID = v.config.GID - data.ContainerSpecific = v.config.IsCtrSpecific + data.Anonymous = v.config.IsAnon return data, nil } |