summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md84
-rw-r--r--README.md17
-rw-r--r--cmd/podman/cleanup.go2
-rw-r--r--cmd/podman/libpodruntime/runtime.go3
-rw-r--r--cmd/podman/logs.go2
-rw-r--r--cmd/podman/play_kube.go2
-rw-r--r--docs/libpod.conf.5.md6
-rw-r--r--docs/podman-generate-kube.1.md4
-rw-r--r--docs/podman-play-kube.1.md4
-rw-r--r--libpod.conf6
-rw-r--r--libpod/boltdb_state.go2
-rw-r--r--libpod/boltdb_state_internal.go11
-rw-r--r--libpod/container_internal_linux.go13
-rw-r--r--libpod/info.go1
-rw-r--r--libpod/options.go22
-rw-r--r--libpod/runtime.go45
-rw-r--r--libpod/runtime_ctr.go5
-rw-r--r--libpod/state.go1
-rw-r--r--libpod/volume.go18
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/containers/image/pkg/blobinfocache/memory.go20
-rw-r--r--vendor/github.com/containers/image/version/version.go2
22 files changed, 245 insertions, 27 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 26e5473b2..b1b166fef 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,5 +1,5 @@
![PODMAN logo](logo/podman-logo-source.svg)
-# Contributing to Libpod
+# Contributing to libpod
We'd love to have you join the community! Below summarizes the processes
that we follow.
@@ -7,6 +7,7 @@ that we follow.
## Topics
* [Reporting Issues](#reporting-issues)
+* [Contributing to libpod](#contributing-to-libpod)
* [Submitting Pull Requests](#submitting-pull-requests)
* [Communications](#communications)
@@ -26,6 +27,87 @@ The easier it is for us to reproduce it, the faster it'll be fixed!
Please don't include any private/sensitive information in your issue!
+## Contributing to libpod
+
+This section describes how to start a contribution to libpod.
+
+### Prepare your environment
+
+Read the [install documentation to see how to install dependencies](install.md) .
+
+The install documentation will illustrate the following steps:
+- install libs and tools
+- check installed versions
+- configure network
+- how to install libpod from sources
+
+### Fork and clone libpod
+
+First you need to fork this project on GitHub.
+
+Be sure to have [defined your `$GOPATH` environment variable](https://github.com/golang/go/wiki/GOPATH).
+
+Create a path that correspond to your clone `mkdir -p $GOPATH/github.com/<you>`.
+
+Clone your fork locally:
+```shell
+$ git clone git@github.com:<you>/libpod github.com/<you> $GOPATH/github.com/<you>/libpod
+$ cd $GOPATH/github.com/<you>/libpod
+```
+
+You can also use `go get` to clone your fork:
+```shell
+$ go get github.com:<you>/libpod
+$ cd $GOPATH/github.com/<you>/libpod
+```
+
+### Deal with make
+
+Libpod use a Makefile to realize common action like building etc...
+
+You can list available actions by using:
+```shell
+$ make help
+Usage: make <target>
+...output...
+```
+
+### Install tools
+
+Makefile allow you to install needed tools:
+```shell
+$ make install.tools
+```
+
+### Building binaries and test your changes
+
+To test your changes do `make binaries` to generate your binaries.
+
+Your binaries are created inside the `bin/` directory and you can test your changes:
+```shell
+$ bin/podman -h
+bin/podman -h
+NAME:
+ podman - manage pods and images
+
+USAGE:
+ podman [global options] command [command options] [arguments...]
+
+VERSION:
+ 1.0.1-dev
+
+COMMANDS:
+ attach Attach to a running container
+ build Build an image using instructions from Dockerfiles
+ commit Create new image based on the changed container
+ container Manage Containers
+ cp Copy files/folders between a container and the local filesystem
+```
+
+Well, you can now create your own branch, apply changes on it, and then submitting your pull request.
+
+For further reading about branching [you can read this document](https://herve.beraud.io/containers/linux/podman/isolate/environment/2019/02/06/how-to-hack-on-podman.html).
+
## Submitting Pull Requests
No Pull Request (PR) is too small! Typos, additional comments in the code,
diff --git a/README.md b/README.md
index 08c584c72..97c548ddd 100644
--- a/README.md
+++ b/README.md
@@ -31,10 +31,19 @@ This project tests all builds against each supported version of Fedora, the late
## Out of scope
-* Signing and pushing images to various image storages.
- See [Skopeo](https://github.com/containers/skopeo/).
-* Container Runtimes daemons for working with the Kubernetes CRI interface.
- See [CRI-O](https://github.com/kubernetes-sigs/cri-o).
+* Specializing in signing and pushing images to various storage backends.
+ See [Skopeo](https://github.com/containers/skopeo/) for those tasks.
+* Container runtimes daemons for working with the Kubernetes CRI interface.
+ [CRI-O](https://github.com/kubernetes-sigs/cri-o) specializes in that.
+* Supporting `docker-compose`. We believe that Kubernetes is the defacto
+ standard for composing Pods and for orchestrating containers, making
+ Kubernetes YAML a defacto standard file format. Hence, Podman allows the
+ creation and execution of Pods from a Kubernetes YAML file (see
+ [podman-play-kube](https://github.com/containers/libpod/blob/master/docs/podman-play-kube.1.md)).
+ Podman can also generate Kubernetes YAML based on a container or Pod (see
+ [podman-generate-kube](https://github.com/containers/libpod/blob/master/docs/podman-generate-kube.1.md)),
+ which allows for an easy transition from a local development environment
+ to a production Kubernetes cluster.
## OCI Projects Plans
diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go
index d68255aa2..33d456643 100644
--- a/cmd/podman/cleanup.go
+++ b/cmd/podman/cleanup.go
@@ -60,7 +60,7 @@ func cleanupCmd(c *cliconfig.CleanupValues) error {
for _, ctr := range cleanupContainers {
hadError := false
if c.Remove {
- if err := runtime.RemoveContainer(ctx, ctr, false, false); err != nil {
+ if err := runtime.RemoveContainer(ctx, ctr, false, true); err != nil {
if lastError != nil {
fmt.Fprintln(os.Stderr, lastError)
}
diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go
index 880b281bd..f4ddf3521 100644
--- a/cmd/podman/libpodruntime/runtime.go
+++ b/cmd/podman/libpodruntime/runtime.go
@@ -21,7 +21,7 @@ func GetRuntime(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
func getRuntime(c *cliconfig.PodmanCommand, renumber bool) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
- storageOpts, volumePath, err := util.GetDefaultStoreOptions()
+ storageOpts, _, err := util.GetDefaultStoreOptions()
if err != nil {
return nil, err
}
@@ -120,7 +120,6 @@ func getRuntime(c *cliconfig.PodmanCommand, renumber bool) (*libpod.Runtime, err
infraCommand, _ := c.Flags().GetString("infra-command")
options = append(options, libpod.WithDefaultInfraCommand(infraCommand))
}
- options = append(options, libpod.WithVolumePath(volumePath))
if c.Flags().Changed("config") {
return libpod.NewRuntimeFromConfig(c.GlobalFlags.Config, options...)
}
diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go
index 97d835d8f..40ae2c846 100644
--- a/cmd/podman/logs.go
+++ b/cmd/podman/logs.go
@@ -38,7 +38,7 @@ func init() {
flags := logsCommand.Flags()
flags.BoolVar(&logsCommand.Details, "details", false, "Show extra details provided to the logs")
flags.BoolVarP(&logsCommand.Follow, "follow", "f", false, "Follow log output. The default is false")
- flags.BoolVarP(&waitCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.BoolVarP(&logsCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.StringVar(&logsCommand.Since, "since", "", "Show logs since TIMESTAMP")
flags.Uint64Var(&logsCommand.Tail, "tail", 0, "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines")
flags.BoolVarP(&logsCommand.Timestamps, "timestamps", "t", false, "Output the timestamps in the log")
diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go
index a59460b71..1a45cbed9 100644
--- a/cmd/podman/play_kube.go
+++ b/cmd/podman/play_kube.go
@@ -153,7 +153,7 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error {
// start the containers
for _, ctr := range containers {
- if err := ctr.Start(ctx, false); err != nil {
+ if err := ctr.Start(ctx, true); err != nil {
// Making this a hard failure here to avoid a mess
// the other containers are in created status
return err
diff --git a/docs/libpod.conf.5.md b/docs/libpod.conf.5.md
index 0836c45fa..9a19e1224 100644
--- a/docs/libpod.conf.5.md
+++ b/docs/libpod.conf.5.md
@@ -13,7 +13,7 @@ libpod to manage containers.
Default transport method for pulling and pushing images
**runtime**=""
- Default OCI runtime to use if nothing is specified
+ Default OCI runtime to use if nothing is specified in **runtimes**
**runtimes**
For each OCI runtime, specify a list of paths to look for. The first one found is used.
@@ -87,6 +87,10 @@ libpod to manage containers.
The default number available is 2048.
If this is changed, a lock renumbering must be performed, using the `podman system renumber` command.
+**volume_path**=""
+ Directory where named volumes will be created in using the default volume driver.
+ By default this will be configured relative to where containers/storage stores containers.
+
## FILES
`/usr/share/containers/libpod.conf`, default libpod configuration path
diff --git a/docs/podman-generate-kube.1.md b/docs/podman-generate-kube.1.md
index 5236f23fe..d4bed8ab1 100644
--- a/docs/podman-generate-kube.1.md
+++ b/docs/podman-generate-kube.1.md
@@ -19,6 +19,8 @@ The **service** option can be used to generate a Service specification for the c
if the object has portmap bindings, the service specification will include a NodePort declaration to expose the service. A
random port is assigned by Podman in the specification.
+Note that the generated Kubernetes YAML file can be used to re-run the deployment via podman-play-kube(1).
+
# OPTIONS:
**s** **--service**
@@ -145,7 +147,7 @@ status:
```
## SEE ALSO
-podman(1), podman-container, podman-pod, podman-play
+podman(1), podman-container(1), podman-pod(1), podman-play-kube(1)
# HISTORY
Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
diff --git a/docs/podman-play-kube.1.md b/docs/podman-play-kube.1.md
index 3fd9746a5..2264f7a88 100644
--- a/docs/podman-play-kube.1.md
+++ b/docs/podman-play-kube.1.md
@@ -20,7 +20,7 @@ kubernetes_input.yml
the pod and containers described in the YAML. The containers within the pod are then started and
the ID of the new Pod is output.
-Ideally the input file would be one created by Podman. This would guarantee a smooth import and expected results.
+Ideally the input file would be one created by Podman (see podman-generate-kube(1)). This would guarantee a smooth import and expected results.
# OPTIONS:
@@ -72,7 +72,7 @@ $ podman play kube demo.yml
```
## SEE ALSO
-podman(1), podman-container(1), podman-pod(1), podman-generate(1), podman-play(1)
+podman(1), podman-container(1), podman-pod(1), podman-generate-kube(1), podman-play(1)
# HISTORY
Decemeber 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
diff --git a/libpod.conf b/libpod.conf
index 8d6158ed5..211ba106d 100644
--- a/libpod.conf
+++ b/libpod.conf
@@ -93,6 +93,12 @@ pause_command = "/pause"
# 'podman system renumber' command).
num_locks = 2048
+# Directory for libpod named volumes.
+# By default, this will be configured relative to where containers/storage
+# stores containers.
+# Uncomment to change location from this default.
+#volume_path = "/var/lib/containers/storage/volumes"
+
# Default OCI runtime
runtime = "runc"
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 25ef5cd0e..c226a0617 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -261,12 +261,14 @@ func (s *BoltState) GetDBConfig() (*DBConfig, error) {
storageRoot := configBucket.Get(graphRootKey)
storageTmp := configBucket.Get(runRootKey)
graphDriver := configBucket.Get(graphDriverKey)
+ volumePath := configBucket.Get(volPathKey)
cfg.LibpodRoot = string(libpodRoot)
cfg.LibpodTmp = string(libpodTmp)
cfg.StorageRoot = string(storageRoot)
cfg.StorageTmp = string(storageTmp)
cfg.GraphDriver = string(graphDriver)
+ cfg.VolumePath = string(volumePath)
return nil
})
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index 3d749849d..936ccbf4c 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -38,6 +38,7 @@ const (
graphRootName = "graph-root"
graphDriverName = "graph-driver-name"
osName = "os"
+ volPathName = "volume-path"
)
var (
@@ -67,6 +68,7 @@ var (
graphRootKey = []byte(graphRootName)
graphDriverKey = []byte(graphDriverName)
osKey = []byte(osName)
+ volPathKey = []byte(volPathName)
)
// Check if the configuration of the database is compatible with the
@@ -105,10 +107,15 @@ func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error {
return err
}
- return validateDBAgainstConfig(configBkt, "storage graph driver",
+ if err := validateDBAgainstConfig(configBkt, "storage graph driver",
rt.config.StorageConfig.GraphDriverName,
graphDriverKey,
- storage.DefaultStoreOptions.GraphDriverName)
+ storage.DefaultStoreOptions.GraphDriverName); err != nil {
+ return err
+ }
+
+ return validateDBAgainstConfig(configBkt, "volume path",
+ rt.config.VolumePath, volPathKey, "")
})
return err
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index f182b6bdf..b074efa3a 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -481,6 +481,19 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
if c.state.State != ContainerStateRunning {
return errors.Wrapf(ErrCtrStateInvalid, "%q is not running, cannot checkpoint", c.state.State)
}
+
+ // Create the CRIU log file and label it
+ dumpLog := filepath.Join(c.bundlePath(), "dump.log")
+
+ logFile, err := os.OpenFile(dumpLog, os.O_CREATE, 0600)
+ if err != nil {
+ return errors.Wrapf(err, "failed to create CRIU log file %q", dumpLog)
+ }
+ logFile.Close()
+ if err = label.SetFileLabel(dumpLog, c.MountLabel()); err != nil {
+ return errors.Wrapf(err, "failed to label CRIU log file %q", dumpLog)
+ }
+
if err := c.runtime.ociRuntime.checkpointContainer(c, options); err != nil {
return err
}
diff --git a/libpod/info.go b/libpod/info.go
index 191ce6810..62088b730 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -121,6 +121,7 @@ func (r *Runtime) storeInfo() (map[string]interface{}, error) {
info["RunRoot"] = r.store.RunRoot()
info["GraphDriverName"] = r.store.GraphDriverName()
info["GraphOptions"] = r.store.GraphOptions()
+ info["VolumePath"] = r.config.VolumePath
statusPairs, err := r.store.Status()
if err != nil {
return nil, err
diff --git a/libpod/options.go b/libpod/options.go
index e22c81f91..1e8592a25 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -47,6 +47,11 @@ func WithStorageConfig(config storage.StoreOptions) RuntimeOption {
rt.config.StaticDir = filepath.Join(config.GraphRoot, "libpod")
rt.configuredFrom.libpodStaticDirSet = true
+ // Also set libpod volume path, so we are a subdirectory
+ // of the c/storage store by default
+ rt.config.VolumePath = filepath.Join(config.GraphRoot, "volumes")
+ rt.configuredFrom.volPathSet = true
+
setField = true
}
@@ -359,6 +364,7 @@ func WithVolumePath(volPath string) RuntimeOption {
}
rt.config.VolumePath = volPath
+ rt.configuredFrom.volPathSet = true
return nil
}
@@ -1242,6 +1248,22 @@ func WithVolumeOptions(options map[string]string) VolumeCreateOption {
}
}
+// withSetCtrSpecific sets a bool notifying libpod that a volume was created
+// specifically for a container.
+// These volumes will be removed when the container is removed and volumes are
+// also specified for removal.
+func withSetCtrSpecific() VolumeCreateOption {
+ return func(volume *Volume) error {
+ if volume.valid {
+ return ErrVolumeFinalized
+ }
+
+ volume.config.IsCtrSpecific = true
+
+ return nil
+ }
+}
+
// Pod Creation Options
// WithPodName sets the name of the pod.
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 94dbf37dd..827c22f5b 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -123,7 +123,10 @@ type RuntimeConfig struct {
// Not included in on-disk config, use the dedicated containers/storage
// configuration file instead
StorageConfig storage.StoreOptions `toml:"-"`
- VolumePath string `toml:"volume_path"`
+ // VolumePath is the default location that named volumes will be created
+ // under. This convention is followed by the default volume driver, but
+ // may not be by other drivers.
+ VolumePath string `toml:"volume_path"`
// ImageDefaultTransport is the default transport method used to fetch
// images
ImageDefaultTransport string `toml:"image_default_transport"`
@@ -232,12 +235,14 @@ type runtimeConfiguredFrom struct {
storageRunRootSet bool
libpodStaticDirSet bool
libpodTmpDirSet bool
+ volPathSet bool
}
var (
defaultRuntimeConfig = RuntimeConfig{
// Leave this empty so containers/storage will use its defaults
StorageConfig: storage.StoreOptions{},
+ VolumePath: filepath.Join(storage.DefaultStoreOptions.GraphRoot, "volumes"),
ImageDefaultTransport: DefaultTransport,
StateType: BoltDBStateStore,
OCIRuntime: "runc",
@@ -400,6 +405,9 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
if tmpConfig.TmpDir != "" {
runtime.configuredFrom.libpodTmpDirSet = true
}
+ if tmpConfig.VolumePath != "" {
+ runtime.configuredFrom.volPathSet = true
+ }
if _, err := toml.Decode(string(contents), runtime.config); err != nil {
return nil, errors.Wrapf(err, "error decoding configuration file %s", configPath)
@@ -526,6 +534,16 @@ func makeRuntime(runtime *Runtime) (err error) {
if runtime.config.OCIRuntime != "" && runtime.config.OCIRuntime[0] == '/' {
foundRuntime = true
runtime.ociRuntimePath = OCIRuntimePath{Name: filepath.Base(runtime.config.OCIRuntime), Paths: []string{runtime.config.OCIRuntime}}
+ stat, err := os.Stat(runtime.config.OCIRuntime)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return errors.Wrapf(err, "the specified OCI runtime %s does not exist", runtime.config.OCIRuntime)
+ }
+ return errors.Wrapf(err, "cannot stat the OCI runtime path %s", runtime.config.OCIRuntime)
+ }
+ if !stat.Mode().IsRegular() {
+ return fmt.Errorf("the specified OCI runtime %s is not a valid file", runtime.config.OCIRuntime)
+ }
} else {
// If not, look it up in the configuration.
paths := runtime.config.OCIRuntimes[runtime.config.OCIRuntime]
@@ -614,29 +632,52 @@ func makeRuntime(runtime *Runtime) (err error) {
if !runtime.configuredFrom.storageGraphDriverSet && dbConfig.GraphDriver != "" {
if runtime.config.StorageConfig.GraphDriverName != dbConfig.GraphDriver &&
runtime.config.StorageConfig.GraphDriverName != "" {
- logrus.Errorf("User-selected graph driver %s overwritten by graph driver %s from database - delete libpod local files to resolve",
+ logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve",
runtime.config.StorageConfig.GraphDriverName, dbConfig.GraphDriver)
}
runtime.config.StorageConfig.GraphDriverName = dbConfig.GraphDriver
}
if !runtime.configuredFrom.storageGraphRootSet && dbConfig.StorageRoot != "" {
+ if runtime.config.StorageConfig.GraphRoot != dbConfig.StorageRoot &&
+ runtime.config.StorageConfig.GraphRoot != "" {
+ logrus.Debugf("Overriding graph root %q with %q from database",
+ runtime.config.StorageConfig.GraphRoot, dbConfig.StorageRoot)
+ }
runtime.config.StorageConfig.GraphRoot = dbConfig.StorageRoot
}
if !runtime.configuredFrom.storageRunRootSet && dbConfig.StorageTmp != "" {
+ if runtime.config.StorageConfig.RunRoot != dbConfig.StorageTmp &&
+ runtime.config.StorageConfig.RunRoot != "" {
+ logrus.Debugf("Overriding run root %q with %q from database",
+ runtime.config.StorageConfig.RunRoot, dbConfig.StorageTmp)
+ }
runtime.config.StorageConfig.RunRoot = dbConfig.StorageTmp
}
if !runtime.configuredFrom.libpodStaticDirSet && dbConfig.LibpodRoot != "" {
+ if runtime.config.StaticDir != dbConfig.LibpodRoot && runtime.config.StaticDir != "" {
+ logrus.Debugf("Overriding static dir %q with %q from database", runtime.config.StaticDir, dbConfig.LibpodRoot)
+ }
runtime.config.StaticDir = dbConfig.LibpodRoot
}
if !runtime.configuredFrom.libpodTmpDirSet && dbConfig.LibpodTmp != "" {
+ if runtime.config.TmpDir != dbConfig.LibpodTmp && runtime.config.TmpDir != "" {
+ logrus.Debugf("Overriding tmp dir %q with %q from database", runtime.config.TmpDir, dbConfig.LibpodTmp)
+ }
runtime.config.TmpDir = dbConfig.LibpodTmp
}
+ if !runtime.configuredFrom.volPathSet && dbConfig.VolumePath != "" {
+ if runtime.config.VolumePath != dbConfig.VolumePath && runtime.config.VolumePath != "" {
+ logrus.Debugf("Overriding volume path %q with %q from database", runtime.config.VolumePath, dbConfig.VolumePath)
+ }
+ runtime.config.VolumePath = dbConfig.VolumePath
+ }
logrus.Debugf("Using graph driver %s", runtime.config.StorageConfig.GraphDriverName)
logrus.Debugf("Using graph root %s", runtime.config.StorageConfig.GraphRoot)
logrus.Debugf("Using run root %s", runtime.config.StorageConfig.RunRoot)
logrus.Debugf("Using static dir %s", runtime.config.StaticDir)
logrus.Debugf("Using tmp dir %s", runtime.config.TmpDir)
+ logrus.Debugf("Using volume path %s", runtime.config.VolumePath)
// Validate our config against the database, now that we've set our
// final storage configuration
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 2ec8d0795..cfa4f9654 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -180,7 +180,7 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ..
if vol.Source[0] != '/' && isNamedVolume(vol.Source) {
volInfo, err := r.state.Volume(vol.Source)
if err != nil {
- newVol, err := r.newVolume(ctx, WithVolumeName(vol.Source))
+ newVol, err := r.newVolume(ctx, WithVolumeName(vol.Source), withSetCtrSpecific())
if err != nil {
return nil, errors.Wrapf(err, "error creating named volume %q", vol.Source)
}
@@ -421,6 +421,9 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
for _, v := range volumes {
if volume, err := runtime.state.Volume(v); err == nil {
+ if !volume.IsCtrSpecific() {
+ continue
+ }
if err := runtime.removeVolume(ctx, volume, false); err != nil && err != ErrNoSuchVolume && err != ErrVolumeBeingUsed {
logrus.Errorf("cleanup volume (%s): %v", v, err)
}
diff --git a/libpod/state.go b/libpod/state.go
index 98282fc83..4296fc3cd 100644
--- a/libpod/state.go
+++ b/libpod/state.go
@@ -8,6 +8,7 @@ type DBConfig struct {
StorageRoot string
StorageTmp string
GraphDriver string
+ VolumePath string
}
// State is a storage backend for libpod's current state.
diff --git a/libpod/volume.go b/libpod/volume.go
index 74878b6a4..0c7618841 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -15,11 +15,12 @@ type VolumeConfig struct {
// Name of the volume
Name string `json:"name"`
- Labels map[string]string `json:"labels"`
- MountPoint string `json:"mountPoint"`
- Driver string `json:"driver"`
- Options map[string]string `json:"options"`
- Scope string `json:"scope"`
+ Labels map[string]string `json:"labels"`
+ MountPoint string `json:"mountPoint"`
+ Driver string `json:"driver"`
+ Options map[string]string `json:"options"`
+ Scope string `json:"scope"`
+ IsCtrSpecific bool `json:"ctrSpecific"`
}
// Name retrieves the volume's name
@@ -60,3 +61,10 @@ func (v *Volume) Options() map[string]string {
func (v *Volume) Scope() string {
return v.config.Scope
}
+
+// IsCtrSpecific returns whether this volume was created specifically for a
+// given container. Images with this set to true will be removed when the
+// container is removed with the Volumes parameter set to true.
+func (v *Volume) IsCtrSpecific() bool {
+ return v.config.IsCtrSpecific
+}
diff --git a/vendor.conf b/vendor.conf
index 445f0844a..678807d1c 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -15,7 +15,7 @@ github.com/containerd/cgroups 39b18af02c4120960f517a3a4c2588fabb61d02c
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
github.com/containernetworking/cni v0.7.0-alpha1
github.com/containernetworking/plugins v0.7.4
-github.com/containers/image v1.4
+github.com/containers/image v1.5
github.com/vbauerster/mpb v3.3.4
github.com/mattn/go-isatty v0.0.4
github.com/VividCortex/ewma v1.1.1
diff --git a/vendor/github.com/containers/image/pkg/blobinfocache/memory.go b/vendor/github.com/containers/image/pkg/blobinfocache/memory.go
index 1ce7dee13..cf6ca5263 100644
--- a/vendor/github.com/containers/image/pkg/blobinfocache/memory.go
+++ b/vendor/github.com/containers/image/pkg/blobinfocache/memory.go
@@ -1,6 +1,7 @@
package blobinfocache
import (
+ "sync"
"time"
"github.com/containers/image/types"
@@ -17,6 +18,7 @@ type locationKey struct {
// memoryCache implements an in-memory-only BlobInfoCache
type memoryCache struct {
+ mutex *sync.Mutex // synchronizes concurrent accesses
uncompressedDigests map[digest.Digest]digest.Digest
digestsByUncompressed map[digest.Digest]map[digest.Digest]struct{} // stores a set of digests for each uncompressed digest
knownLocations map[locationKey]map[types.BICLocationReference]time.Time // stores last known existence time for each location reference
@@ -28,6 +30,7 @@ type memoryCache struct {
// Manual users of types.{ImageSource,ImageDestination} might also use this instead of a persistent cache.
func NewMemoryCache() types.BlobInfoCache {
return &memoryCache{
+ mutex: new(sync.Mutex),
uncompressedDigests: map[digest.Digest]digest.Digest{},
digestsByUncompressed: map[digest.Digest]map[digest.Digest]struct{}{},
knownLocations: map[locationKey]map[types.BICLocationReference]time.Time{},
@@ -38,6 +41,15 @@ func NewMemoryCache() types.BlobInfoCache {
// May return anyDigest if it is known to be uncompressed.
// Returns "" if nothing is known about the digest (it may be compressed or uncompressed).
func (mem *memoryCache) UncompressedDigest(anyDigest digest.Digest) digest.Digest {
+ mem.mutex.Lock()
+ defer mem.mutex.Unlock()
+ return mem.uncompressedDigest(anyDigest)
+}
+
+// uncompressedDigest returns an uncompressed digest corresponding to anyDigest.
+// May return anyDigest if it is known to be uncompressed.
+// Returns "" if nothing is known about the digest (it may be compressed or uncompressed).
+func (mem *memoryCache) uncompressedDigest(anyDigest digest.Digest) digest.Digest {
if d, ok := mem.uncompressedDigests[anyDigest]; ok {
return d
}
@@ -56,6 +68,8 @@ func (mem *memoryCache) UncompressedDigest(anyDigest digest.Digest) digest.Diges
// because a manifest/config pair exists); otherwise the cache could be poisoned and allow substituting unexpected blobs.
// (Eventually, the DiffIDs in image config could detect the substitution, but that may be too late, and not all image formats contain that data.)
func (mem *memoryCache) RecordDigestUncompressedPair(anyDigest digest.Digest, uncompressed digest.Digest) {
+ mem.mutex.Lock()
+ defer mem.mutex.Unlock()
if previous, ok := mem.uncompressedDigests[anyDigest]; ok && previous != uncompressed {
logrus.Warnf("Uncompressed digest for blob %s previously recorded as %s, now %s", anyDigest, previous, uncompressed)
}
@@ -72,6 +86,8 @@ func (mem *memoryCache) RecordDigestUncompressedPair(anyDigest digest.Digest, un
// RecordKnownLocation records that a blob with the specified digest exists within the specified (transport, scope) scope,
// and can be reused given the opaque location data.
func (mem *memoryCache) RecordKnownLocation(transport types.ImageTransport, scope types.BICTransportScope, blobDigest digest.Digest, location types.BICLocationReference) {
+ mem.mutex.Lock()
+ defer mem.mutex.Unlock()
key := locationKey{transport: transport.Name(), scope: scope, blobDigest: blobDigest}
locationScope, ok := mem.knownLocations[key]
if !ok {
@@ -103,11 +119,13 @@ func (mem *memoryCache) appendReplacementCandidates(candidates []candidateWithTi
// data from previous RecordDigestUncompressedPair calls is used to also look up variants of the blob which have the same
// uncompressed digest.
func (mem *memoryCache) CandidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute bool) []types.BICReplacementCandidate {
+ mem.mutex.Lock()
+ defer mem.mutex.Unlock()
res := []candidateWithTime{}
res = mem.appendReplacementCandidates(res, transport, scope, primaryDigest)
var uncompressedDigest digest.Digest // = ""
if canSubstitute {
- if uncompressedDigest = mem.UncompressedDigest(primaryDigest); uncompressedDigest != "" {
+ if uncompressedDigest = mem.uncompressedDigest(primaryDigest); uncompressedDigest != "" {
otherDigests := mem.digestsByUncompressed[uncompressedDigest] // nil if not present in the map
for d := range otherDigests {
if d != primaryDigest && d != uncompressedDigest {
diff --git a/vendor/github.com/containers/image/version/version.go b/vendor/github.com/containers/image/version/version.go
index 10075992d..2a3bc1b5c 100644
--- a/vendor/github.com/containers/image/version/version.go
+++ b/vendor/github.com/containers/image/version/version.go
@@ -11,7 +11,7 @@ const (
VersionPatch = 5
// VersionDev indicates development branch. Releases will be empty string.
- VersionDev = "-dev"
+ VersionDev = ""
)
// Version is the specification version that the package types support.