mirror of
https://github.com/containers/podman.git
synced 2025-05-21 00:56:36 +08:00
podman volume create --opt=o=timeout...
add an option to configure the driver timeout when creating a volume. The default is 5 seconds but this value is too small for some custom drivers. Signed-off-by: cdoern <cdoern@redhat.com>
This commit is contained in:
@ -41,7 +41,7 @@ func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions {
|
|||||||
return &opts
|
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 {
|
func Inspect(namesOrIDs []string, options entities.InspectOptions) error {
|
||||||
inspector, err := newInspector(options)
|
inspector, err := newInspector(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -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 `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 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 .
|
- The `o` option supports using volume options other than the UID/GID options with the **local** driver and requires root privileges.
|
||||||
- Using volume options other then the UID/GID options with the **local** driver 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.
|
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.
|
||||||
|
|
||||||
|
@ -508,7 +508,7 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu
|
|||||||
|
|
||||||
// Retrieve volume driver
|
// Retrieve volume driver
|
||||||
if volume.UsesVolumeDriver() {
|
if volume.UsesVolumeDriver() {
|
||||||
plugin, err := s.runtime.getVolumePlugin(volume.config.Driver)
|
plugin, err := s.runtime.getVolumePlugin(volume.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We want to fail gracefully here, to ensure that we
|
// We want to fail gracefully here, to ensure that we
|
||||||
// can still remove volumes even if their plugin is
|
// can still remove volumes even if their plugin is
|
||||||
|
@ -56,4 +56,6 @@ type InspectVolumeData struct {
|
|||||||
// a container, the container will chown the volume to the container process
|
// a container, the container will chown the volume to the container process
|
||||||
// UID/GID.
|
// UID/GID.
|
||||||
NeedsChown bool `json:"NeedsChown,omitempty"`
|
NeedsChown bool `json:"NeedsChown,omitempty"`
|
||||||
|
// Timeout is the specified driver timeout if given
|
||||||
|
Timeout int `json:"Timeout,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -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
|
// WithTimezone sets the timezone in the container
|
||||||
func WithTimezone(path string) CtrCreateOption {
|
func WithTimezone(path string) CtrCreateOption {
|
||||||
return func(ctr *Container) error {
|
return func(ctr *Container) error {
|
||||||
|
@ -129,7 +129,7 @@ func validatePlugin(newPlugin *VolumePlugin) error {
|
|||||||
|
|
||||||
// GetVolumePlugin gets a single volume plugin, with the given name, at the
|
// GetVolumePlugin gets a single volume plugin, with the given name, at the
|
||||||
// given path.
|
// given path.
|
||||||
func GetVolumePlugin(name string, path string) (*VolumePlugin, error) {
|
func GetVolumePlugin(name string, path string, timeout int) (*VolumePlugin, error) {
|
||||||
pluginsLock.Lock()
|
pluginsLock.Lock()
|
||||||
defer pluginsLock.Unlock()
|
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.
|
// And since we can reuse it, might as well cache it.
|
||||||
client := new(http.Client)
|
client := new(http.Client)
|
||||||
client.Timeout = defaultTimeout
|
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
|
// This bit borrowed from pkg/bindings/connection.go
|
||||||
client.Transport = &http.Transport{
|
client.Transport = &http.Transport{
|
||||||
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||||
|
@ -1194,9 +1194,11 @@ func (r *Runtime) reloadStorageConf() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getVolumePlugin gets a specific volume plugin given its name.
|
// getVolumePlugin gets a specific volume plugin.
|
||||||
func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) {
|
func (r *Runtime) getVolumePlugin(volConfig *VolumeConfig) (*plugin.VolumePlugin, error) {
|
||||||
// There is no plugin for local.
|
// There is no plugin for local.
|
||||||
|
name := volConfig.Driver
|
||||||
|
timeout := volConfig.Timeout
|
||||||
if name == define.VolumeDriverLocal || name == "" {
|
if name == define.VolumeDriverLocal || name == "" {
|
||||||
return nil, nil
|
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 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
|
// GetSecretsStorageDir returns the directory that the secrets manager should take
|
||||||
|
@ -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
|
// Plugin can be nil if driver is local, but that's OK - superfluous
|
||||||
// assignment doesn't hurt much.
|
// assignment doesn't hurt much.
|
||||||
plugin, err := r.getVolumePlugin(volume.config.Driver)
|
plugin, err := r.getVolumePlugin(volume.config)
|
||||||
if err != nil {
|
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)
|
return nil, errors.Wrapf(err, "volume %s uses volume plugin %s but it could not be retrieved", volume.config.Name, volume.config.Driver)
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,8 @@ type VolumeConfig struct {
|
|||||||
// DisableQuota indicates that the volume should completely disable using any
|
// DisableQuota indicates that the volume should completely disable using any
|
||||||
// quota tracking.
|
// quota tracking.
|
||||||
DisableQuota bool `json:"disableQuota,omitempty"`
|
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.
|
// VolumeState holds the volume's mutable state.
|
||||||
|
@ -63,6 +63,7 @@ func (v *Volume) Inspect() (*define.InspectVolumeData, error) {
|
|||||||
data.MountCount = v.state.MountCount
|
data.MountCount = v.state.MountCount
|
||||||
data.NeedsCopyUp = v.state.NeedsCopyUp
|
data.NeedsCopyUp = v.state.NeedsCopyUp
|
||||||
data.NeedsChown = v.state.NeedsChown
|
data.NeedsChown = v.state.NeedsChown
|
||||||
|
data.Timeout = v.config.Timeout
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,16 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error)
|
|||||||
libpodOptions = append(libpodOptions, libpod.WithVolumeDisableQuota())
|
libpodOptions = append(libpodOptions, libpod.WithVolumeDisableQuota())
|
||||||
// set option "NOQUOTA": "true"
|
// set option "NOQUOTA": "true"
|
||||||
volumeOptions["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:
|
default:
|
||||||
finalVal = append(finalVal, o)
|
finalVal = append(finalVal, o)
|
||||||
}
|
}
|
||||||
|
@ -162,4 +162,19 @@ var _ = Describe("Podman volume create", func() {
|
|||||||
Expect(inspectOpts).Should(Exit(0))
|
Expect(inspectOpts).Should(Exit(0))
|
||||||
Expect(inspectOpts.OutputToString()).To(Equal(optionStrFormatExpect))
|
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))
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user