summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_exec.go2
-rw-r--r--libpod/container_internal.go2
-rw-r--r--libpod/define/errors.go4
-rw-r--r--libpod/define/pod_inspect.go2
-rw-r--r--libpod/image/df.go126
-rw-r--r--libpod/info.go2
-rw-r--r--libpod/oci_conmon_linux.go25
-rw-r--r--libpod/oci_conmon_unsupported.go2
-rw-r--r--libpod/options.go13
-rw-r--r--libpod/runtime.go5
10 files changed, 166 insertions, 17 deletions
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index 2a852ab81..f5f54c7cc 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -629,7 +629,7 @@ func (c *Container) ExecRemove(sessionID string, force bool) error {
logrus.Infof("Removing container %s exec session %s", c.ID(), session.ID())
- // Update status of exec session if running, so we cna check if it
+ // Update status of exec session if running, so we can check if it
// stopped in the meantime.
if session.State == define.ExecStateRunning {
running, err := c.ociRuntime.ExecUpdateStatus(c, session.ID())
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 5a0a0edfa..0514fb46f 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1269,7 +1269,7 @@ func (c *Container) stop(timeout uint) error {
c.state.StoppedByUser = true
if !conmonAlive {
- // Conmon is dead, so we can't epect an exit code.
+ // Conmon is dead, so we can't expect an exit code.
c.state.ExitCode = -1
c.state.FinishedTime = time.Now()
c.state.State = define.ContainerStateStopped
diff --git a/libpod/define/errors.go b/libpod/define/errors.go
index 7714ebbf0..b3f6483d1 100644
--- a/libpod/define/errors.go
+++ b/libpod/define/errors.go
@@ -163,6 +163,6 @@ var (
ErrNetworkOnPodContainer = errors.New("network cannot be configured when it is shared with a pod")
// ErrStoreNotInitialized indicates that the container storage was never
- // initilized.
- ErrStoreNotInitialized = errors.New("the container storage was never initilized")
+ // initialized.
+ ErrStoreNotInitialized = errors.New("the container storage was never initialized")
)
diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go
index 634cbb728..60e19fe05 100644
--- a/libpod/define/pod_inspect.go
+++ b/libpod/define/pod_inspect.go
@@ -87,7 +87,7 @@ type InspectPodInfraConfig struct {
// HostAdd adds a number of hosts to the infra container's resolv.conf
// which will be shared with the rest of the pod.
HostAdd []string
- // Networks is a list of CNI networks te pod will join.
+ // Networks is a list of CNI networks the pod will join.
Networks []string
}
diff --git a/libpod/image/df.go b/libpod/image/df.go
new file mode 100644
index 000000000..84cf7af9e
--- /dev/null
+++ b/libpod/image/df.go
@@ -0,0 +1,126 @@
+package image
+
+import (
+ "context"
+ "time"
+
+ "github.com/containers/image/v5/docker/reference"
+)
+
+// DiskUsageStat gives disk-usage statistics for a specific image.
+type DiskUsageStat struct {
+ // ID of the image.
+ ID string
+ // Repository of the first recorded name of the image.
+ Repository string
+ // Tag of the first recorded name of the image.
+ Tag string
+ // Created is the creation time of the image.
+ Created time.Time
+ // SharedSize is the amount of space shared with another image.
+ SharedSize uint64
+ // UniqueSize is the amount of space used only by this image.
+ UniqueSize uint64
+ // Size is the total size of the image (i.e., the sum of the shared and
+ // unique size).
+ Size uint64
+ // Number of containers using the image.
+ Containers int
+}
+
+// DiskUsage returns disk-usage statistics for the specified slice of images.
+func (ir *Runtime) DiskUsage(ctx context.Context, images []*Image) ([]DiskUsageStat, error) {
+ stats := make([]DiskUsageStat, len(images))
+
+ // Build a layerTree to quickly compute (and cache!) parent/child
+ // relations.
+ tree, err := ir.layerTree()
+ if err != nil {
+ return nil, err
+ }
+
+ // Calculate the stats for each image.
+ for i, img := range images {
+ stat, err := diskUsageForImage(ctx, img, tree)
+ if err != nil {
+ return nil, err
+ }
+ stats[i] = *stat
+ }
+
+ return stats, nil
+}
+
+// diskUsageForImage returns the disk-usage statistics for the spcified image.
+func diskUsageForImage(ctx context.Context, image *Image, tree *layerTree) (*DiskUsageStat, error) {
+ stat := DiskUsageStat{
+ ID: image.ID(),
+ Created: image.Created(),
+ }
+
+ // Repository and tag.
+ var name, repository, tag string
+ for _, n := range image.Names() {
+ if len(n) > 0 {
+ name = n
+ break
+ }
+ }
+ if len(name) > 0 {
+ named, err := reference.ParseNormalizedNamed(name)
+ if err != nil {
+ return nil, err
+ }
+ repository = named.Name()
+ if tagged, isTagged := named.(reference.NamedTagged); isTagged {
+ tag = tagged.Tag()
+ }
+ } else {
+ repository = "<none>"
+ tag = "<none>"
+ }
+ stat.Repository = repository
+ stat.Tag = tag
+
+ // Shared, unique and total size.
+ parent, err := tree.parent(ctx, image)
+ if err != nil {
+ return nil, err
+ }
+ childIDs, err := tree.children(ctx, image, false)
+ if err != nil {
+ return nil, err
+ }
+ // Optimistically set unique size to the full size of the image.
+ size, err := image.Size(ctx)
+ if err != nil {
+ return nil, err
+ }
+ stat.UniqueSize = *size
+
+ if len(childIDs) > 0 {
+ // If we have children, we share everything.
+ stat.SharedSize = stat.UniqueSize
+ stat.UniqueSize = 0
+ } else if parent != nil {
+ // If we have no children but a parent, remove the parent
+ // (shared) size from the unique one.
+ size, err := parent.Size(ctx)
+ if err != nil {
+ return nil, err
+ }
+ stat.UniqueSize -= *size
+ stat.SharedSize = *size
+ }
+
+ stat.Size = stat.SharedSize + stat.UniqueSize
+
+ // Number of containers using the image.
+ containers, err := image.Containers()
+ if err != nil {
+ return nil, err
+ }
+ stat.Containers = len(containers)
+
+ return &stat, nil
+}
diff --git a/libpod/info.go b/libpod/info.go
index 050d792bc..153000b6f 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -162,7 +162,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
return nil, errors.Wrapf(err, "error parsing system uptime")
}
- // TODO Isnt there a simple lib for this, something like humantime?
+ // TODO Isn't there a simple lib for this, something like humantime?
hoursFound := false
var timeBuffer bytes.Buffer
var hoursBuffer bytes.Buffer
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index bb138ca14..5769e5580 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -64,6 +64,7 @@ type ConmonOCIRuntime struct {
logSizeMax int64
noPivot bool
reservePorts bool
+ runtimeFlags []string
supportsJSON bool
supportsKVM bool
supportsNoCgroups bool
@@ -76,7 +77,7 @@ type ConmonOCIRuntime struct {
// The first path that points to a valid executable will be used.
// Deliberately private. Someone should not be able to construct this outside of
// libpod.
-func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *config.Config) (OCIRuntime, error) {
+func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeFlags []string, runtimeCfg *config.Config) (OCIRuntime, error) {
if name == "" {
return nil, errors.Wrapf(define.ErrInvalidArg, "the OCI runtime must be provided a non-empty name")
}
@@ -98,6 +99,7 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime
runtime := new(ConmonOCIRuntime)
runtime.name = name
runtime.conmonPath = conmonPath
+ runtime.runtimeFlags = runtimeFlags
runtime.conmonEnv = runtimeCfg.Engine.ConmonEnvVars
runtime.cgroupManager = runtimeCfg.Engine.CgroupManager
@@ -378,7 +380,7 @@ func (r *ConmonOCIRuntime) StartContainer(ctr *Container) error {
if path, ok := os.LookupEnv("PATH"); ok {
env = append(env, fmt.Sprintf("PATH=%s", path))
}
- if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, "start", ctr.ID()); err != nil {
+ if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, append(r.runtimeFlags, "start", ctr.ID())...); err != nil {
return err
}
@@ -398,10 +400,11 @@ func (r *ConmonOCIRuntime) KillContainer(ctr *Container, signal uint, all bool)
}
env := []string{fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)}
var args []string
+ args = append(args, r.runtimeFlags...)
if all {
- args = []string{"kill", "--all", ctr.ID(), fmt.Sprintf("%d", signal)}
+ args = append(args, "kill", "--all", ctr.ID(), fmt.Sprintf("%d", signal))
} else {
- args = []string{"kill", ctr.ID(), fmt.Sprintf("%d", signal)}
+ args = append(args, "kill", ctr.ID(), fmt.Sprintf("%d", signal))
}
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, args...); err != nil {
return errors.Wrapf(err, "error sending signal to container %s", ctr.ID())
@@ -478,7 +481,7 @@ func (r *ConmonOCIRuntime) DeleteContainer(ctr *Container) error {
return err
}
env := []string{fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)}
- return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, "delete", "--force", ctr.ID())
+ return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, append(r.runtimeFlags, "delete", "--force", ctr.ID())...)
}
// PauseContainer pauses the given container.
@@ -488,7 +491,7 @@ func (r *ConmonOCIRuntime) PauseContainer(ctr *Container) error {
return err
}
env := []string{fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)}
- return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, "pause", ctr.ID())
+ return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, append(r.runtimeFlags, "pause", ctr.ID())...)
}
// UnpauseContainer unpauses the given container.
@@ -498,7 +501,7 @@ func (r *ConmonOCIRuntime) UnpauseContainer(ctr *Container) error {
return err
}
env := []string{fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)}
- return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, "resume", ctr.ID())
+ return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, append(r.runtimeFlags, "resume", ctr.ID())...)
}
// HTTPAttach performs an attach for the HTTP API.
@@ -765,6 +768,7 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container
logrus.Debugf("Writing checkpoint to %s", imagePath)
logrus.Debugf("Writing checkpoint logs to %s", workPath)
args := []string{}
+ args = append(args, r.runtimeFlags...)
args = append(args, "checkpoint")
args = append(args, "--image-path")
args = append(args, imagePath)
@@ -1310,6 +1314,13 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p
"--exit-dir", exitDir,
"--socket-dir-path", r.socketsDir,
}
+ if len(r.runtimeFlags) > 0 {
+ rFlags := []string{}
+ for _, arg := range r.runtimeFlags {
+ rFlags = append(rFlags, "--runtime-arg", arg)
+ }
+ args = append(args, rFlags...)
+ }
if r.cgroupManager == config.SystemdCgroupsManager && !ctr.config.NoCgroups && ctr.config.CgroupsMode != cgroupSplit {
args = append(args, "-s")
diff --git a/libpod/oci_conmon_unsupported.go b/libpod/oci_conmon_unsupported.go
index 28d6ef12f..2504c31f0 100644
--- a/libpod/oci_conmon_unsupported.go
+++ b/libpod/oci_conmon_unsupported.go
@@ -17,7 +17,7 @@ type ConmonOCIRuntime struct {
}
// newConmonOCIRuntime is not supported on this OS.
-func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *config.Config) (OCIRuntime, error) {
+func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeFlags []string, runtimeCfg *config.Config) (OCIRuntime, error) {
return nil, define.ErrNotImplemented
}
diff --git a/libpod/options.go b/libpod/options.go
index 7eec530ea..d592124bc 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -530,6 +530,17 @@ func WithEnableSDNotify() RuntimeOption {
}
}
+// WithRuntimeFlags adds the global runtime flags to the container config
+func WithRuntimeFlags(runtimeFlags []string) RuntimeOption {
+ return func(rt *Runtime) error {
+ if rt.valid {
+ return define.ErrRuntimeFinalized
+ }
+ rt.runtimeFlags = runtimeFlags
+ return nil
+ }
+}
+
// Container Creation Options
// WithShmDir sets the directory that should be mounted on /dev/shm.
@@ -608,7 +619,7 @@ func WithSecLabels(labelOpts []string) CtrCreateOption {
}
}
-// WithUser sets the user identity field in configutation.
+// WithUser sets the user identity field in configuration.
// Valid uses [user | user:group | uid | uid:gid | user:gid | uid:group ].
func WithUser(user string) CtrCreateOption {
return func(ctr *Container) error {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 1d2e624d8..fdd9ebcc8 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -53,6 +53,7 @@ type Runtime struct {
imageContext *types.SystemContext
defaultOCIRuntime OCIRuntime
ociRuntimes map[string]OCIRuntime
+ runtimeFlags []string
netPlugin ocicni.CNIPlugin
conmonPath string
imageRuntime *image.Runtime
@@ -365,7 +366,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// Initialize remaining OCI runtimes
for name, paths := range runtime.config.Engine.OCIRuntimes {
- ociRuntime, err := newConmonOCIRuntime(name, paths, runtime.conmonPath, runtime.config)
+ ociRuntime, err := newConmonOCIRuntime(name, paths, runtime.conmonPath, runtime.runtimeFlags, runtime.config)
if err != nil {
// Don't fatally error.
// This will allow us to ship configs including optional
@@ -385,7 +386,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
if strings.HasPrefix(runtime.config.Engine.OCIRuntime, "/") {
name := filepath.Base(runtime.config.Engine.OCIRuntime)
- ociRuntime, err := newConmonOCIRuntime(name, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.config)
+ ociRuntime, err := newConmonOCIRuntime(name, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.runtimeFlags, runtime.config)
if err != nil {
return err
}