[lxc-devel] [lxd/master] Improve handling of container storage on import

stgraber on Github lxc-bot at linuxcontainers.org
Mon Sep 10 05:26:07 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180910/367d38b3/attachment.bin>
-------------- next part --------------
From e67790097ce4d853141a75c6689341740ce66a56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 10 Sep 2018 00:24:30 -0400
Subject: [PATCH 1/3] lxd/containers: Avoid root device name conflict
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/containers_post.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index d142981c61..db4230672d 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -295,7 +295,7 @@ func createFromMigration(d *Daemon, req *api.ContainersPost) Response {
 			continue
 		}
 
-		args.Devices["root"] = rootDev
+		args.Devices[rootDevName] = rootDev
 	} else if localRootDiskDeviceKey != "" && localRootDiskDevice["pool"] == "" {
 		args.Devices[localRootDiskDeviceKey]["pool"] = storagePool
 	}

From b627f7d22093a3746a00b8825c30d4d334127f77 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 10 Sep 2018 00:32:09 -0400
Subject: [PATCH 2/3] lxd/import: Add root disk if needed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #5016

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/api_internal.go | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 1954b64eab..5bab2bfe44 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -797,6 +797,12 @@ func internalImport(d *Daemon, r *http.Request) Response {
 		}
 	}
 
+	// Prepare root disk entry if needed
+	rootDev := map[string]string{}
+	rootDev["type"] = "disk"
+	rootDev["path"] = "/"
+	rootDev["pool"] = containerPoolName
+
 	for _, snap := range existingSnapshots {
 		// Check if an entry for the snapshot already exists in the db.
 		_, snapErr := d.cluster.ContainerID(snap.Name)
@@ -851,6 +857,25 @@ func internalImport(d *Daemon, r *http.Request) Response {
 			return SmartError(err)
 		}
 
+		// Add root device if missing
+		root, _, _ := shared.GetRootDiskDevice(snap.Devices)
+		if root == "" {
+			if snap.Devices == nil {
+				snap.Devices = map[string]map[string]string{}
+			}
+
+			rootDevName := "root"
+			for i := 0; i < 100; i++ {
+				if snap.Devices[rootDevName] == nil {
+					break
+				}
+				rootDevName = fmt.Sprintf("root%d", i)
+				continue
+			}
+
+			snap.Devices[rootDevName] = rootDev
+		}
+
 		_, err = containerCreateInternal(d.State(), db.ContainerArgs{
 			Architecture: arch,
 			BaseImage:    baseImage,
@@ -884,6 +909,25 @@ func internalImport(d *Daemon, r *http.Request) Response {
 
 	baseImage := backup.Container.Config["volatile.base_image"]
 
+	// Add root device if missing
+	root, _, _ := shared.GetRootDiskDevice(backup.Container.Devices)
+	if root == "" {
+		if backup.Container.Devices == nil {
+			backup.Container.Devices = map[string]map[string]string{}
+		}
+
+		rootDevName := "root"
+		for i := 0; i < 100; i++ {
+			if backup.Container.Devices[rootDevName] == nil {
+				break
+			}
+			rootDevName = fmt.Sprintf("root%d", i)
+			continue
+		}
+
+		backup.Container.Devices[rootDevName] = rootDev
+	}
+
 	arch, err := osarch.ArchitectureId(backup.Container.Architecture)
 	if err != nil {
 		return SmartError(err)

From e9d3402394ceba0b7df227c40f554c8018d46d7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 10 Sep 2018 01:25:01 -0400
Subject: [PATCH 3/3] lxd/import: Don't delete container on import failure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #5017

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/api_internal.go  | 12 ++++++++++--
 lxd/container_lxc.go | 21 +++++++++++++++++++--
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 5bab2bfe44..45be457bad 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -7,6 +7,7 @@ import (
 	"io/ioutil"
 	"net/http"
 	"os"
+	"path/filepath"
 	"strconv"
 	"strings"
 
@@ -398,8 +399,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 	}
 
 	// Read in the backup.yaml file.
-	backupYamlPath := shared.VarPath("storage-pools", containerPoolName,
-		"containers", req.Name, "backup.yaml")
+	backupYamlPath := filepath.Join(containerMntPoint, "backup.yaml")
 	backup, err := slurpBackupFile(backupYamlPath)
 	if err != nil {
 		return SmartError(err)
@@ -803,6 +803,14 @@ func internalImport(d *Daemon, r *http.Request) Response {
 	rootDev["path"] = "/"
 	rootDev["pool"] = containerPoolName
 
+	// Mark the filesystem as going through an import
+	fd, err := os.Create(filepath.Join(containerMntPoint, ".importing"))
+	if err != nil {
+		return InternalError(err)
+	}
+	fd.Close()
+	defer os.Remove(fd.Name())
+
 	for _, snap := range existingSnapshots {
 		// Check if an entry for the snapshot already exists in the db.
 		_, snapErr := d.cluster.ContainerID(snap.Name)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 7d0b1c4754..de14f2a814 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -3373,12 +3373,29 @@ func (c *containerLXC) Delete() error {
 		return err
 	}
 
+	// Check if we're dealing with "lxd import"
+	isImport := false
+	if c.storage != nil {
+		_, poolName, _ := c.storage.GetContainerPoolInfo()
+
+		if c.IsSnapshot() {
+			cName, _, _ := containerGetParentAndSnapshotName(c.name)
+			if shared.PathExists(shared.VarPath("storage-pools", poolName, "containers", cName, ".importing")) {
+				isImport = true
+			}
+		} else {
+			if shared.PathExists(shared.VarPath("storage-pools", poolName, "containers", c.name, ".importing")) {
+				isImport = true
+			}
+		}
+	}
+
 	// Attempt to initialize storage interface for the container.
 	c.initStorage()
 
 	if c.IsSnapshot() {
 		// Remove the snapshot
-		if c.storage != nil {
+		if c.storage != nil && !isImport {
 			err := c.storage.ContainerSnapshotDelete(c)
 			if err != nil {
 				logger.Warn("Failed to delete snapshot", log.Ctx{"name": c.Name(), "err": err})
@@ -3410,7 +3427,7 @@ func (c *containerLXC) Delete() error {
 		c.cleanup()
 
 		// Delete the container from disk
-		if c.storage != nil {
+		if c.storage != nil && !isImport {
 			_, poolName, _ := c.storage.GetContainerPoolInfo()
 			containerMountPoint := getContainerMountPoint(poolName, c.Name())
 			if shared.PathExists(c.Path()) ||


More information about the lxc-devel mailing list