Signed-off-by: Brian Goff <cpuguy83@gmail.com>
| ... | ... |
@@ -179,11 +179,6 @@ func (daemon *Daemon) restore() error {
|
| 179 | 179 |
delete(containers, id) |
| 180 | 180 |
continue |
| 181 | 181 |
} |
| 182 |
- // verify that all volumes valid and have been migrated from the pre-1.7 layout |
|
| 183 |
- if err := daemon.verifyVolumesInfo(c); err != nil {
|
|
| 184 |
- // don't skip the container due to error |
|
| 185 |
- logrus.Errorf("Failed to verify volumes for container '%s': %v", c.ID, err)
|
|
| 186 |
- } |
|
| 187 | 182 |
if err := daemon.Register(c); err != nil {
|
| 188 | 183 |
logrus.Errorf("Failed to register container %s: %s", c.ID, err)
|
| 189 | 184 |
delete(containers, id) |
| ... | ... |
@@ -6,18 +6,11 @@ import ( |
| 6 | 6 |
"errors" |
| 7 | 7 |
"io/ioutil" |
| 8 | 8 |
"os" |
| 9 |
- "path/filepath" |
|
| 10 | 9 |
"testing" |
| 11 | 10 |
|
| 12 | 11 |
containertypes "github.com/docker/docker/api/types/container" |
| 13 | 12 |
"github.com/docker/docker/container" |
| 14 | 13 |
"github.com/docker/docker/daemon/config" |
| 15 |
- "github.com/docker/docker/pkg/idtools" |
|
| 16 |
- "github.com/docker/docker/volume" |
|
| 17 |
- "github.com/docker/docker/volume/drivers" |
|
| 18 |
- "github.com/docker/docker/volume/local" |
|
| 19 |
- "github.com/docker/docker/volume/store" |
|
| 20 |
- "github.com/gotestyourself/gotestyourself/assert" |
|
| 21 | 14 |
) |
| 22 | 15 |
|
| 23 | 16 |
type fakeContainerGetter struct {
|
| ... | ... |
@@ -273,85 +266,3 @@ func TestNetworkOptions(t *testing.T) {
|
| 273 | 273 |
t.Fatal("Expected networkOptions error, got nil")
|
| 274 | 274 |
} |
| 275 | 275 |
} |
| 276 |
- |
|
| 277 |
-func TestMigratePre17Volumes(t *testing.T) {
|
|
| 278 |
- rootDir, err := ioutil.TempDir("", "test-daemon-volumes")
|
|
| 279 |
- if err != nil {
|
|
| 280 |
- t.Fatal(err) |
|
| 281 |
- } |
|
| 282 |
- defer os.RemoveAll(rootDir) |
|
| 283 |
- |
|
| 284 |
- volumeRoot := filepath.Join(rootDir, "volumes") |
|
| 285 |
- err = os.MkdirAll(volumeRoot, 0755) |
|
| 286 |
- if err != nil {
|
|
| 287 |
- t.Fatal(err) |
|
| 288 |
- } |
|
| 289 |
- |
|
| 290 |
- containerRoot := filepath.Join(rootDir, "containers") |
|
| 291 |
- cid := "1234" |
|
| 292 |
- err = os.MkdirAll(filepath.Join(containerRoot, cid), 0755) |
|
| 293 |
- assert.NilError(t, err) |
|
| 294 |
- |
|
| 295 |
- vid := "5678" |
|
| 296 |
- vfsPath := filepath.Join(rootDir, "vfs", "dir", vid) |
|
| 297 |
- err = os.MkdirAll(vfsPath, 0755) |
|
| 298 |
- assert.NilError(t, err) |
|
| 299 |
- |
|
| 300 |
- config := []byte(` |
|
| 301 |
- {
|
|
| 302 |
- "ID": "` + cid + `", |
|
| 303 |
- "Volumes": {
|
|
| 304 |
- "/foo": "` + vfsPath + `", |
|
| 305 |
- "/bar": "/foo", |
|
| 306 |
- "/quux": "/quux" |
|
| 307 |
- }, |
|
| 308 |
- "VolumesRW": {
|
|
| 309 |
- "/foo": true, |
|
| 310 |
- "/bar": true, |
|
| 311 |
- "/quux": false |
|
| 312 |
- } |
|
| 313 |
- } |
|
| 314 |
- `) |
|
| 315 |
- |
|
| 316 |
- volStore, err := store.New(volumeRoot) |
|
| 317 |
- if err != nil {
|
|
| 318 |
- t.Fatal(err) |
|
| 319 |
- } |
|
| 320 |
- drv, err := local.New(volumeRoot, idtools.IDPair{UID: 0, GID: 0})
|
|
| 321 |
- if err != nil {
|
|
| 322 |
- t.Fatal(err) |
|
| 323 |
- } |
|
| 324 |
- volumedrivers.Register(drv, volume.DefaultDriverName) |
|
| 325 |
- |
|
| 326 |
- daemon := &Daemon{
|
|
| 327 |
- root: rootDir, |
|
| 328 |
- repository: containerRoot, |
|
| 329 |
- volumes: volStore, |
|
| 330 |
- } |
|
| 331 |
- err = ioutil.WriteFile(filepath.Join(containerRoot, cid, "config.v2.json"), config, 600) |
|
| 332 |
- if err != nil {
|
|
| 333 |
- t.Fatal(err) |
|
| 334 |
- } |
|
| 335 |
- c, err := daemon.load(cid) |
|
| 336 |
- if err != nil {
|
|
| 337 |
- t.Fatal(err) |
|
| 338 |
- } |
|
| 339 |
- if err := daemon.verifyVolumesInfo(c); err != nil {
|
|
| 340 |
- t.Fatal(err) |
|
| 341 |
- } |
|
| 342 |
- |
|
| 343 |
- expected := map[string]volume.MountPoint{
|
|
| 344 |
- "/foo": {Destination: "/foo", RW: true, Name: vid},
|
|
| 345 |
- "/bar": {Source: "/foo", Destination: "/bar", RW: true},
|
|
| 346 |
- "/quux": {Source: "/quux", Destination: "/quux", RW: false},
|
|
| 347 |
- } |
|
| 348 |
- for id, mp := range c.MountPoints {
|
|
| 349 |
- x, exists := expected[id] |
|
| 350 |
- if !exists {
|
|
| 351 |
- t.Fatal("volume not migrated")
|
|
| 352 |
- } |
|
| 353 |
- if mp.Source != x.Source || mp.Destination != x.Destination || mp.RW != x.RW || mp.Name != x.Name {
|
|
| 354 |
- t.Fatalf("got unexpected mountpoint, expected: %+v, got: %+v", x, mp)
|
|
| 355 |
- } |
|
| 356 |
- } |
|
| 357 |
-} |
| ... | ... |
@@ -632,13 +632,6 @@ func setupDaemonProcess(config *config.Config) error {
|
| 632 | 632 |
return nil |
| 633 | 633 |
} |
| 634 | 634 |
|
| 635 |
-// verifyVolumesInfo is a no-op on windows. |
|
| 636 |
-// This is called during daemon initialization to migrate volumes from pre-1.7. |
|
| 637 |
-// volumes were not supported on windows pre-1.7 |
|
| 638 |
-func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error {
|
|
| 639 |
- return nil |
|
| 640 |
-} |
|
| 641 |
- |
|
| 642 | 635 |
func (daemon *Daemon) setupSeccompProfile() error {
|
| 643 | 636 |
return nil |
| 644 | 637 |
} |
| ... | ... |
@@ -3,10 +3,8 @@ |
| 3 | 3 |
package daemon // import "github.com/docker/docker/daemon" |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
- "encoding/json" |
|
| 7 | 6 |
"fmt" |
| 8 | 7 |
"os" |
| 9 |
- "path/filepath" |
|
| 10 | 8 |
"sort" |
| 11 | 9 |
"strconv" |
| 12 | 10 |
"strings" |
| ... | ... |
@@ -15,9 +13,6 @@ import ( |
| 15 | 15 |
"github.com/docker/docker/pkg/fileutils" |
| 16 | 16 |
"github.com/docker/docker/pkg/mount" |
| 17 | 17 |
"github.com/docker/docker/volume" |
| 18 |
- "github.com/docker/docker/volume/drivers" |
|
| 19 |
- "github.com/docker/docker/volume/local" |
|
| 20 |
- "github.com/pkg/errors" |
|
| 21 | 18 |
) |
| 22 | 19 |
|
| 23 | 20 |
// setupMounts iterates through each of the mount points for a container and |
| ... | ... |
@@ -113,80 +108,6 @@ func setBindModeIfNull(bind *volume.MountPoint) {
|
| 113 | 113 |
} |
| 114 | 114 |
} |
| 115 | 115 |
|
| 116 |
-// migrateVolume links the contents of a volume created pre Docker 1.7 |
|
| 117 |
-// into the location expected by the local driver. |
|
| 118 |
-// It creates a symlink from DOCKER_ROOT/vfs/dir/VOLUME_ID to DOCKER_ROOT/volumes/VOLUME_ID/_container_data. |
|
| 119 |
-// It preserves the volume json configuration generated pre Docker 1.7 to be able to |
|
| 120 |
-// downgrade from Docker 1.7 to Docker 1.6 without losing volume compatibility. |
|
| 121 |
-func migrateVolume(id, vfs string) error {
|
|
| 122 |
- l, err := volumedrivers.GetDriver(volume.DefaultDriverName) |
|
| 123 |
- if err != nil {
|
|
| 124 |
- return err |
|
| 125 |
- } |
|
| 126 |
- |
|
| 127 |
- newDataPath := l.(*local.Root).DataPath(id) |
|
| 128 |
- fi, err := os.Stat(newDataPath) |
|
| 129 |
- if err != nil && !os.IsNotExist(err) {
|
|
| 130 |
- return err |
|
| 131 |
- } |
|
| 132 |
- |
|
| 133 |
- if fi != nil && fi.IsDir() {
|
|
| 134 |
- return nil |
|
| 135 |
- } |
|
| 136 |
- |
|
| 137 |
- return os.Symlink(vfs, newDataPath) |
|
| 138 |
-} |
|
| 139 |
- |
|
| 140 |
-// verifyVolumesInfo ports volumes configured for the containers pre docker 1.7. |
|
| 141 |
-// It reads the container configuration and creates valid mount points for the old volumes. |
|
| 142 |
-func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error {
|
|
| 143 |
- container.Lock() |
|
| 144 |
- defer container.Unlock() |
|
| 145 |
- |
|
| 146 |
- // Inspect old structures only when we're upgrading from old versions |
|
| 147 |
- // to versions >= 1.7 and the MountPoints has not been populated with volumes data. |
|
| 148 |
- type volumes struct {
|
|
| 149 |
- Volumes map[string]string |
|
| 150 |
- VolumesRW map[string]bool |
|
| 151 |
- } |
|
| 152 |
- cfgPath, err := container.ConfigPath() |
|
| 153 |
- if err != nil {
|
|
| 154 |
- return err |
|
| 155 |
- } |
|
| 156 |
- f, err := os.Open(cfgPath) |
|
| 157 |
- if err != nil {
|
|
| 158 |
- return errors.Wrap(err, "could not open container config") |
|
| 159 |
- } |
|
| 160 |
- defer f.Close() |
|
| 161 |
- var cv volumes |
|
| 162 |
- if err := json.NewDecoder(f).Decode(&cv); err != nil {
|
|
| 163 |
- return errors.Wrap(err, "could not decode container config") |
|
| 164 |
- } |
|
| 165 |
- |
|
| 166 |
- if len(container.MountPoints) == 0 && len(cv.Volumes) > 0 {
|
|
| 167 |
- for destination, hostPath := range cv.Volumes {
|
|
| 168 |
- vfsPath := filepath.Join(daemon.root, "vfs", "dir") |
|
| 169 |
- rw := cv.VolumesRW != nil && cv.VolumesRW[destination] |
|
| 170 |
- |
|
| 171 |
- if strings.HasPrefix(hostPath, vfsPath) {
|
|
| 172 |
- id := filepath.Base(hostPath) |
|
| 173 |
- v, err := daemon.volumes.CreateWithRef(id, volume.DefaultDriverName, container.ID, nil, nil) |
|
| 174 |
- if err != nil {
|
|
| 175 |
- return err |
|
| 176 |
- } |
|
| 177 |
- if err := migrateVolume(id, hostPath); err != nil {
|
|
| 178 |
- return err |
|
| 179 |
- } |
|
| 180 |
- container.AddMountPointWithVolume(destination, v, true) |
|
| 181 |
- } else { // Bind mount
|
|
| 182 |
- m := volume.MountPoint{Source: hostPath, Destination: destination, RW: rw}
|
|
| 183 |
- container.MountPoints[destination] = &m |
|
| 184 |
- } |
|
| 185 |
- } |
|
| 186 |
- } |
|
| 187 |
- return nil |
|
| 188 |
-} |
|
| 189 |
- |
|
| 190 | 116 |
func (daemon *Daemon) mountVolumes(container *container.Container) error {
|
| 191 | 117 |
mounts, err := daemon.setupMounts(container) |
| 192 | 118 |
if err != nil {
|
| ... | ... |
@@ -35,7 +35,6 @@ import ( |
| 35 | 35 |
testdaemon "github.com/docker/docker/internal/test/daemon" |
| 36 | 36 |
"github.com/docker/docker/opts" |
| 37 | 37 |
"github.com/docker/docker/pkg/mount" |
| 38 |
- "github.com/docker/docker/pkg/stringid" |
|
| 39 | 38 |
units "github.com/docker/go-units" |
| 40 | 39 |
"github.com/docker/libnetwork/iptables" |
| 41 | 40 |
"github.com/docker/libtrust" |
| ... | ... |
@@ -2672,84 +2671,6 @@ func (s *DockerDaemonSuite) TestDaemonRestartSaveContainerExitCode(c *check.C) {
|
| 2672 | 2672 |
c.Assert(out, checker.Equals, errMsg1) |
| 2673 | 2673 |
} |
| 2674 | 2674 |
|
| 2675 |
-func (s *DockerDaemonSuite) TestDaemonBackcompatPre17Volumes(c *check.C) {
|
|
| 2676 |
- testRequires(c, SameHostDaemon) |
|
| 2677 |
- d := s.d |
|
| 2678 |
- d.StartWithBusybox(c) |
|
| 2679 |
- |
|
| 2680 |
- // hack to be able to side-load a container config |
|
| 2681 |
- out, err := d.Cmd("create", "busybox:latest")
|
|
| 2682 |
- c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 2683 |
- id := strings.TrimSpace(out) |
|
| 2684 |
- |
|
| 2685 |
- out, err = d.Cmd("inspect", "--type=image", "--format={{.ID}}", "busybox:latest")
|
|
| 2686 |
- c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 2687 |
- d.Stop(c) |
|
| 2688 |
- <-d.Wait |
|
| 2689 |
- |
|
| 2690 |
- imageID := strings.TrimSpace(out) |
|
| 2691 |
- volumeID := stringid.GenerateNonCryptoID() |
|
| 2692 |
- vfsPath := filepath.Join(d.Root, "vfs", "dir", volumeID) |
|
| 2693 |
- c.Assert(os.MkdirAll(vfsPath, 0755), checker.IsNil) |
|
| 2694 |
- |
|
| 2695 |
- config := []byte(` |
|
| 2696 |
- {
|
|
| 2697 |
- "ID": "` + id + `", |
|
| 2698 |
- "Name": "hello", |
|
| 2699 |
- "Driver": "` + d.StorageDriver() + `", |
|
| 2700 |
- "Image": "` + imageID + `", |
|
| 2701 |
- "Config": {"Image": "busybox:latest"},
|
|
| 2702 |
- "NetworkSettings": {},
|
|
| 2703 |
- "Volumes": {
|
|
| 2704 |
- "/bar":"/foo", |
|
| 2705 |
- "/foo": "` + vfsPath + `", |
|
| 2706 |
- "/quux":"/quux" |
|
| 2707 |
- }, |
|
| 2708 |
- "VolumesRW": {
|
|
| 2709 |
- "/bar": true, |
|
| 2710 |
- "/foo": true, |
|
| 2711 |
- "/quux": false |
|
| 2712 |
- } |
|
| 2713 |
- } |
|
| 2714 |
- `) |
|
| 2715 |
- |
|
| 2716 |
- configPath := filepath.Join(d.Root, "containers", id, "config.v2.json") |
|
| 2717 |
- c.Assert(ioutil.WriteFile(configPath, config, 600), checker.IsNil) |
|
| 2718 |
- d.Start(c) |
|
| 2719 |
- |
|
| 2720 |
- out, err = d.Cmd("inspect", "--type=container", "--format={{ json .Mounts }}", id)
|
|
| 2721 |
- c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 2722 |
- type mount struct {
|
|
| 2723 |
- Name string |
|
| 2724 |
- Source string |
|
| 2725 |
- Destination string |
|
| 2726 |
- Driver string |
|
| 2727 |
- RW bool |
|
| 2728 |
- } |
|
| 2729 |
- |
|
| 2730 |
- ls := []mount{}
|
|
| 2731 |
- err = json.NewDecoder(strings.NewReader(out)).Decode(&ls) |
|
| 2732 |
- c.Assert(err, checker.IsNil) |
|
| 2733 |
- |
|
| 2734 |
- expected := []mount{
|
|
| 2735 |
- {Source: "/foo", Destination: "/bar", RW: true},
|
|
| 2736 |
- {Name: volumeID, Destination: "/foo", RW: true},
|
|
| 2737 |
- {Source: "/quux", Destination: "/quux", RW: false},
|
|
| 2738 |
- } |
|
| 2739 |
- c.Assert(ls, checker.HasLen, len(expected)) |
|
| 2740 |
- |
|
| 2741 |
- for _, m := range ls {
|
|
| 2742 |
- var matched bool |
|
| 2743 |
- for _, x := range expected {
|
|
| 2744 |
- if m.Source == x.Source && m.Destination == x.Destination && m.RW == x.RW || m.Name != x.Name {
|
|
| 2745 |
- matched = true |
|
| 2746 |
- break |
|
| 2747 |
- } |
|
| 2748 |
- } |
|
| 2749 |
- c.Assert(matched, checker.True, check.Commentf("did find match for %+v", m))
|
|
| 2750 |
- } |
|
| 2751 |
-} |
|
| 2752 |
- |
|
| 2753 | 2675 |
func (s *DockerDaemonSuite) TestDaemonWithUserlandProxyPath(c *check.C) {
|
| 2754 | 2676 |
testRequires(c, SameHostDaemon, DaemonIsLinux) |
| 2755 | 2677 |
|