From 562e4f1e23a52cff05078f68e21199514ba58250 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Thu, 10 Oct 2013 17:52:01 -0700 Subject: [PATCH] Verbose migration add warning for running container Conflicts: hack/make.sh runtime.go runtime_test.go --- hack/make.sh | 2 +- runtime.go | 125 +++++++++++++++++++++++++++++------------------- runtime_test.go | 2 +- 3 files changed, 78 insertions(+), 51 deletions(-) diff --git a/hack/make.sh b/hack/make.sh index 15380e6a53..62863bb8d8 100755 --- a/hack/make.sh +++ b/hack/make.sh @@ -44,7 +44,7 @@ if [ -n "$(git status --porcelain)" ]; then fi # Use these flags when compiling the tests and final binary -LDFLAGS='-X main.GITCOMMIT "'$GITCOMMIT'" -X main.VERSION "'$VERSION'" -w -linkmode external -extldflags "-lpthread -static -Wl,--unresolved-symbols=ignore-all"' +LDFLAGS='-X main.GITCOMMIT "'$GITCOMMIT'" -X main.VERSION "'$VERSION'" -w -linkmode external -extldflags "-static -Wl,--unresolved-symbols=ignore-in-shared-libs"' BUILDFLAGS='-tags netgo' bundle() { diff --git a/runtime.go b/runtime.go index 11b75f2e9c..578d374b38 100644 --- a/runtime.go +++ b/runtime.go @@ -287,7 +287,10 @@ func (runtime *Runtime) restore() error { return err } + deviceSet := runtime.deviceSet containers := []*Container{} + containersToMigrate := []*Container{} + for i, v := range dir { id := v.Name() container, err := runtime.load(id) @@ -300,68 +303,92 @@ func (runtime *Runtime) restore() error { } utils.Debugf("Loaded container %v", container.ID) containers = append(containers, container) + + if !deviceSet.HasDevice(container.ID) { + containersToMigrate = append(containersToMigrate, container) + } } - deviceSet := runtime.deviceSet - for _, container := range containers { - - // Perform a migration for aufs containers - if !deviceSet.HasDevice(container.ID) { - contents, err := ioutil.ReadDir(container.rwPath()) - if err != nil { - if !os.IsNotExist(err) { - utils.Debugf("[migration] Error reading rw dir %s", err) - } - continue - } - - if len(contents) > 0 { - utils.Debugf("[migration] Begin migration of %s", container.ID) - - image, err := runtime.graph.Get(container.Image) - if err != nil { - utils.Debugf("[migratoin] Failed to get image %s", err) - continue - } - - unmount := func() { - if err := image.Unmount(runtime, container.RootfsPath(), container.ID); err != nil { - utils.Debugf("[migraton] Failed to unmount image %s", err) - } - } - - if err := image.Mount(runtime, container.RootfsPath(), container.rwPath(), container.ID); err != nil { - utils.Debugf("[migratoin] Failed to mount image %s", err) - continue - } - - if err := image.applyLayer(container.rwPath(), container.RootfsPath()); err != nil { - utils.Debugf("[migration] Failed to apply layer %s", err) - unmount() - continue - } - - unmount() - - if err := os.RemoveAll(container.rwPath()); err != nil { - utils.Debugf("[migration] Failed to remove rw dir %s", err) - } - - utils.Debugf("[migration] End migration of %s", container.ID) - } + // Migrate AUFS containers to device mapper + if len(containersToMigrate) > 0 { + if err := migrateToDeviceMapper(runtime, containersToMigrate); err != nil { + return err } - } for _, container := range containers { if err := runtime.Register(container); err != nil { utils.Debugf("Failed to register container %s: %s", container.ID, err) + continue } } - if os.Getenv("DEBUG") == "" && os.Getenv("TEST") == "" { fmt.Printf("\bdone.\n") } + + return nil +} + +func migrateToDeviceMapper(runtime *Runtime, containers []*Container) error { + var ( + image *Image + contents []os.FileInfo + err error + ) + + fmt.Printf("Migrating %d containers to new storage backend\n", len(containers)) + for _, container := range containers { + if container.State.Running { + fmt.Printf("WARNING - Cannot migrate %s because the container is running. Please stop the container and relaunch the daemon!") + continue + } + + fmt.Printf("Migrating %s\n", container.ID) + + if contents, err = ioutil.ReadDir(container.rwPath()); err != nil { + if !os.IsNotExist(err) { + fmt.Printf("Error reading rw dir %s\n", err) + } + continue + } + + if len(contents) == 0 { + fmt.Printf("Skipping migration of %s because rw layer contains no changes\n") + continue + } + + if image, err = runtime.graph.Get(container.Image); err != nil { + fmt.Printf("Failed to fetch image %s\n", err) + continue + } + + unmount := func() { + if err = image.Unmount(runtime, container.RootfsPath(), container.ID); err != nil { + fmt.Printf("Failed to unmount image %s\n", err) + } + } + + if err = image.Mount(runtime, container.RootfsPath(), container.rwPath(), container.ID); err != nil { + fmt.Printf("Failed to mount image %s\n", err) + continue + } + + if err = image.applyLayer(container.rwPath(), container.RootfsPath()); err != nil { + fmt.Printf("Failed to apply layer in storage backend %s\n", err) + unmount() + continue + } + + unmount() + + if err = os.RemoveAll(container.rwPath()); err != nil { + fmt.Printf("Failed to remove rw layer %s\n", err) + } + + fmt.Printf("Successful migration for %s\n", container.ID) + } + fmt.Printf("Migration complete\n") + return nil } diff --git a/runtime_test.go b/runtime_test.go index 73697137bc..b3a2ccb16f 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -151,7 +151,7 @@ func init() { deviceset := devmapper.NewDeviceSetDM(unitTestStoreDevicesBase) // Create a device, which triggers the initiation of the base FS // This avoids other tests doing this and timing out - deviceset.AddDevice("init","") + deviceset.AddDevice("init", "") // Make it our Store root if runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, deviceset, false); err != nil {