From 7030dc0160bd56637355645771991655500aeee5 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Wed, 8 Sep 2021 09:33:51 -0400 Subject: [PATCH] Add support for image_copy_tmp_dir Allow users to set the default location for the temporary files used during image pulls and pushes. Defaults to /var/tmp; Overridden via "TMPDIR" environment variable. Allow special flag "storage" to indicate the the storage should use the tmp directory in containers/storage/tmp. Needed to fix: https://github.com/containers/podman/issues/11107 Signed-off-by: Daniel J Walsh --- docs/containers.conf.5.md | 6 +++++ pkg/config/config.go | 8 ++++++ pkg/config/config_test.go | 27 ++++++++++++++++++++ pkg/config/containers.conf | 5 ++++ pkg/config/default.go | 13 ++++++++++ pkg/config/testdata/containers_default.conf | 3 +++ pkg/config/testdata/containers_override.conf | 1 + 7 files changed, 63 insertions(+) diff --git a/docs/containers.conf.5.md b/docs/containers.conf.5.md index 84615f306..1121f8517 100644 --- a/docs/containers.conf.5.md +++ b/docs/containers.conf.5.md @@ -491,6 +491,12 @@ The list of OCI runtimes that support running containers with KVM separation. The list of OCI runtimes that support running containers without CGroups. +**image_copy_tmp_dir**="/var/tmp" + +Default location for storing temporary container image content. Can be +overridden with the TMPDIR environment variable. If you specify "storage", then +the location of the container/storage tmp directory will be used. + **static_dir**="/var/lib/containers/storage/libpod" Directory for persistent libpod files (database, etc). diff --git a/pkg/config/config.go b/pkg/config/config.go index 94f1b4695..c7e03a3fb 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -234,6 +234,8 @@ type EngineConfig struct { // EventsLogger determines where events should be logged. EventsLogger string `toml:"events_logger,omitempty"` + // graphRoot internal stores the location of the graphroot + graphRoot string // configuration files. When the same filename is present in in // multiple directories, the file in the directory listed last in // this slice takes precedence. @@ -380,6 +382,12 @@ type EngineConfig struct { // before sending kill signal. StopTimeout uint `toml:"stop_timeout,omitempty"` + // ImageCopyTmpDir is the default location for storing temporary + // container image content, Can be overridden with the TMPDIR + // environment variable. If you specify "storage", then the + // location of the container/storage tmp directory will be used. + ImageCopyTmpDir string `toml:"image_copy_tmp_dir,omitempty"` + // TmpDir is the path to a temporary directory to store per-boot container // files. Must be stored in a tmpfs. TmpDir string `toml:"tmp_dir,omitempty"` diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 51b37fde4..1d30ddc6f 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -28,6 +28,7 @@ var _ = Describe("Config", func() { gomega.Expect(err).To(gomega.BeNil()) gomega.Expect(defaultConfig.Containers.ApparmorProfile).To(gomega.Equal(apparmor.Profile)) gomega.Expect(defaultConfig.Containers.PidsLimit).To(gomega.BeEquivalentTo(2048)) + gomega.Expect(defaultConfig.ImageCopyTmpDir()).To(gomega.BeEquivalentTo("/var/tmp")) }) It("should succeed with devices", func() { @@ -107,6 +108,31 @@ var _ = Describe("Config", func() { }) }) + Describe("readStorageTmp", func() { + It("test image_copy_tmp_dir='storage'", func() { + // Reload from new configuration file + testFile := "testdata/temp.conf" + content := `[engine] +image_copy_tmp_dir="storage"` + err := ioutil.WriteFile(testFile, []byte(content), os.ModePerm) + // Then + gomega.Expect(err).To(gomega.BeNil()) + defer os.Remove(testFile) + + config, _ := NewConfig(testFile) + gomega.Expect(config.ImageCopyTmpDir()).To(gomega.ContainSubstring("containers/storage/tmp")) + // Given we do + oldTMPDIR, set := os.LookupEnv("TMPDIR") + os.Setenv("TMPDIR", "/var/tmp/foobar") + gomega.Expect(config.ImageCopyTmpDir()).To(gomega.BeEquivalentTo("/var/tmp/foobar")) + if set { + os.Setenv("TMPDIR", oldTMPDIR) + } else { + os.Unsetenv("TMPDIR") + } + }) + }) + Describe("readConfigFromFile", func() { It("should succeed with default config", func() { // Given @@ -327,6 +353,7 @@ var _ = Describe("Config", func() { gomega.Expect(config.Containers.LogSizeMax).To(gomega.Equal(int64(100000))) gomega.Expect(config.Engine.ImageParallelCopies).To(gomega.Equal(uint(10))) gomega.Expect(config.Engine.ImageDefaultFormat).To(gomega.Equal("v2s2")) + gomega.Expect(config.ImageCopyTmpDir()).To(gomega.BeEquivalentTo("/tmp/foobar")) }) It("should fail with invalid value", func() { diff --git a/pkg/config/containers.conf b/pkg/config/containers.conf index 481405a1a..748b7debe 100644 --- a/pkg/config/containers.conf +++ b/pkg/config/containers.conf @@ -452,6 +452,11 @@ default_sysctls = [ # #runtime_supports_nocgroups = ["crun"] +# Default location for storing temporary container image content, Can be overridden with the TMPDIR environment +# variable. If you specify "storage", then the location of the +# container/storage tmp directory will be used. +# image_copy_tmp_dir="/var/tmp" + # Directory for persistent engine files (database, etc) # By default, this will be configured relative to where the containers/storage # stores containers diff --git a/pkg/config/default.go b/pkg/config/default.go index 89193be64..18e1f5dd6 100644 --- a/pkg/config/default.go +++ b/pkg/config/default.go @@ -244,6 +244,8 @@ func defaultConfigFromMemory() (*EngineConfig, error) { logrus.Warnf("Storage configuration is unset - using hardcoded default graph root %q", _defaultGraphRoot) storeOpts.GraphRoot = _defaultGraphRoot } + c.graphRoot = storeOpts.GraphRoot + c.ImageCopyTmpDir = "/var/tmp" c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod") c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes") @@ -562,3 +564,14 @@ func (c *Config) RootlessNetworking() string { func (c *Config) MachineImage() string { return c.Engine.MachineImage } + +// ImageCopyTmpDir default storage tmpdir +func (c *Config) ImageCopyTmpDir() string { + if path, found := os.LookupEnv("TMPDIR"); found { + return path + } + if c.Engine.ImageCopyTmpDir == "storage" { + return filepath.Join(c.Engine.graphRoot, "tmp") + } + return c.Engine.ImageCopyTmpDir +} diff --git a/pkg/config/testdata/containers_default.conf b/pkg/config/testdata/containers_default.conf index 02dafb9eb..f81e0106c 100644 --- a/pkg/config/testdata/containers_default.conf +++ b/pkg/config/testdata/containers_default.conf @@ -119,6 +119,9 @@ conmon_env_vars = [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ] +image_copy_tmp_dir="storage" + + # Paths to look for the Conmon container manager binary conmon_path = [ "/usr/libexec/podman/conmon", diff --git a/pkg/config/testdata/containers_override.conf b/pkg/config/testdata/containers_override.conf index 1f81eed89..cde9d3d85 100644 --- a/pkg/config/testdata/containers_override.conf +++ b/pkg/config/testdata/containers_override.conf @@ -8,6 +8,7 @@ log_size_max = 100000 [engine] image_parallel_copies=10 image_default_format="v2s2" +image_copy_tmp_dir="/tmp/foobar" [secrets] driver = "pass"