diff options
-rw-r--r-- | cmd/podman/inspect/inspect.go | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-volume-create.1.md | 4 | ||||
-rw-r--r-- | libpod/boltdb_state_internal.go | 2 | ||||
-rw-r--r-- | libpod/define/volume_inspect.go | 2 | ||||
-rw-r--r-- | libpod/options.go | 12 | ||||
-rw-r--r-- | libpod/plugin/volume_api.go | 9 | ||||
-rw-r--r-- | libpod/runtime.go | 8 | ||||
-rw-r--r-- | libpod/runtime_volume_linux.go | 2 | ||||
-rw-r--r-- | libpod/volume.go | 2 | ||||
-rw-r--r-- | libpod/volume_inspect.go | 1 | ||||
-rw-r--r-- | pkg/domain/infra/abi/parse/parse.go | 10 | ||||
-rw-r--r-- | test/e2e/volume_create_test.go | 15 |
12 files changed, 60 insertions, 9 deletions
diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index f6e3fca06..e36fd9e0d 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -41,7 +41,7 @@ func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions { return &opts } -// Inspect inspects the specified container/image names or IDs. +// Inspect inspects the specified container/image/pod/volume names or IDs. func Inspect(namesOrIDs []string, options entities.InspectOptions) error { inspector, err := newInspector(options) if err != nil { diff --git a/docs/source/markdown/podman-volume-create.1.md b/docs/source/markdown/podman-volume-create.1.md index 31e109791..fefbc13f8 100644 --- a/docs/source/markdown/podman-volume-create.1.md +++ b/docs/source/markdown/podman-volume-create.1.md @@ -39,8 +39,8 @@ The `o` option sets options for the mount, and is equivalent to the `-o` flag to - The `o` option supports `uid` and `gid` options to set the UID and GID of the created volume that are not normally supported by **mount(8)**. - The `o` option supports the `size` option to set the maximum size of the created volume, the `inodes` option to set the maximum number of inodes for the volume and `noquota` to completely disable quota support even for tracking of disk usage. Currently these flags are only supported on "xfs" file system mounted with the `prjquota` flag described in the **xfs_quota(8)** man page. - - The `o` option supports . - - Using volume options other then the UID/GID options with the **local** driver requires root privileges. + - The `o` option supports using volume options other than the UID/GID options with the **local** driver and requires root privileges. + - The `o` options supports the `timeout` option which allows users to set a driver specific timeout in seconds before volume creation fails. For example, **--opts=o=timeout=10** sets a driver timeout of 10 seconds. When not using the **local** driver, the given options are passed directly to the volume plugin. In this case, supported options are dictated by the plugin in question, not Podman. diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index d6f035af9..9dc333ef9 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -508,7 +508,7 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu // Retrieve volume driver if volume.UsesVolumeDriver() { - plugin, err := s.runtime.getVolumePlugin(volume.config.Driver) + plugin, err := s.runtime.getVolumePlugin(volume.config) if err != nil { // We want to fail gracefully here, to ensure that we // can still remove volumes even if their plugin is diff --git a/libpod/define/volume_inspect.go b/libpod/define/volume_inspect.go index fac179176..4b91c3ece 100644 --- a/libpod/define/volume_inspect.go +++ b/libpod/define/volume_inspect.go @@ -56,4 +56,6 @@ type InspectVolumeData struct { // a container, the container will chown the volume to the container process // UID/GID. NeedsChown bool `json:"NeedsChown,omitempty"` + // Timeout is the specified driver timeout if given + Timeout int `json:"Timeout,omitempty"` } diff --git a/libpod/options.go b/libpod/options.go index 8b3b07efa..7f4ca22d3 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1693,6 +1693,18 @@ func withSetAnon() VolumeCreateOption { } } +// WithVolumeDriverTimeout sets the volume creation timeout period +func WithVolumeDriverTimeout(timeout int) VolumeCreateOption { + return func(volume *Volume) error { + if volume.valid { + return define.ErrVolumeFinalized + } + + volume.config.Timeout = timeout + return nil + } +} + // WithTimezone sets the timezone in the container func WithTimezone(path string) CtrCreateOption { return func(ctr *Container) error { diff --git a/libpod/plugin/volume_api.go b/libpod/plugin/volume_api.go index 2818e70c1..2587bd571 100644 --- a/libpod/plugin/volume_api.go +++ b/libpod/plugin/volume_api.go @@ -129,7 +129,7 @@ func validatePlugin(newPlugin *VolumePlugin) error { // GetVolumePlugin gets a single volume plugin, with the given name, at the // given path. -func GetVolumePlugin(name string, path string) (*VolumePlugin, error) { +func GetVolumePlugin(name string, path string, timeout int) (*VolumePlugin, error) { pluginsLock.Lock() defer pluginsLock.Unlock() @@ -153,6 +153,13 @@ func GetVolumePlugin(name string, path string) (*VolumePlugin, error) { // And since we can reuse it, might as well cache it. client := new(http.Client) client.Timeout = defaultTimeout + // if the user specified a non-zero timeout, use their value. Else, keep the default. + if timeout != 0 { + if time.Duration(timeout)*time.Second < defaultTimeout { + logrus.Warnf("the default timeout for volume creation is %d seconds, setting a time less than that may break this feature.", defaultTimeout) + } + client.Timeout = time.Duration(timeout) * time.Second + } // This bit borrowed from pkg/bindings/connection.go client.Transport = &http.Transport{ DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { diff --git a/libpod/runtime.go b/libpod/runtime.go index 6c8a99846..8aad480bf 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -1194,9 +1194,11 @@ func (r *Runtime) reloadStorageConf() error { return nil } -// getVolumePlugin gets a specific volume plugin given its name. -func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) { +// getVolumePlugin gets a specific volume plugin. +func (r *Runtime) getVolumePlugin(volConfig *VolumeConfig) (*plugin.VolumePlugin, error) { // There is no plugin for local. + name := volConfig.Driver + timeout := volConfig.Timeout if name == define.VolumeDriverLocal || name == "" { return nil, nil } @@ -1206,7 +1208,7 @@ func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) { return nil, errors.Wrapf(define.ErrMissingPlugin, "no volume plugin with name %s available", name) } - return plugin.GetVolumePlugin(name, pluginPath) + return plugin.GetVolumePlugin(name, pluginPath, timeout) } // GetSecretsStorageDir returns the directory that the secrets manager should take diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index f8788e183..59dba9b35 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -56,7 +56,7 @@ func (r *Runtime) newVolume(options ...VolumeCreateOption) (_ *Volume, deferredE // Plugin can be nil if driver is local, but that's OK - superfluous // assignment doesn't hurt much. - plugin, err := r.getVolumePlugin(volume.config.Driver) + plugin, err := r.getVolumePlugin(volume.config) if err != nil { return nil, errors.Wrapf(err, "volume %s uses volume plugin %s but it could not be retrieved", volume.config.Name, volume.config.Driver) } diff --git a/libpod/volume.go b/libpod/volume.go index ab461a37f..2e8cd77a5 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -55,6 +55,8 @@ type VolumeConfig struct { // DisableQuota indicates that the volume should completely disable using any // quota tracking. DisableQuota bool `json:"disableQuota,omitempty"` + // Timeout allows users to override the default driver timeout of 5 seconds + Timeout int } // VolumeState holds the volume's mutable state. diff --git a/libpod/volume_inspect.go b/libpod/volume_inspect.go index 3d721410b..2182f04e6 100644 --- a/libpod/volume_inspect.go +++ b/libpod/volume_inspect.go @@ -63,6 +63,7 @@ func (v *Volume) Inspect() (*define.InspectVolumeData, error) { data.MountCount = v.state.MountCount data.NeedsCopyUp = v.state.NeedsCopyUp data.NeedsChown = v.state.NeedsChown + data.Timeout = v.config.Timeout return data, nil } diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go index 66794e592..4e8c2e508 100644 --- a/pkg/domain/infra/abi/parse/parse.go +++ b/pkg/domain/infra/abi/parse/parse.go @@ -78,6 +78,16 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) libpodOptions = append(libpodOptions, libpod.WithVolumeDisableQuota()) // set option "NOQUOTA": "true" volumeOptions["NOQUOTA"] = "true" + case "timeout": + if len(splitO) != 2 { + return nil, errors.Wrapf(define.ErrInvalidArg, "timeout option must provide a valid timeout in seconds") + } + intTimeout, err := strconv.Atoi(splitO[1]) + if err != nil { + return nil, errors.Wrapf(err, "cannot convert Timeout %s to an integer", splitO[1]) + } + logrus.Debugf("Removing timeout from options and adding WithTimeout for Timeout %d", intTimeout) + libpodOptions = append(libpodOptions, libpod.WithVolumeDriverTimeout(intTimeout)) default: finalVal = append(finalVal, o) } diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go index 499283cab..7a975f6a5 100644 --- a/test/e2e/volume_create_test.go +++ b/test/e2e/volume_create_test.go @@ -162,4 +162,19 @@ var _ = Describe("Podman volume create", func() { Expect(inspectOpts).Should(Exit(0)) Expect(inspectOpts.OutputToString()).To(Equal(optionStrFormatExpect)) }) + + It("podman create volume with o=timeout", func() { + volName := "testVol" + timeout := 10 + timeoutStr := "10" + session := podmanTest.Podman([]string{"volume", "create", "--opt", fmt.Sprintf("o=timeout=%d", timeout), volName}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + inspectTimeout := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Timeout }}", volName}) + inspectTimeout.WaitWithDefaultTimeout() + Expect(inspectTimeout).Should(Exit(0)) + Expect(inspectTimeout.OutputToString()).To(Equal(timeoutStr)) + + }) }) |