diff options
author | W. Trevor King <wking@tremily.us> | 2018-11-19 09:22:32 -0800 |
---|---|---|
committer | W. Trevor King <wking@tremily.us> | 2019-01-08 21:06:17 -0800 |
commit | f6a2b6bf2b923a148792cc141ec4c27b5889c077 (patch) | |
tree | e4f6ba1dff72d3e597edcc2bce304fdd5b3849eb /libpod | |
parent | c9d63fe89d0a79b069b56249aaa4c168b47649c0 (diff) | |
download | podman-f6a2b6bf2b923a148792cc141ec4c27b5889c077.tar.gz podman-f6a2b6bf2b923a148792cc141ec4c27b5889c077.tar.bz2 podman-f6a2b6bf2b923a148792cc141ec4c27b5889c077.zip |
hooks: Add pre-create hooks for runtime-config manipulation
There's been a lot of discussion over in [1] about how to support the
NVIDIA folks and others who want to be able to create devices
(possibly after having loaded kernel modules) and bind userspace
libraries into the container. Currently that's happening in the
middle of runc's create-time mount handling before the container
pivots to its new root directory with runc's incorrectly-timed
prestart hook trigger [2]. With this commit, we extend hooks with a
'precreate' stage to allow trusted parties to manipulate the config
JSON before calling the runtime's 'create'.
I'm recycling the existing Hook schema from pkg/hooks for this,
because we'll want Timeout for reliability and When to avoid the
expense of fork/exec when a given hook does not need to make config
changes [3].
[1]: https://github.com/opencontainers/runc/pull/1811
[2]: https://github.com/opencontainers/runc/issues/1710
[3]: https://github.com/containers/libpod/issues/1828#issuecomment-439888059
Signed-off-by: W. Trevor King <wking@tremily.us>
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal.go | 30 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 10 |
2 files changed, 28 insertions, 12 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go index cc4c36bc9..69df33bc9 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1181,6 +1181,7 @@ func (c *Container) saveSpec(spec *spec.Spec) error { return nil } +// Warning: precreate hooks may alter 'config' in place. func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (extensionStageHooks map[string][]spec.Hook, err error) { var locale string var ok bool @@ -1209,13 +1210,13 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten } } + allHooks := make(map[string][]spec.Hook) if c.runtime.config.HooksDir == nil { if rootless.IsRootless() { return nil, nil } - allHooks := make(map[string][]spec.Hook) for _, hDir := range []string{hooks.DefaultDir, hooks.OverrideDir} { - manager, err := hooks.New(ctx, []string{hDir}, []string{"poststop"}, lang) + manager, err := hooks.New(ctx, []string{hDir}, []string{"precreate", "poststop"}, lang) if err != nil { if os.IsNotExist(err) { continue @@ -1233,19 +1234,32 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten allHooks[i] = hook } } - return allHooks, nil + } else { + manager, err := hooks.New(ctx, c.runtime.config.HooksDir, []string{"precreate", "poststop"}, lang) + if err != nil { + if os.IsNotExist(err) { + logrus.Warnf("Requested OCI hooks directory %q does not exist", c.runtime.config.HooksDir) + return nil, nil + } + return nil, err + } + + allHooks, err = manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0) + if err != nil { + return nil, err + } } - manager, err := hooks.New(ctx, c.runtime.config.HooksDir, []string{"poststop"}, lang) + hookErr, err := exec.RuntimeConfigFilter(ctx, allHooks["precreate"], config, exec.DefaultPostKillTimeout) if err != nil { - if os.IsNotExist(err) { - logrus.Warnf("Requested OCI hooks directory %q does not exist", c.runtime.config.HooksDir) - return nil, nil + logrus.Warnf("container %s: precreate hook: %v", c.ID(), err) + if hookErr != nil && hookErr != err { + logrus.Debugf("container %s: precreate hook (hook error): %v", c.ID(), hookErr) } return nil, err } - return manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0) + return allHooks, nil } // mount mounts the container's root filesystem diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 0745b7732..c66be1061 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -228,10 +228,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } - if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { - return nil, errors.Wrapf(err, "error setting up OCI Hooks") - } - // Bind builtin image volumes if c.config.Rootfs == "" && c.config.ImageVolumes { if err := c.addLocalVolumes(ctx, &g, execUser); err != nil { @@ -384,6 +380,12 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { logrus.Debugf("set root propagation to %q", rootPropagation) g.SetLinuxRootPropagation(rootPropagation) } + + // Warning: precreate hooks may alter g.Config in place. + if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { + return nil, errors.Wrapf(err, "error setting up OCI Hooks") + } + return g.Config, nil } |