[lxc-devel] [lxd/master] Storage: Move legacy code removal/reorg

tomponline on Github lxc-bot at linuxcontainers.org
Fri Feb 28 15:46:02 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 350 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200228/4f2d0a21/attachment-0001.bin>
-------------- next part --------------
From e5c1ad935fac79ad15ee1e5cfbfa9fc00b9adc9b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 15:52:50 +0000
Subject: [PATCH 01/62] lxd/instance/drivers/driver/lxc: Removes temporary lxc
 placeholder

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 21 ---------------------
 1 file changed, 21 deletions(-)
 delete mode 100644 lxd/instance/drivers/driver_lxc.go

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
deleted file mode 100644
index 2e067a435c..0000000000
--- a/lxd/instance/drivers/driver_lxc.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package drivers
-
-import (
-	"github.com/lxc/lxd/lxd/db"
-	deviceConfig "github.com/lxc/lxd/lxd/device/config"
-	"github.com/lxc/lxd/lxd/instance"
-	"github.com/lxc/lxd/lxd/state"
-	"github.com/lxc/lxd/shared/api"
-)
-
-// LXCLoad is used to link containerLXCLoad from main package, it is temporary export until such time
-// as containerLXC can be moved into this package.
-var LXCLoad func(s *state.State, args db.InstanceArgs, profiles []api.Profile) (instance.Instance, error)
-
-// LXCInstantiate is used to link containerLXCInstantiate from main package, it is temporary export until such
-// time as containerLXC can be moved into this package.
-var LXCInstantiate func(s *state.State, args db.InstanceArgs, expandedDevices deviceConfig.Devices) instance.Instance
-
-// LXCCreate is used to link containerLXCCreate from main package, it is temporary export until such time
-// as containerLXC can be moved into this package.
-var LXCCreate func(s *state.State, args db.InstanceArgs) (instance.Instance, error)

From 6601ca70755a78c8b403cda0b81ba146d4e4f373 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 15:53:25 +0000
Subject: [PATCH 02/62] lxd/container/lxc: Moves to instance/drivers package

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/{container_lxc.go => instance/drivers/driver_lxc.go} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename lxd/{container_lxc.go => instance/drivers/driver_lxc.go} (100%)

diff --git a/lxd/container_lxc.go b/lxd/instance/drivers/driver_lxc.go
similarity index 100%
rename from lxd/container_lxc.go
rename to lxd/instance/drivers/driver_lxc.go

From 34efed44a4477f924dd6ebd7d0046cb1fab683be Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 16:08:15 +0000
Subject: [PATCH 03/62] lxd/container/lxc/exec/cmd: Moves to instance/drivers
 package

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 .../drivers/driver_lxc_cmd.go}                                    | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename lxd/{container_lxc_exec_cmd.go => instance/drivers/driver_lxc_cmd.go} (100%)

diff --git a/lxd/container_lxc_exec_cmd.go b/lxd/instance/drivers/driver_lxc_cmd.go
similarity index 100%
rename from lxd/container_lxc_exec_cmd.go
rename to lxd/instance/drivers/driver_lxc_cmd.go

From 9f7002034f0d0a9902f27b5c68f57b4d9fcdf432 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:39:30 +0000
Subject: [PATCH 04/62] lxd/instance/drivers/driver/utils: Adds
 SetupSharedMounts function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_utils.go | 46 ++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 lxd/instance/drivers/driver_utils.go

diff --git a/lxd/instance/drivers/driver_utils.go b/lxd/instance/drivers/driver_utils.go
new file mode 100644
index 0000000000..283fd24b10
--- /dev/null
+++ b/lxd/instance/drivers/driver_utils.go
@@ -0,0 +1,46 @@
+package drivers
+
+import (
+	"sync"
+
+	"golang.org/x/sys/unix"
+
+	"github.com/lxc/lxd/shared"
+)
+
+// have we setup shared mounts?
+var sharedMounted bool
+var sharedMountsLock sync.Mutex
+
+// SetupSharedMounts sets up shared mounts.
+func SetupSharedMounts() error {
+	// Check if we already went through this
+	if sharedMounted {
+		return nil
+	}
+
+	// Get a lock to prevent races
+	sharedMountsLock.Lock()
+	defer sharedMountsLock.Unlock()
+
+	// Check if already setup
+	path := shared.VarPath("shmounts")
+	if shared.IsMountPoint(path) {
+		sharedMounted = true
+		return nil
+	}
+
+	// Mount a new tmpfs
+	if err := unix.Mount("tmpfs", path, "tmpfs", 0, "size=100k,mode=0711"); err != nil {
+		return err
+	}
+
+	// Mark as MS_SHARED and MS_REC
+	var flags uintptr = unix.MS_SHARED | unix.MS_REC
+	if err := unix.Mount(path, path, "none", flags, ""); err != nil {
+		return err
+	}
+
+	sharedMounted = true
+	return nil
+}

From 273f5f9fe925df384ee518c484a419d0898db492 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:39:52 +0000
Subject: [PATCH 05/62] lxd/api/internal: instance.Container usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/api_internal.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 9d1dab7c1a..a8fe617433 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -135,7 +135,7 @@ func internalContainerOnStart(d *Daemon, r *http.Request) response.Response {
 		return response.SmartError(fmt.Errorf("Instance is not container type"))
 	}
 
-	c := inst.(*containerLXC)
+	c := inst.(instance.Container)
 	err = c.OnStart()
 	if err != nil {
 		logger.Error("The start hook failed", log.Ctx{"container": c.Name(), "err": err})
@@ -166,7 +166,7 @@ func internalContainerOnStopNS(d *Daemon, r *http.Request) response.Response {
 		return response.SmartError(fmt.Errorf("Instance is not container type"))
 	}
 
-	c := inst.(*containerLXC)
+	c := inst.(instance.Container)
 	err = c.OnStopNS(target, netns)
 	if err != nil {
 		logger.Error("The stopns hook failed", log.Ctx{"container": c.Name(), "err": err})
@@ -196,7 +196,7 @@ func internalContainerOnStop(d *Daemon, r *http.Request) response.Response {
 		return response.SmartError(fmt.Errorf("Instance is not container type"))
 	}
 
-	c := inst.(*containerLXC)
+	c := inst.(instance.Container)
 	err = c.OnStop(target)
 	if err != nil {
 		logger.Error("The stop hook failed", log.Ctx{"container": c.Name(), "err": err})

From dd627333af234c7cc02d63bbca293f9a37145765 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:40:23 +0000
Subject: [PATCH 06/62] lxd/container: instance.CriuMigrationArgs and
 instance.Container usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container.go | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/lxd/container.go b/lxd/container.go
index 4b521fbef0..094d6fad37 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -384,17 +384,17 @@ func instanceCreateAsSnapshot(s *state.State, args db.InstanceArgs, sourceInstan
 		 * after snapshotting will fail.
 		 */
 
-		criuMigrationArgs := CriuMigrationArgs{
-			cmd:          lxc.MIGRATE_DUMP,
-			stateDir:     stateDir,
-			function:     "snapshot",
-			stop:         false,
-			actionScript: false,
-			dumpDir:      "",
-			preDumpDir:   "",
+		criuMigrationArgs := instance.CriuMigrationArgs{
+			Cmd:          lxc.MIGRATE_DUMP,
+			StateDir:     stateDir,
+			Function:     "snapshot",
+			Stop:         false,
+			ActionScript: false,
+			DumpDir:      "",
+			PreDumpDir:   "",
 		}
 
-		c := sourceInstance.(*containerLXC)
+		c := sourceInstance.(instance.Container)
 		err = c.Migrate(&criuMigrationArgs)
 		if err != nil {
 			os.RemoveAll(sourceInstance.StatePath())

From 9739cd70b94090ab5d3ab82b9247f254b7edbcc0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:41:00 +0000
Subject: [PATCH 07/62] lxd/container/console: instance.Container usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_console.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/container_console.go b/lxd/container_console.go
index e461a9f7ff..9207508b32 100644
--- a/lxd/container_console.go
+++ b/lxd/container_console.go
@@ -354,7 +354,7 @@ func containerConsoleLogGet(d *Daemon, r *http.Request) response.Response {
 		return response.SmartError(fmt.Errorf("Instance is not container type"))
 	}
 
-	c := inst.(*containerLXC)
+	c := inst.(instance.Container)
 	ent := response.FileResponseEntry{}
 	if !c.IsRunning() {
 		// Hand back the contents of the console ringbuffer logfile.
@@ -408,7 +408,7 @@ func containerConsoleLogDelete(d *Daemon, r *http.Request) response.Response {
 		return response.SmartError(fmt.Errorf("Instance is not container type"))
 	}
 
-	c := inst.(*containerLXC)
+	c := inst.(instance.Container)
 
 	truncateConsoleLogFile := func(path string) error {
 		// Check that this is a regular file. We don't want to try and unlink

From ab5601a6e1ef14a47469c387cd5a0125c02b7b11 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:41:18 +0000
Subject: [PATCH 08/62] lxd/container/exec: instance.Container usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_exec.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/container_exec.go b/lxd/container_exec.go
index 2302ee54b3..c15c4afe90 100644
--- a/lxd/container_exec.go
+++ b/lxd/container_exec.go
@@ -426,7 +426,7 @@ func containerExecPost(d *Daemon, r *http.Request) response.Response {
 		ws.fds = map[int]string{}
 
 		if inst.Type() == instancetype.Container {
-			c := inst.(*containerLXC)
+			c := inst.(instance.Container)
 			idmapset, err := c.CurrentIdmap()
 			if err != nil {
 				return response.InternalError(err)

From 420b7046238a7ac7802db20aa99835a7b945e266 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:41:40 +0000
Subject: [PATCH 09/62] lxd/container/lxc/utils: Removes idmapsetFromString

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_lxc_utils.go | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/lxd/container_lxc_utils.go b/lxd/container_lxc_utils.go
index 9da660f398..7ea2afea2b 100644
--- a/lxd/container_lxc_utils.go
+++ b/lxd/container_lxc_utils.go
@@ -6,20 +6,6 @@ import (
 	"github.com/lxc/lxd/shared/idmap"
 )
 
-func idmapsetFromString(idmapString string) (*idmap.IdmapSet, error) {
-	lastIdmap := new(idmap.IdmapSet)
-	err := json.Unmarshal([]byte(idmapString), &lastIdmap.Idmap)
-	if err != nil {
-		return nil, err
-	}
-
-	if len(lastIdmap.Idmap) == 0 {
-		return nil, nil
-	}
-
-	return lastIdmap, nil
-}
-
 func idmapsetToJSON(idmapSet *idmap.IdmapSet) (string, error) {
 	idmapBytes, err := json.Marshal(idmapSet.Idmap)
 	if err != nil {

From 1675115c51808be93e412a6f0d24029685ca4f8a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:42:04 +0000
Subject: [PATCH 10/62] lxd/container/test: instance.Container usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_test.go | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/lxd/container_test.go b/lxd/container_test.go
index 5fbfd96403..e4677eec76 100644
--- a/lxd/container_test.go
+++ b/lxd/container_test.go
@@ -142,10 +142,10 @@ func (suite *containerTestSuite) TestContainer_LoadFromDB() {
 	suite.Req.Nil(err)
 
 	// When loading from DB, we won't have a full LXC config
-	c.(*containerLXC).c = nil
-	c.(*containerLXC).cConfig = false
-	c2.(*containerLXC).c = nil
-	c2.(*containerLXC).cConfig = false
+	c.(*instanceDrivers.LXC).c = nil
+	c.(*instanceDrivers.LXC).cConfig = false
+	c2.(*instanceDrivers.LXC).c = nil
+	c2.(*instanceDrivers.LXC).cConfig = false
 
 	suite.Exactly(
 		c,
@@ -250,9 +250,9 @@ func (suite *containerTestSuite) TestContainer_findIdmap_isolated() {
 	suite.Req.Nil(err)
 	defer c2.Delete()
 
-	map1, err := c1.(*containerLXC).NextIdmap()
+	map1, err := c1.(instance.Container).NextIdmap()
 	suite.Req.Nil(err)
-	map2, err := c2.(*containerLXC).NextIdmap()
+	map2, err := c2.(instance.Container).NextIdmap()
 	suite.Req.Nil(err)
 
 	host := suite.d.os.IdmapSet.Idmap[0]
@@ -291,9 +291,9 @@ func (suite *containerTestSuite) TestContainer_findIdmap_mixed() {
 	suite.Req.Nil(err)
 	defer c2.Delete()
 
-	map1, err := c1.(*containerLXC).NextIdmap()
+	map1, err := c1.(instance.Container).NextIdmap()
 	suite.Req.Nil(err)
-	map2, err := c2.(*containerLXC).NextIdmap()
+	map2, err := c2.(instance.Container).NextIdmap()
 	suite.Req.Nil(err)
 
 	host := suite.d.os.IdmapSet.Idmap[0]
@@ -323,7 +323,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_raw() {
 	suite.Req.Nil(err)
 	defer c1.Delete()
 
-	map1, err := c1.(*containerLXC).NextIdmap()
+	map1, err := c1.(instance.Container).NextIdmap()
 	suite.Req.Nil(err)
 
 	host := suite.d.os.IdmapSet.Idmap[0]
@@ -369,7 +369,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_maxed() {
 
 		defer c.Delete()
 
-		m, err := c.(*containerLXC).NextIdmap()
+		m, err := c.(instance.Container).NextIdmap()
 		suite.Req.Nil(err)
 
 		maps = append(maps, m)

From 740b63fe5d9e313ee78f61ff065135b8dce7f393 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:42:30 +0000
Subject: [PATCH 11/62] lxd/daemon: instanceDrivers.SetupSharedMounts usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/daemon.go | 39 ++-------------------------------------
 1 file changed, 2 insertions(+), 37 deletions(-)

diff --git a/lxd/daemon.go b/lxd/daemon.go
index acb1e4eb8e..414133db0a 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -36,6 +36,7 @@ import (
 	"github.com/lxc/lxd/lxd/events"
 	"github.com/lxc/lxd/lxd/firewall"
 	"github.com/lxc/lxd/lxd/instance"
+	instanceDrivers "github.com/lxc/lxd/lxd/instance/drivers"
 	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/maas"
 	"github.com/lxc/lxd/lxd/node"
@@ -483,42 +484,6 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) {
 	}
 }
 
-// have we setup shared mounts?
-var sharedMounted bool
-var sharedMountsLock sync.Mutex
-
-func setupSharedMounts() error {
-	// Check if we already went through this
-	if sharedMounted {
-		return nil
-	}
-
-	// Get a lock to prevent races
-	sharedMountsLock.Lock()
-	defer sharedMountsLock.Unlock()
-
-	// Check if already setup
-	path := shared.VarPath("shmounts")
-	if shared.IsMountPoint(path) {
-		sharedMounted = true
-		return nil
-	}
-
-	// Mount a new tmpfs
-	if err := unix.Mount("tmpfs", path, "tmpfs", 0, "size=100k,mode=0711"); err != nil {
-		return err
-	}
-
-	// Mark as MS_SHARED and MS_REC
-	var flags uintptr = unix.MS_SHARED | unix.MS_REC
-	if err := unix.Mount(path, path, "none", flags, ""); err != nil {
-		return err
-	}
-
-	sharedMounted = true
-	return nil
-}
-
 func (d *Daemon) Init() error {
 	err := d.init()
 
@@ -687,7 +652,7 @@ func (d *Daemon) init() error {
 	/* Setup some mounts (nice to have) */
 	if !d.os.MockMode {
 		// Attempt to mount the shmounts tmpfs
-		setupSharedMounts()
+		instanceDrivers.SetupSharedMounts()
 
 		// Attempt to Mount the devlxd tmpfs
 		devlxd := filepath.Join(d.os.VarDir, "devlxd")

From 3800bac21c9852280d531236b9570fccd5082c10 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:42:47 +0000
Subject: [PATCH 12/62] lxd/devices: inst.RegisterDevices usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/devices.go | 32 ++++----------------------------
 1 file changed, 4 insertions(+), 28 deletions(-)

diff --git a/lxd/devices.go b/lxd/devices.go
index 4ce79fa9ae..dd7c523bab 100644
--- a/lxd/devices.go
+++ b/lxd/devices.go
@@ -560,40 +560,16 @@ func deviceEventListener(s *state.State) {
 func devicesRegister(s *state.State) {
 	instances, err := instance.LoadNodeAll(s, instancetype.Container)
 	if err != nil {
-		logger.Error("Problem loading containers list", log.Ctx{"err": err})
+		logger.Error("Problem loading instances list", log.Ctx{"err": err})
 		return
 	}
 
-	for _, instanceIf := range instances {
-		c, ok := instanceIf.(*containerLXC)
-		if !ok {
-			logger.Errorf("Instance is not container type")
+	for _, inst := range instances {
+		if !inst.IsRunning() {
 			continue
 		}
 
-		if !c.IsRunning() {
-			continue
-		}
-
-		devices := c.ExpandedDevices()
-		for _, dev := range devices.Sorted() {
-			d, _, err := c.deviceLoad(dev.Name, dev.Config)
-			if err == device.ErrUnsupportedDevType {
-				continue
-			}
-
-			if err != nil {
-				logger.Error("Failed to load device to register", log.Ctx{"err": err, "container": c.Name(), "device": dev.Name})
-				continue
-			}
-
-			// Check whether device wants to register for any events.
-			err = d.Register()
-			if err != nil {
-				logger.Error("Failed to register device", log.Ctx{"err": err, "container": c.Name(), "device": dev.Name})
-				continue
-			}
-		}
+		inst.RegisterDevices()
 	}
 }
 

From 8daed6643205be6ea93a60295b36fd446b02cb70 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:43:10 +0000
Subject: [PATCH 13/62] lxd/devlxd: Removes devlxdEventSend

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/devlxd.go | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/lxd/devlxd.go b/lxd/devlxd.go
index f56c2e234c..7eb41c9e98 100644
--- a/lxd/devlxd.go
+++ b/lxd/devlxd.go
@@ -12,7 +12,6 @@ import (
 	"strconv"
 	"strings"
 	"sync"
-	"time"
 	"unsafe"
 
 	"github.com/gorilla/mux"
@@ -151,15 +150,6 @@ var devlxdEventsGet = devLxdHandler{"/1.0/events", func(d *Daemon, c instance.In
 	return &devLxdResponse{"websocket", http.StatusOK, "websocket"}
 }}
 
-func devlxdEventSend(c instance.Instance, eventType string, eventMessage interface{}) error {
-	event := shared.Jmap{}
-	event["type"] = eventType
-	event["timestamp"] = time.Now()
-	event["metadata"] = eventMessage
-
-	return c.DaemonState().DevlxdEvents.Send(strconv.Itoa(c.ID()), eventType, eventMessage)
-}
-
 var handlers = []devLxdHandler{
 	{"/", func(d *Daemon, c instance.Instance, w http.ResponseWriter, r *http.Request) *devLxdResponse {
 		return okResponse([]string{"/1.0"}, "json")

From fa58c80e66668f8bf76a8d5f420f25b4e42789d9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:43:28 +0000
Subject: [PATCH 14/62] lxd/devlxd: instance.Container usage

And golint fixes

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/devlxd.go | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/lxd/devlxd.go b/lxd/devlxd.go
index 7eb41c9e98..2414a22646 100644
--- a/lxd/devlxd.go
+++ b/lxd/devlxd.go
@@ -180,15 +180,15 @@ func hoistReq(f func(*Daemon, instance.Instance, http.ResponseWriter, *http.Requ
 		}
 
 		// Access control
-		rootUid := int64(0)
+		rootUID := int64(0)
 
 		idmapset, err := c.CurrentIdmap()
 		if err == nil && idmapset != nil {
 			uid, _ := idmapset.ShiftIntoNs(0, 0)
-			rootUid = int64(uid)
+			rootUID = int64(uid)
 		}
 
-		if rootUid != cred.UID {
+		if rootUID != cred.UID {
 			http.Error(w, "Access denied for non-root user", 401)
 			return
 		}
@@ -308,7 +308,7 @@ func extractUnderlyingConn(w http.ResponseWriter) *net.UnixConn {
 
 var pidNotInContainerErr = fmt.Errorf("pid not in container?")
 
-func findContainerForPid(pid int32, s *state.State) (*containerLXC, error) {
+func findContainerForPid(pid int32, s *state.State) (instance.Container, error) {
 	/*
 	 * Try and figure out which container a pid is in. There is probably a
 	 * better way to do this. Based on rharper's initial performance
@@ -355,8 +355,7 @@ func findContainerForPid(pid int32, s *state.State) (*containerLXC, error) {
 				return nil, fmt.Errorf("Instance is not container type")
 			}
 
-			c := inst.(*containerLXC)
-			return c, nil
+			return inst.(instance.Container), nil
 		}
 
 		status, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid))
@@ -405,7 +404,7 @@ func findContainerForPid(pid int32, s *state.State) (*containerLXC, error) {
 		}
 
 		if origPidNs == pidNs {
-			return inst.(*containerLXC), nil
+			return inst.(instance.Container), nil
 		}
 	}
 

From 339e4d29ee031d82106e1be3e21bb1d6d0eab644 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:49:40 +0000
Subject: [PATCH 15/62] lxd/instance/drivers/driver/lxc: Renames containerLXC
 to lxc

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 350 ++++++++++++++---------------
 1 file changed, 169 insertions(+), 181 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 9b13c10503..e0809956b8 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -1,4 +1,4 @@
-package main
+package drivers
 
 import (
 	"bufio"
@@ -34,7 +34,6 @@ import (
 	"github.com/lxc/lxd/lxd/device"
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
 	"github.com/lxc/lxd/lxd/instance"
-	instanceDrivers "github.com/lxc/lxd/lxd/instance/drivers"
 	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/instance/operationlock"
 	"github.com/lxc/lxd/lxd/maas"
@@ -147,9 +146,9 @@ func lxcStatusCode(state lxc.State) api.StatusCode {
 }
 
 // Loader functions
-func containerLXCCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error) {
+func lxcCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error) {
 	// Create the container struct
-	c := &containerLXC{
+	c := &lxc{
 		state:        s,
 		id:           args.ID,
 		project:      args.Project,
@@ -354,20 +353,20 @@ func containerLXCCreate(s *state.State, args db.InstanceArgs) (instance.Instance
 	return c, nil
 }
 
-func containerLXCLoad(s *state.State, args db.InstanceArgs, profiles []api.Profile) (instance.Instance, error) {
+func lxcLoad(s *state.State, args db.InstanceArgs, profiles []api.Profile) (instance.Instance, error) {
 	// Create the container struct
-	c := containerLXCInstantiate(s, args, nil)
+	c := lxcInstantiate(s, args, nil)
 
 	// Setup finalizer
-	runtime.SetFinalizer(c, containerLXCUnload)
+	runtime.SetFinalizer(c, lxcUnload)
 
 	// Expand config and devices
-	err := c.(*containerLXC).expandConfig(profiles)
+	err := c.(*lxc).expandConfig(profiles)
 	if err != nil {
 		return nil, err
 	}
 
-	err = c.(*containerLXC).expandDevices(profiles)
+	err = c.(*lxc).expandDevices(profiles)
 	if err != nil {
 		return nil, err
 	}
@@ -376,7 +375,7 @@ func containerLXCLoad(s *state.State, args db.InstanceArgs, profiles []api.Profi
 }
 
 // Unload is called by the garbage collector
-func containerLXCUnload(c *containerLXC) {
+func lxcUnload(c *lxc) {
 	runtime.SetFinalizer(c, nil)
 	if c.c != nil {
 		c.c.Release()
@@ -385,8 +384,8 @@ func containerLXCUnload(c *containerLXC) {
 }
 
 // Create a container struct without initializing it.
-func containerLXCInstantiate(s *state.State, args db.InstanceArgs, expandedDevices deviceConfig.Devices) instance.Instance {
-	c := &containerLXC{
+func lxcInstantiate(s *state.State, args db.InstanceArgs, expandedDevices deviceConfig.Devices) instance.Instance {
+	c := &lxc{
 		state:        s,
 		id:           args.ID,
 		project:      args.Project,
@@ -427,8 +426,8 @@ func containerLXCInstantiate(s *state.State, args db.InstanceArgs, expandedDevic
 	return c
 }
 
-// The LXC container driver
-type containerLXC struct {
+// The LXC container driver.
+type lxc struct {
 	// Properties
 	architecture int
 	dbType       instancetype.Type
@@ -471,7 +470,7 @@ type containerLXC struct {
 	expiryDate time.Time
 }
 
-func (c *containerLXC) Type() instancetype.Type {
+func (c *lxc) Type() instancetype.Type {
 	return c.dbType
 }
 
@@ -659,7 +658,7 @@ func findIdmap(state *state.State, cName string, isolatedStr string, configBase
 	return nil, 0, fmt.Errorf("Not enough uid/gid available for the container")
 }
 
-func (c *containerLXC) init() error {
+func (c *lxc) init() error {
 	// Compute the expanded config and device list
 	err := c.expandConfig(nil)
 	if err != nil {
@@ -674,7 +673,7 @@ func (c *containerLXC) init() error {
 	return nil
 }
 
-func (c *containerLXC) initLXC(config bool) error {
+func (c *lxc) initLXC(config bool) error {
 	// No need to go through all that for snapshots
 	if c.IsSnapshot() {
 		return nil
@@ -1275,7 +1274,7 @@ func (c *containerLXC) initLXC(config bool) error {
 }
 
 // runHooks executes the callback functions returned from a function.
-func (c *containerLXC) runHooks(hooks []func() error) error {
+func (c *lxc) runHooks(hooks []func() error) error {
 	// Run any post start hooks.
 	if len(hooks) > 0 {
 		for _, hook := range hooks {
@@ -1290,7 +1289,7 @@ func (c *containerLXC) runHooks(hooks []func() error) error {
 }
 
 // deviceLoad instantiates and validates a new device and returns it along with enriched config.
-func (c *containerLXC) deviceLoad(deviceName string, rawConfig deviceConfig.Device) (device.Device, deviceConfig.Device, error) {
+func (c *lxc) deviceLoad(deviceName string, rawConfig deviceConfig.Device) (device.Device, deviceConfig.Device, error) {
 	var configCopy deviceConfig.Device
 	var err error
 
@@ -1312,7 +1311,7 @@ func (c *containerLXC) deviceLoad(deviceName string, rawConfig deviceConfig.Devi
 }
 
 // deviceAdd loads a new device and calls its Add() function.
-func (c *containerLXC) deviceAdd(deviceName string, rawConfig deviceConfig.Device) error {
+func (c *lxc) deviceAdd(deviceName string, rawConfig deviceConfig.Device) error {
 	d, _, err := c.deviceLoad(deviceName, rawConfig)
 	if err != nil {
 		return err
@@ -1324,7 +1323,7 @@ func (c *containerLXC) deviceAdd(deviceName string, rawConfig deviceConfig.Devic
 // deviceStart loads a new device and calls its Start() function. After processing the runtime
 // config returned from Start(), it also runs the device's Register() function irrespective of
 // whether the container is running or not.
-func (c *containerLXC) deviceStart(deviceName string, rawConfig deviceConfig.Device, isRunning bool) (*deviceConfig.RunConfig, error) {
+func (c *lxc) deviceStart(deviceName string, rawConfig deviceConfig.Device, isRunning bool) (*deviceConfig.RunConfig, error) {
 	d, configCopy, err := c.deviceLoad(deviceName, rawConfig)
 	if err != nil {
 		return nil, err
@@ -1389,7 +1388,7 @@ func (c *containerLXC) deviceStart(deviceName string, rawConfig deviceConfig.Dev
 }
 
 // deviceStaticShiftMounts statically shift device mount files ownership to active idmap if needed.
-func (c *containerLXC) deviceStaticShiftMounts(mounts []deviceConfig.MountEntryItem) error {
+func (c *lxc) deviceStaticShiftMounts(mounts []deviceConfig.MountEntryItem) error {
 	idmapSet, err := c.CurrentIdmap()
 	if err != nil {
 		return fmt.Errorf("Failed to get idmap for device: %s", err)
@@ -1417,7 +1416,7 @@ func (c *containerLXC) deviceStaticShiftMounts(mounts []deviceConfig.MountEntryI
 }
 
 // deviceAddCgroupRules live adds cgroup rules to a container.
-func (c *containerLXC) deviceAddCgroupRules(cgroups []deviceConfig.RunConfigItem) error {
+func (c *lxc) deviceAddCgroupRules(cgroups []deviceConfig.RunConfigItem) error {
 	cg, err := c.cgroup(nil)
 	if err != nil {
 		return err
@@ -1440,7 +1439,7 @@ func (c *containerLXC) deviceAddCgroupRules(cgroups []deviceConfig.RunConfigItem
 }
 
 // deviceAttachNIC live attaches a NIC device to a container.
-func (c *containerLXC) deviceAttachNIC(configCopy map[string]string, netIF []deviceConfig.RunConfigItem) error {
+func (c *lxc) deviceAttachNIC(configCopy map[string]string, netIF []deviceConfig.RunConfigItem) error {
 	devName := ""
 	for _, dev := range netIF {
 		if dev.Key == "link" {
@@ -1469,7 +1468,7 @@ func (c *containerLXC) deviceAttachNIC(configCopy map[string]string, netIF []dev
 }
 
 // deviceUpdate loads a new device and calls its Update() function.
-func (c *containerLXC) deviceUpdate(deviceName string, rawConfig deviceConfig.Device, oldDevices deviceConfig.Devices, isRunning bool) error {
+func (c *lxc) deviceUpdate(deviceName string, rawConfig deviceConfig.Device, oldDevices deviceConfig.Devices, isRunning bool) error {
 	d, _, err := c.deviceLoad(deviceName, rawConfig)
 	if err != nil {
 		return err
@@ -1484,7 +1483,7 @@ func (c *containerLXC) deviceUpdate(deviceName string, rawConfig deviceConfig.De
 }
 
 // deviceStop loads a new device and calls its Stop() function.
-func (c *containerLXC) deviceStop(deviceName string, rawConfig deviceConfig.Device, stopHookNetnsPath string) error {
+func (c *lxc) deviceStop(deviceName string, rawConfig deviceConfig.Device, stopHookNetnsPath string) error {
 	d, configCopy, err := c.deviceLoad(deviceName, rawConfig)
 
 	// If deviceLoad fails with unsupported device type then return.
@@ -1553,7 +1552,7 @@ func (c *containerLXC) deviceStop(deviceName string, rawConfig deviceConfig.Devi
 }
 
 // deviceDetachNIC detaches a NIC device from a container.
-func (c *containerLXC) deviceDetachNIC(configCopy map[string]string, netIF []deviceConfig.RunConfigItem, stopHookNetnsPath string) error {
+func (c *lxc) deviceDetachNIC(configCopy map[string]string, netIF []deviceConfig.RunConfigItem, stopHookNetnsPath string) error {
 	// Get requested device name to detach interface back to on the host.
 	devName := ""
 	for _, dev := range netIF {
@@ -1614,7 +1613,7 @@ func (c *containerLXC) deviceDetachNIC(configCopy map[string]string, netIF []dev
 
 // deviceHandleMounts live attaches or detaches mounts on a container.
 // If the mount DevPath is empty the mount action is treated as unmount.
-func (c *containerLXC) deviceHandleMounts(mounts []deviceConfig.MountEntryItem) error {
+func (c *lxc) deviceHandleMounts(mounts []deviceConfig.MountEntryItem) error {
 	for _, mount := range mounts {
 		if mount.DevPath != "" {
 			flags := 0
@@ -1661,7 +1660,7 @@ func (c *containerLXC) deviceHandleMounts(mounts []deviceConfig.MountEntryItem)
 }
 
 // deviceRemove loads a new device and calls its Remove() function.
-func (c *containerLXC) deviceRemove(deviceName string, rawConfig deviceConfig.Device) error {
+func (c *lxc) deviceRemove(deviceName string, rawConfig deviceConfig.Device) error {
 	d, _, err := c.deviceLoad(deviceName, rawConfig)
 
 	// If deviceLoad fails with unsupported device type then return.
@@ -1681,7 +1680,7 @@ func (c *containerLXC) deviceRemove(deviceName string, rawConfig deviceConfig.De
 
 // deviceVolatileGetFunc returns a function that retrieves a named device's volatile config and
 // removes its device prefix from the keys.
-func (c *containerLXC) deviceVolatileGetFunc(devName string) func() map[string]string {
+func (c *lxc) deviceVolatileGetFunc(devName string) func() map[string]string {
 	return func() map[string]string {
 		volatile := make(map[string]string)
 		prefix := fmt.Sprintf("volatile.%s.", devName)
@@ -1696,7 +1695,7 @@ func (c *containerLXC) deviceVolatileGetFunc(devName string) func() map[string]s
 
 // deviceVolatileSetFunc returns a function that can be called to save a named device's volatile
 // config using keys that do not have the device's name prefixed.
-func (c *containerLXC) deviceVolatileSetFunc(devName string) func(save map[string]string) error {
+func (c *lxc) deviceVolatileSetFunc(devName string) func(save map[string]string) error {
 	return func(save map[string]string) error {
 		volatileSave := make(map[string]string)
 		for k, v := range save {
@@ -1709,7 +1708,7 @@ func (c *containerLXC) deviceVolatileSetFunc(devName string) func(save map[strin
 
 // deviceResetVolatile resets a device's volatile data when its removed or updated in such a way
 // that it is removed then added immediately afterwards.
-func (c *containerLXC) deviceResetVolatile(devName string, oldConfig, newConfig deviceConfig.Device) error {
+func (c *lxc) deviceResetVolatile(devName string, oldConfig, newConfig deviceConfig.Device) error {
 	volatileClear := make(map[string]string)
 	devicePrefix := fmt.Sprintf("volatile.%s.", devName)
 
@@ -1746,7 +1745,7 @@ func (c *containerLXC) deviceResetVolatile(devName string, oldConfig, newConfig
 }
 
 // DeviceEventHandler actions the results of a RunConfig after an event has occurred on a device.
-func (c *containerLXC) DeviceEventHandler(runConf *deviceConfig.RunConfig) error {
+func (c *lxc) DeviceEventHandler(runConf *deviceConfig.RunConfig) error {
 	// Device events can only be processed when the container is running.
 	if !c.IsRunning() {
 		return nil
@@ -1807,7 +1806,7 @@ func (c *containerLXC) DeviceEventHandler(runConf *deviceConfig.RunConfig) error
 }
 
 // Config handling
-func (c *containerLXC) expandConfig(profiles []api.Profile) error {
+func (c *lxc) expandConfig(profiles []api.Profile) error {
 	if profiles == nil && len(c.profiles) > 0 {
 		var err error
 		profiles, err = c.state.Cluster.ProfilesGet(c.project, c.profiles)
@@ -1821,7 +1820,7 @@ func (c *containerLXC) expandConfig(profiles []api.Profile) error {
 	return nil
 }
 
-func (c *containerLXC) expandDevices(profiles []api.Profile) error {
+func (c *lxc) expandDevices(profiles []api.Profile) error {
 	if profiles == nil && len(c.profiles) > 0 {
 		var err error
 		profiles, err = c.state.Cluster.ProfilesGet(c.project, c.profiles)
@@ -1886,7 +1885,7 @@ func UnshiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet) error {
 }
 
 // Start functions
-func (c *containerLXC) startCommon() (string, []func() error, error) {
+func (c *lxc) startCommon() (string, []func() error, error) {
 	var ourStart bool
 	postStartHooks := []func() error{}
 
@@ -2247,7 +2246,7 @@ func (c *containerLXC) startCommon() (string, []func() error, error) {
 
 // detachInterfaceRename enters the container's network namespace and moves the named interface
 // in ifName back to the network namespace of the running process as the name specified in hostName.
-func (c *containerLXC) detachInterfaceRename(netns string, ifName string, hostName string) error {
+func (c *lxc) detachInterfaceRename(netns string, ifName string, hostName string) error {
 	lxdPID := os.Getpid()
 
 	// Run forknet detach
@@ -2269,7 +2268,7 @@ func (c *containerLXC) detachInterfaceRename(netns string, ifName string, hostNa
 	return nil
 }
 
-func (c *containerLXC) Start(stateful bool) error {
+func (c *lxc) Start(stateful bool) error {
 	var ctxMap log.Ctx
 
 	// Setup a new operation
@@ -2313,14 +2312,14 @@ func (c *containerLXC) Start(stateful bool) error {
 			return fmt.Errorf("Container has no existing state to restore")
 		}
 
-		criuMigrationArgs := CriuMigrationArgs{
-			cmd:          lxc.MIGRATE_RESTORE,
-			stateDir:     c.StatePath(),
-			function:     "snapshot",
-			stop:         false,
-			actionScript: false,
-			dumpDir:      "",
-			preDumpDir:   "",
+		criuMigrationArgs := instance.CriuMigrationArgs{
+			Cmd:          liblxc.MIGRATE_RESTORE,
+			StateDir:     c.StatePath(),
+			Function:     "snapshot",
+			Stop:         false,
+			ActionScript: false,
+			DumpDir:      "",
+			PreDumpDir:   "",
 		}
 
 		err := c.Migrate(&criuMigrationArgs)
@@ -2421,7 +2420,7 @@ func (c *containerLXC) Start(stateful bool) error {
 	return nil
 }
 
-func (c *containerLXC) OnStart() error {
+func (c *lxc) OnStart() error {
 	// Make sure we can't call go-lxc functions by mistake
 	c.fromHook = true
 
@@ -2478,7 +2477,7 @@ func (c *containerLXC) OnStart() error {
 
 	// Apply network priority
 	if c.expandedConfig["limits.network.priority"] != "" {
-		go func(c *containerLXC) {
+		go func(c *lxc) {
 			c.fromHook = false
 			err := c.setNetworkPriority()
 			if err != nil {
@@ -2511,7 +2510,7 @@ func (c *containerLXC) OnStart() error {
 }
 
 // Stop functions
-func (c *containerLXC) Stop(stateful bool) error {
+func (c *lxc) Stop(stateful bool) error {
 	var ctxMap log.Ctx
 
 	// Check that we're not already stopped
@@ -2549,14 +2548,14 @@ func (c *containerLXC) Stop(stateful bool) error {
 			return err
 		}
 
-		criuMigrationArgs := CriuMigrationArgs{
-			cmd:          lxc.MIGRATE_DUMP,
-			stateDir:     stateDir,
-			function:     "snapshot",
-			stop:         true,
-			actionScript: false,
-			dumpDir:      "",
-			preDumpDir:   "",
+		criuMigrationArgs := instance.CriuMigrationArgs{
+			Cmd:          liblxc.MIGRATE_DUMP,
+			StateDir:     stateDir,
+			Function:     "snapshot",
+			Stop:         true,
+			ActionScript: false,
+			DumpDir:      "",
+			PreDumpDir:   "",
 		}
 
 		// Checkpoint
@@ -2652,7 +2651,7 @@ func (c *containerLXC) Stop(stateful bool) error {
 	return nil
 }
 
-func (c *containerLXC) Shutdown(timeout time.Duration) error {
+func (c *lxc) Shutdown(timeout time.Duration) error {
 	var ctxMap log.Ctx
 
 	// Check that we're not already stopped
@@ -2715,7 +2714,7 @@ func (c *containerLXC) Shutdown(timeout time.Duration) error {
 
 // OnStopNS is triggered by LXC's stop hook once a container is shutdown but before the container's
 // namespaces have been closed. The netns path of the stopped container is provided.
-func (c *containerLXC) OnStopNS(target string, netns string) error {
+func (c *lxc) OnStopNS(target string, netns string) error {
 	// Validate target
 	if !shared.StringInSlice(target, []string{"stop", "reboot"}) {
 		logger.Error("Container sent invalid target to OnStopNS", log.Ctx{"container": c.Name(), "target": target})
@@ -2730,7 +2729,7 @@ func (c *containerLXC) OnStopNS(target string, netns string) error {
 
 // OnStop is triggered by LXC's post-stop hook once a container is shutdown and after the
 // container's namespaces have been closed.
-func (c *containerLXC) OnStop(target string) error {
+func (c *lxc) OnStop(target string) error {
 	// Validate target
 	if !shared.StringInSlice(target, []string{"stop", "reboot"}) {
 		logger.Error("Container sent invalid target to OnStop", log.Ctx{"container": c.Name(), "target": target})
@@ -2795,7 +2794,7 @@ func (c *containerLXC) OnStop(target string) error {
 		logger.Error("Failed to set container state", log.Ctx{"container": c.Name(), "err": err})
 	}
 
-	go func(c *containerLXC, target string, op *operationlock.InstanceOperation) {
+	go func(c *lxc, target string, op *operationlock.InstanceOperation) {
 		c.fromHook = false
 		err = nil
 
@@ -2845,7 +2844,7 @@ func (c *containerLXC) OnStop(target string) error {
 }
 
 // cleanupDevices performs any needed device cleanup steps when container is stopped.
-func (c *containerLXC) cleanupDevices(netns string) {
+func (c *lxc) cleanupDevices(netns string) {
 	for _, dev := range c.expandedDevices.Sorted() {
 		// Use the device interface if device supports it.
 		err := c.deviceStop(dev.Name, dev.Config, netns)
@@ -2858,7 +2857,7 @@ func (c *containerLXC) cleanupDevices(netns string) {
 }
 
 // Freezer functions
-func (c *containerLXC) Freeze() error {
+func (c *lxc) Freeze() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
 		"name":      c.name,
@@ -2911,7 +2910,7 @@ func (c *containerLXC) Freeze() error {
 	return err
 }
 
-func (c *containerLXC) Unfreeze() error {
+func (c *lxc) Unfreeze() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
 		"name":      c.name,
@@ -2965,7 +2964,7 @@ var LxcMonitorStateError = fmt.Errorf("Monitor is hung")
 
 // Get lxc container state, with 1 second timeout
 // If we don't get a reply, assume the lxc monitor is hung
-func (c *containerLXC) getLxcState() (lxc.State, error) {
+func (c *lxc) getLxcState() (liblxc.State, error) {
 	if c.IsSnapshot() {
 		return lxc.StateMap["STOPPED"], nil
 	}
@@ -2986,11 +2985,11 @@ func (c *containerLXC) getLxcState() (lxc.State, error) {
 	case state := <-monitor:
 		return state, nil
 	case <-time.After(5 * time.Second):
-		return lxc.StateMap["FROZEN"], LxcMonitorStateError
+		return liblxc.StateMap["FROZEN"], LxcMonitorStateError
 	}
 }
 
-func (c *containerLXC) Render() (interface{}, interface{}, error) {
+func (c *lxc) Render() (interface{}, interface{}, error) {
 	// Ignore err as the arch string on error is correct (unknown)
 	architectureName, _ := osarch.ArchitectureName(c.architecture)
 
@@ -3049,7 +3048,7 @@ func (c *containerLXC) Render() (interface{}, interface{}, error) {
 	return &ct, etag, nil
 }
 
-func (c *containerLXC) RenderFull() (*api.InstanceFull, interface{}, error) {
+func (c *lxc) RenderFull() (*api.InstanceFull, interface{}, error) {
 	if c.IsSnapshot() {
 		return nil, nil, fmt.Errorf("RenderFull only works with containers")
 	}
@@ -3107,7 +3106,7 @@ func (c *containerLXC) RenderFull() (*api.InstanceFull, interface{}, error) {
 	return &ct, etag, nil
 }
 
-func (c *containerLXC) RenderState() (*api.InstanceState, error) {
+func (c *lxc) RenderState() (*api.InstanceState, error) {
 	cState, err := c.getLxcState()
 	if err != nil {
 		return nil, err
@@ -3131,7 +3130,7 @@ func (c *containerLXC) RenderState() (*api.InstanceState, error) {
 	return &status, nil
 }
 
-func (c *containerLXC) Snapshots() ([]instance.Instance, error) {
+func (c *lxc) Snapshots() ([]instance.Instance, error) {
 	var snaps []db.Instance
 
 	if c.IsSnapshot() {
@@ -3166,7 +3165,7 @@ func (c *containerLXC) Snapshots() ([]instance.Instance, error) {
 	return instances, nil
 }
 
-func (c *containerLXC) Backups() ([]backup.Backup, error) {
+func (c *lxc) Backups() ([]backup.Backup, error) {
 	// Get all the backups
 	backupNames, err := c.state.Cluster.ContainerGetBackups(c.project, c.name)
 	if err != nil {
@@ -3188,7 +3187,7 @@ func (c *containerLXC) Backups() ([]backup.Backup, error) {
 }
 
 // Restore restores a snapshot.
-func (c *containerLXC) Restore(sourceContainer instance.Instance, stateful bool) error {
+func (c *lxc) Restore(sourceContainer instance.Instance, stateful bool) error {
 	var ctxMap log.Ctx
 
 	// Initialize storage interface for the container and mount the rootfs for criu state check.
@@ -3313,14 +3312,14 @@ func (c *containerLXC) Restore(sourceContainer instance.Instance, stateful bool)
 		logger.Debug("Performing stateful restore", ctxMap)
 		c.stateful = true
 
-		criuMigrationArgs := CriuMigrationArgs{
-			cmd:          lxc.MIGRATE_RESTORE,
-			stateDir:     c.StatePath(),
-			function:     "snapshot",
-			stop:         false,
-			actionScript: false,
-			dumpDir:      "",
-			preDumpDir:   "",
+		criuMigrationArgs := instance.CriuMigrationArgs{
+			Cmd:          liblxc.MIGRATE_RESTORE,
+			StateDir:     c.StatePath(),
+			Function:     "snapshot",
+			Stop:         false,
+			ActionScript: false,
+			DumpDir:      "",
+			PreDumpDir:   "",
 		}
 
 		// Checkpoint.
@@ -3360,7 +3359,7 @@ func (c *containerLXC) Restore(sourceContainer instance.Instance, stateful bool)
 	return nil
 }
 
-func (c *containerLXC) cleanup() {
+func (c *lxc) cleanup() {
 	// Unmount any leftovers
 	c.removeUnixDevices()
 	c.removeDiskDevices()
@@ -3376,7 +3375,7 @@ func (c *containerLXC) cleanup() {
 	os.RemoveAll(c.ShmountsPath())
 }
 
-func (c *containerLXC) Delete() error {
+func (c *lxc) Delete() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
 		"name":      c.name,
@@ -3490,7 +3489,7 @@ func (c *containerLXC) Delete() error {
 	return nil
 }
 
-func (c *containerLXC) Rename(newName string) error {
+func (c *lxc) Rename(newName string) error {
 	oldName := c.Name()
 	ctxMap := log.Ctx{
 		"project":   c.project,
@@ -3636,7 +3635,7 @@ func (c *containerLXC) Rename(newName string) error {
 	return nil
 }
 
-func (c *containerLXC) CGroupGet(key string) (string, error) {
+func (c *lxc) CGroupGet(key string) (string, error) {
 	// Load the go-lxc struct
 	err := c.initLXC(false)
 	if err != nil {
@@ -3652,7 +3651,7 @@ func (c *containerLXC) CGroupGet(key string) (string, error) {
 	return strings.Join(value, "\n"), nil
 }
 
-func (c *containerLXC) CGroupSet(key string, value string) error {
+func (c *lxc) CGroupSet(key string, value string) error {
 	// Load the go-lxc struct
 	err := c.initLXC(false)
 	if err != nil {
@@ -3672,7 +3671,7 @@ func (c *containerLXC) CGroupSet(key string, value string) error {
 	return nil
 }
 
-func (c *containerLXC) VolatileSet(changes map[string]string) error {
+func (c *lxc) VolatileSet(changes map[string]string) error {
 	// Sanity check
 	for key := range changes {
 		if !strings.HasPrefix(key, "volatile.") {
@@ -3710,7 +3709,7 @@ func (c *containerLXC) VolatileSet(changes map[string]string) error {
 	return nil
 }
 
-func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
+func (c *lxc) Update(args db.InstanceArgs, userRequested bool) error {
 	// Set sane defaults for unset keys
 	if args.Project == "" {
 		args.Project = "default"
@@ -4433,7 +4432,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
 	return nil
 }
 
-func (c *containerLXC) updateDevices(removeDevices deviceConfig.Devices, addDevices deviceConfig.Devices, updateDevices deviceConfig.Devices, oldExpandedDevices deviceConfig.Devices) error {
+func (c *lxc) updateDevices(removeDevices deviceConfig.Devices, addDevices deviceConfig.Devices, updateDevices deviceConfig.Devices, oldExpandedDevices deviceConfig.Devices) error {
 	isRunning := c.IsRunning()
 
 	// Remove devices in reverse order to how they were added.
@@ -4488,7 +4487,7 @@ func (c *containerLXC) updateDevices(removeDevices deviceConfig.Devices, addDevi
 	return nil
 }
 
-func (c *containerLXC) Export(w io.Writer, properties map[string]string) error {
+func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
 		"name":      c.name,
@@ -4735,18 +4734,7 @@ func getCRIULogErrors(imagesDir string, method string) (string, error) {
 	return strings.Join(ret, "\n"), nil
 }
 
-type CriuMigrationArgs struct {
-	cmd          uint
-	stateDir     string
-	function     string
-	stop         bool
-	actionScript bool
-	dumpDir      string
-	preDumpDir   string
-	features     lxc.CriuFeatures
-}
-
-func (c *containerLXC) Migrate(args *CriuMigrationArgs) error {
+func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 	ctxMap := log.Ctx{
 		"project":      c.project,
 		"name":         c.name,
@@ -4954,7 +4942,7 @@ func (c *containerLXC) Migrate(args *CriuMigrationArgs) error {
 
 // DeferTemplateApply sets volatile key to apply template on next start. Used when instance's
 // volume isn't mounted.
-func (c *containerLXC) DeferTemplateApply(trigger string) error {
+func (c *lxc) DeferTemplateApply(trigger string) error {
 	err := c.VolatileSet(map[string]string{"volatile.apply_template": trigger})
 	if err != nil {
 		return errors.Wrap(err, "Failed to set apply_template volatile key")
@@ -4963,7 +4951,7 @@ func (c *containerLXC) DeferTemplateApply(trigger string) error {
 	return nil
 }
 
-func (c *containerLXC) templateApplyNow(trigger string) error {
+func (c *lxc) templateApplyNow(trigger string) error {
 	// If there's no metadata, just return
 	fname := filepath.Join(c.Path(), "metadata.yaml")
 	if !shared.PathExists(fname) {
@@ -5105,7 +5093,7 @@ func (c *containerLXC) templateApplyNow(trigger string) error {
 	return nil
 }
 
-func (c *containerLXC) FileExists(path string) error {
+func (c *lxc) FileExists(path string) error {
 	// Setup container storage if needed
 	var ourStart bool
 	var err error
@@ -5153,7 +5141,7 @@ func (c *containerLXC) FileExists(path string) error {
 	return nil
 }
 
-func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, os.FileMode, string, []string, error) {
+func (c *lxc) FilePull(srcpath string, dstpath string) (int64, int64, os.FileMode, string, []string, error) {
 	// Check for ongoing operations (that may involve shifting).
 	op := operationlock.Get(c.id)
 	if op != nil {
@@ -5282,7 +5270,7 @@ func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, o
 	return uid, gid, os.FileMode(mode), type_, dirEnts, nil
 }
 
-func (c *containerLXC) FilePush(type_ string, srcpath string, dstpath string, uid int64, gid int64, mode int, write string) error {
+func (c *lxc) FilePush(type_ string, srcpath string, dstpath string, uid int64, gid int64, mode int, write string) error {
 	// Check for ongoing operations (that may involve shifting).
 	op := operationlock.Get(c.id)
 	if op != nil {
@@ -5378,7 +5366,7 @@ func (c *containerLXC) FilePush(type_ string, srcpath string, dstpath string, ui
 	return nil
 }
 
-func (c *containerLXC) FileRemove(path string) error {
+func (c *lxc) FileRemove(path string) error {
 	var errStr string
 	var ourStart bool
 	var err error
@@ -5439,7 +5427,7 @@ func (c *containerLXC) FileRemove(path string) error {
 	return nil
 }
 
-func (c *containerLXC) Console() (*os.File, chan error, error) {
+func (c *lxc) Console() (*os.File, chan error, error) {
 	chDisconnect := make(chan error, 1)
 
 	args := []string{
@@ -5492,7 +5480,7 @@ func (c *containerLXC) Console() (*os.File, chan error, error) {
 	return master, chDisconnect, nil
 }
 
-func (c *containerLXC) ConsoleLog(opts lxc.ConsoleLogOptions) (string, error) {
+func (c *lxc) ConsoleLog(opts liblxc.ConsoleLogOptions) (string, error) {
 	msg, err := c.c.ConsoleLog(opts)
 	if err != nil {
 		return "", err
@@ -5501,7 +5489,7 @@ func (c *containerLXC) ConsoleLog(opts lxc.ConsoleLogOptions) (string, error) {
 	return string(msg), nil
 }
 
-func (c *containerLXC) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os.File, stderr *os.File) (instance.Cmd, error) {
+func (c *lxc) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os.File, stderr *os.File) (instance.Cmd, error) {
 	// Prepare the environment
 	envSlice := []string{}
 
@@ -5583,7 +5571,7 @@ func (c *containerLXC) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os
 		return nil, err
 	}
 
-	instCmd := &ContainerLXCCmd{
+	instCmd := &lxcCmd{
 		cmd:              &cmd,
 		attachedChildPid: attachedPid,
 	}
@@ -5591,7 +5579,7 @@ func (c *containerLXC) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os
 	return instCmd, nil
 }
 
-func (c *containerLXC) cpuState() api.InstanceStateCPU {
+func (c *lxc) cpuState() api.InstanceStateCPU {
 	cpu := api.InstanceStateCPU{}
 
 	// CPU usage in seconds
@@ -5621,7 +5609,7 @@ func (c *containerLXC) cpuState() api.InstanceStateCPU {
 	return cpu
 }
 
-func (c *containerLXC) diskState() map[string]api.InstanceStateDisk {
+func (c *lxc) diskState() map[string]api.InstanceStateDisk {
 	disk := map[string]api.InstanceStateDisk{}
 
 	for _, dev := range c.expandedDevices.Sorted() {
@@ -5655,7 +5643,7 @@ func (c *containerLXC) diskState() map[string]api.InstanceStateDisk {
 	return disk
 }
 
-func (c *containerLXC) memoryState() api.InstanceStateMemory {
+func (c *lxc) memoryState() api.InstanceStateMemory {
 	memory := api.InstanceStateMemory{}
 	cg, err := c.cgroup(nil)
 	if err != nil {
@@ -5705,7 +5693,7 @@ func (c *containerLXC) memoryState() api.InstanceStateMemory {
 	return memory
 }
 
-func (c *containerLXC) networkState() map[string]api.InstanceStateNetwork {
+func (c *lxc) networkState() map[string]api.InstanceStateNetwork {
 	result := map[string]api.InstanceStateNetwork{}
 
 	pid := c.InitPID()
@@ -5763,7 +5751,7 @@ func (c *containerLXC) networkState() map[string]api.InstanceStateNetwork {
 	return result
 }
 
-func (c *containerLXC) processesState() int64 {
+func (c *lxc) processesState() int64 {
 	// Return 0 if not running
 	pid := c.InitPID()
 	if pid == -1 {
@@ -5813,8 +5801,8 @@ func (c *containerLXC) processesState() int64 {
 }
 
 // getStoragePool returns the current storage pool handle. To avoid a DB lookup each time this
-// function is called, the handle is cached internally in the containerLXC struct.
-func (c *containerLXC) getStoragePool() (storagePools.Pool, error) {
+// function is called, the handle is cached internally in the lxc struct.
+func (c *lxc) getStoragePool() (storagePools.Pool, error) {
 	if c.storagePool != nil {
 		return c.storagePool, nil
 	}
@@ -5829,7 +5817,7 @@ func (c *containerLXC) getStoragePool() (storagePools.Pool, error) {
 }
 
 // getStorageType returns the storage type of the instance's storage pool.
-func (c *containerLXC) getStorageType() (string, error) {
+func (c *lxc) getStorageType() (string, error) {
 	pool, err := c.getStoragePool()
 	if err != nil {
 		return "", err
@@ -5839,12 +5827,12 @@ func (c *containerLXC) getStorageType() (string, error) {
 }
 
 // StorageStart mounts the instance's rootfs volume. Deprecated.
-func (c *containerLXC) StorageStart() (bool, error) {
+func (c *lxc) StorageStart() (bool, error) {
 	return c.mount()
 }
 
 // mount the instance's rootfs volume if needed.
-func (c *containerLXC) mount() (bool, error) {
+func (c *lxc) mount() (bool, error) {
 	pool, err := c.getStoragePool()
 	if err != nil {
 		return false, err
@@ -5868,12 +5856,12 @@ func (c *containerLXC) mount() (bool, error) {
 }
 
 // StorageStop unmounts the instance's rootfs volume. Deprecated.
-func (c *containerLXC) StorageStop() (bool, error) {
+func (c *lxc) StorageStop() (bool, error) {
 	return c.unmount()
 }
 
 // unmount the instance's rootfs volume if needed.
-func (c *containerLXC) unmount() (bool, error) {
+func (c *lxc) unmount() (bool, error) {
 	pool, err := c.getStoragePool()
 	if err != nil {
 		return false, err
@@ -5897,7 +5885,7 @@ func (c *containerLXC) unmount() (bool, error) {
 }
 
 // Mount handling
-func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int, mntnsPID int, shiftfs bool) error {
+func (c *lxc) insertMountLXD(source, target, fstype string, flags int, mntnsPID int, shiftfs bool) error {
 	pid := mntnsPID
 	if pid <= 0 {
 		// Get the init PID
@@ -5955,7 +5943,7 @@ func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int,
 	return nil
 }
 
-func (c *containerLXC) insertMountLXC(source, target, fstype string, flags int) error {
+func (c *lxc) insertMountLXC(source, target, fstype string, flags int) error {
 	cname := project.Prefix(c.Project(), c.Name())
 	configPath := filepath.Join(c.LogPath(), "lxc.conf")
 	if fstype == "" {
@@ -5974,7 +5962,7 @@ func (c *containerLXC) insertMountLXC(source, target, fstype string, flags int)
 	return nil
 }
 
-func (c *containerLXC) insertMount(source, target, fstype string, flags int, shiftfs bool) error {
+func (c *lxc) insertMount(source, target, fstype string, flags int, shiftfs bool) error {
 	if c.state.OS.LXCFeatures["mount_injection_file"] && !shiftfs {
 		return c.insertMountLXC(source, target, fstype, flags)
 	}
@@ -5982,7 +5970,7 @@ func (c *containerLXC) insertMount(source, target, fstype string, flags int, shi
 	return c.insertMountLXD(source, target, fstype, flags, -1, shiftfs)
 }
 
-func (c *containerLXC) removeMount(mount string) error {
+func (c *lxc) removeMount(mount string) error {
 	// Get the init PID
 	pid := c.InitPID()
 	if pid == -1 {
@@ -6014,7 +6002,7 @@ func (c *containerLXC) removeMount(mount string) error {
 	return nil
 }
 
-func (c *containerLXC) InsertSeccompUnixDevice(prefix string, m deviceConfig.Device, pid int) error {
+func (c *lxc) InsertSeccompUnixDevice(prefix string, m deviceConfig.Device, pid int) error {
 	if pid < 0 {
 		return fmt.Errorf("Invalid request PID specified")
 	}
@@ -6069,7 +6057,7 @@ func (c *containerLXC) InsertSeccompUnixDevice(prefix string, m deviceConfig.Dev
 	return c.insertMountLXD(devPath, tgtPath, "none", unix.MS_BIND, pid, false)
 }
 
-func (c *containerLXC) removeUnixDevices() error {
+func (c *lxc) removeUnixDevices() error {
 	// Check that we indeed have devices to remove
 	if !shared.PathExists(c.DevicesPath()) {
 		return nil
@@ -6101,7 +6089,7 @@ func (c *containerLXC) removeUnixDevices() error {
 
 // FillNetworkDevice takes a nic or infiniband device type and enriches it with automatically
 // generated name and hwaddr properties if these are missing from the device.
-func (c *containerLXC) FillNetworkDevice(name string, m deviceConfig.Device) (deviceConfig.Device, error) {
+func (c *lxc) FillNetworkDevice(name string, m deviceConfig.Device) (deviceConfig.Device, error) {
 	var err error
 	newDevice := m.Clone()
 
@@ -6260,7 +6248,7 @@ func (c *containerLXC) FillNetworkDevice(name string, m deviceConfig.Device) (de
 	return newDevice, nil
 }
 
-func (c *containerLXC) removeDiskDevices() error {
+func (c *lxc) removeDiskDevices() error {
 	// Check that we indeed have devices to remove
 	if !shared.PathExists(c.DevicesPath()) {
 		return nil
@@ -6294,7 +6282,7 @@ func (c *containerLXC) removeDiskDevices() error {
 }
 
 // Network I/O limits
-func (c *containerLXC) setNetworkPriority() error {
+func (c *lxc) setNetworkPriority() error {
 	cg, err := c.cgroup(nil)
 	if err != nil {
 		return err
@@ -6347,23 +6335,23 @@ func (c *containerLXC) setNetworkPriority() error {
 }
 
 // Various state query functions
-func (c *containerLXC) IsStateful() bool {
+func (c *lxc) IsStateful() bool {
 	return c.stateful
 }
 
-func (c *containerLXC) IsEphemeral() bool {
+func (c *lxc) IsEphemeral() bool {
 	return c.ephemeral
 }
 
-func (c *containerLXC) IsFrozen() bool {
+func (c *lxc) IsFrozen() bool {
 	return c.State() == "FROZEN"
 }
 
-func (c *containerLXC) IsNesting() bool {
+func (c *lxc) IsNesting() bool {
 	return shared.IsTrue(c.expandedConfig["security.nesting"])
 }
 
-func (c *containerLXC) isCurrentlyPrivileged() bool {
+func (c *lxc) isCurrentlyPrivileged() bool {
 	if !c.IsRunning() {
 		return c.IsPrivileged()
 	}
@@ -6376,44 +6364,44 @@ func (c *containerLXC) isCurrentlyPrivileged() bool {
 	return idmap == nil
 }
 
-func (c *containerLXC) IsPrivileged() bool {
+func (c *lxc) IsPrivileged() bool {
 	return shared.IsTrue(c.expandedConfig["security.privileged"])
 }
 
-func (c *containerLXC) IsRunning() bool {
+func (c *lxc) IsRunning() bool {
 	state := c.State()
 	return state != "BROKEN" && state != "STOPPED"
 }
 
-func (c *containerLXC) IsSnapshot() bool {
+func (c *lxc) IsSnapshot() bool {
 	return c.snapshot
 }
 
 // Various property query functions
-func (c *containerLXC) Architecture() int {
+func (c *lxc) Architecture() int {
 	return c.architecture
 }
 
-func (c *containerLXC) CreationDate() time.Time {
+func (c *lxc) CreationDate() time.Time {
 	return c.creationDate
 }
-func (c *containerLXC) LastUsedDate() time.Time {
+func (c *lxc) LastUsedDate() time.Time {
 	return c.lastUsedDate
 }
-func (c *containerLXC) ExpandedConfig() map[string]string {
+func (c *lxc) ExpandedConfig() map[string]string {
 	return c.expandedConfig
 }
 
-func (c *containerLXC) ExpandedDevices() deviceConfig.Devices {
+func (c *lxc) ExpandedDevices() deviceConfig.Devices {
 	return c.expandedDevices
 }
 
 // ID gets container's ID.
-func (c *containerLXC) ID() int {
+func (c *lxc) ID() int {
 	return c.id
 }
 
-func (c *containerLXC) InitPID() int {
+func (c *lxc) InitPID() int {
 	// Load the go-lxc struct
 	err := c.initLXC(false)
 	if err != nil {
@@ -6423,42 +6411,42 @@ func (c *containerLXC) InitPID() int {
 	return c.c.InitPid()
 }
 
-func (c *containerLXC) LocalConfig() map[string]string {
+func (c *lxc) LocalConfig() map[string]string {
 	return c.localConfig
 }
 
-func (c *containerLXC) LocalDevices() deviceConfig.Devices {
+func (c *lxc) LocalDevices() deviceConfig.Devices {
 	return c.localDevices
 }
 
-func (c *containerLXC) CurrentIdmap() (*idmap.IdmapSet, error) {
+func (c *lxc) CurrentIdmap() (*idmap.IdmapSet, error) {
 	jsonIdmap, ok := c.LocalConfig()["volatile.idmap.current"]
 	if !ok {
 		return c.DiskIdmap()
 	}
 
-	return idmapsetFromString(jsonIdmap)
+	return storageDrivers.IDMapsetFromString(jsonIdmap)
 }
 
-func (c *containerLXC) DiskIdmap() (*idmap.IdmapSet, error) {
+func (c *lxc) DiskIdmap() (*idmap.IdmapSet, error) {
 	jsonIdmap, ok := c.LocalConfig()["volatile.last_state.idmap"]
 	if !ok {
 		return nil, nil
 	}
 
-	return idmapsetFromString(jsonIdmap)
+	return storageDrivers.IDMapsetFromString(jsonIdmap)
 }
 
-func (c *containerLXC) NextIdmap() (*idmap.IdmapSet, error) {
+func (c *lxc) NextIdmap() (*idmap.IdmapSet, error) {
 	jsonIdmap, ok := c.LocalConfig()["volatile.idmap.next"]
 	if !ok {
 		return c.CurrentIdmap()
 	}
 
-	return idmapsetFromString(jsonIdmap)
+	return storageDrivers.IDMapsetFromString(jsonIdmap)
 }
 
-func (c *containerLXC) DaemonState() *state.State {
+func (c *lxc) DaemonState() *state.State {
 	// FIXME: This function should go away, since the abstract container
 	//        interface should not be coupled with internal state details.
 	//        However this is not currently possible, because many
@@ -6468,27 +6456,27 @@ func (c *containerLXC) DaemonState() *state.State {
 	return c.state
 }
 
-func (c *containerLXC) Location() string {
+func (c *lxc) Location() string {
 	return c.node
 }
 
-func (c *containerLXC) Project() string {
+func (c *lxc) Project() string {
 	return c.project
 }
 
-func (c *containerLXC) Name() string {
+func (c *lxc) Name() string {
 	return c.name
 }
 
-func (c *containerLXC) Description() string {
+func (c *lxc) Description() string {
 	return c.description
 }
 
-func (c *containerLXC) Profiles() []string {
+func (c *lxc) Profiles() []string {
 	return c.profiles
 }
 
-func (c *containerLXC) State() string {
+func (c *lxc) State() string {
 	state, err := c.getLxcState()
 	if err != nil {
 		return api.Error.String()
@@ -6497,42 +6485,42 @@ func (c *containerLXC) State() string {
 }
 
 // Various container paths
-func (c *containerLXC) Path() string {
+func (c *lxc) Path() string {
 	return storagePools.InstancePath(c.Type(), c.Project(), c.Name(), c.IsSnapshot())
 }
 
-func (c *containerLXC) DevicesPath() string {
+func (c *lxc) DevicesPath() string {
 	name := project.Prefix(c.Project(), c.Name())
 	return shared.VarPath("devices", name)
 }
 
-func (c *containerLXC) ShmountsPath() string {
+func (c *lxc) ShmountsPath() string {
 	name := project.Prefix(c.Project(), c.Name())
 	return shared.VarPath("shmounts", name)
 }
 
-func (c *containerLXC) LogPath() string {
+func (c *lxc) LogPath() string {
 	name := project.Prefix(c.Project(), c.Name())
 	return shared.LogPath(name)
 }
 
-func (c *containerLXC) LogFilePath() string {
+func (c *lxc) LogFilePath() string {
 	return filepath.Join(c.LogPath(), "lxc.log")
 }
 
-func (c *containerLXC) ConsoleBufferLogPath() string {
+func (c *lxc) ConsoleBufferLogPath() string {
 	return filepath.Join(c.LogPath(), "console.log")
 }
 
-func (c *containerLXC) RootfsPath() string {
+func (c *lxc) RootfsPath() string {
 	return filepath.Join(c.Path(), "rootfs")
 }
 
-func (c *containerLXC) TemplatesPath() string {
+func (c *lxc) TemplatesPath() string {
 	return filepath.Join(c.Path(), "templates")
 }
 
-func (c *containerLXC) StatePath() string {
+func (c *lxc) StatePath() string {
 	/* FIXME: backwards compatibility: we used to use Join(RootfsPath(),
 	 * "state"), which was bad. Let's just check to see if that directory
 	 * exists.
@@ -6544,7 +6532,7 @@ func (c *containerLXC) StatePath() string {
 	return filepath.Join(c.Path(), "state")
 }
 
-func (c *containerLXC) StoragePool() (string, error) {
+func (c *lxc) StoragePool() (string, error) {
 	poolName, err := c.state.Cluster.InstancePool(c.Project(), c.Name())
 	if err != nil {
 		return "", err
@@ -6554,11 +6542,11 @@ func (c *containerLXC) StoragePool() (string, error) {
 }
 
 // Progress tracking
-func (c *containerLXC) SetOperation(op *operations.Operation) {
+func (c *lxc) SetOperation(op *operations.Operation) {
 	c.op = op
 }
 
-func (c *containerLXC) ExpiryDate() time.Time {
+func (c *lxc) ExpiryDate() time.Time {
 	if c.IsSnapshot() {
 		return c.expiryDate
 	}
@@ -6567,7 +6555,7 @@ func (c *containerLXC) ExpiryDate() time.Time {
 	return time.Time{}
 }
 
-func (c *containerLXC) updateProgress(progress string) {
+func (c *lxc) updateProgress(progress string) {
 	if c.op == nil {
 		return
 	}
@@ -6584,7 +6572,7 @@ func (c *containerLXC) updateProgress(progress string) {
 }
 
 // Internal MAAS handling
-func (c *containerLXC) maasInterfaces(devices map[string]map[string]string) ([]maas.ContainerInterface, error) {
+func (c *lxc) maasInterfaces(devices map[string]map[string]string) ([]maas.ContainerInterface, error) {
 	interfaces := []maas.ContainerInterface{}
 	for k, m := range devices {
 		if m["type"] != "nic" {
@@ -6634,7 +6622,7 @@ func (c *containerLXC) maasInterfaces(devices map[string]map[string]string) ([]m
 	return interfaces, nil
 }
 
-func (c *containerLXC) maasUpdate(oldDevices map[string]map[string]string) error {
+func (c *lxc) maasUpdate(oldDevices map[string]map[string]string) error {
 	// Check if MAAS is configured
 	maasURL, err := cluster.ConfigGetString(c.state.Cluster, "maas.api.url")
 	if err != nil {
@@ -6684,7 +6672,7 @@ func (c *containerLXC) maasUpdate(oldDevices map[string]map[string]string) error
 	return c.state.MAAS.CreateContainer(project.Prefix(c.project, c.name), interfaces)
 }
 
-func (c *containerLXC) maasRename(newName string) error {
+func (c *lxc) maasRename(newName string) error {
 	maasURL, err := cluster.ConfigGetString(c.state.Cluster, "maas.api.url")
 	if err != nil {
 		return err
@@ -6719,7 +6707,7 @@ func (c *containerLXC) maasRename(newName string) error {
 	return c.state.MAAS.RenameContainer(project.Prefix(c.project, c.name), project.Prefix(c.project, newName))
 }
 
-func (c *containerLXC) maasDelete() error {
+func (c *lxc) maasDelete() error {
 	maasURL, err := cluster.ConfigGetString(c.state.Cluster, "maas.api.url")
 	if err != nil {
 		return err
@@ -6754,7 +6742,7 @@ func (c *containerLXC) maasDelete() error {
 	return c.state.MAAS.DeleteContainer(project.Prefix(c.project, c.name))
 }
 
-func (c *containerLXC) cgroup(cc *lxc.Container) (*cgroup.CGroup, error) {
+func (c *lxc) cgroup(cc *liblxc.Container) (*cgroup.CGroup, error) {
 	rw := lxcCgroupReadWriter{}
 	if cc != nil {
 		rw.cc = cc
@@ -6805,7 +6793,7 @@ func (rw *lxcCgroupReadWriter) Set(version cgroup.Backend, controller string, ke
 }
 
 // UpdateBackupFile writes the instance's backup.yaml file to storage.
-func (c *containerLXC) UpdateBackupFile() error {
+func (c *lxc) UpdateBackupFile() error {
 	pool, err := c.getStoragePool()
 	if err != nil {
 		return err

From 6c7099080497acf90c09d6b177c35764a6e910fa Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:50:36 +0000
Subject: [PATCH 16/62] lxd/instance/drivers/driver/lxc: Removes temporary
 loader placeholders

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index e0809956b8..06650943be 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -57,15 +57,6 @@ import (
 	"github.com/lxc/lxd/shared/units"
 )
 
-func init() {
-	// Temporarily link containerLXC load functions to instanceDrivers package so it can be used by the
-	// internal loader functions. These can be removed once containerLXC type is moved into the
-	// instance/drivers package.
-	instanceDrivers.LXCLoad = containerLXCLoad
-	instanceDrivers.LXCInstantiate = containerLXCInstantiate
-	instanceDrivers.LXCCreate = containerLXCCreate
-}
-
 // Helper functions
 func lxcSetConfigItem(c *lxc.Container, key string, value string) error {
 	if c == nil {

From 76b2e1e13e6ce336f0a2ec9637b34d9b903fb368 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:52:05 +0000
Subject: [PATCH 17/62] lxd/instance/drivers/driver/lxc: Renames lxc to liblxc

For clarity that this is the external lxc package (with the view that eventually LXC type will be renamed to lxc).

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 06650943be..31b745cf62 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -21,7 +21,7 @@ import (
 	"github.com/flosch/pongo2"
 	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
-	lxc "gopkg.in/lxc/go-lxc.v2"
+	liblxc "gopkg.in/lxc/go-lxc.v2"
 	yaml "gopkg.in/yaml.v2"
 
 	"github.com/lxc/lxd/lxd/apparmor"
@@ -58,7 +58,7 @@ import (
 )
 
 // Helper functions
-func lxcSetConfigItem(c *lxc.Container, key string, value string) error {
+func lxcSetConfigItem(c *liblxc.Container, key string, value string) error {
 	if c == nil {
 		return fmt.Errorf("Uninitialized go-lxc struct")
 	}
@@ -122,7 +122,7 @@ func lxcSetConfigItem(c *lxc.Container, key string, value string) error {
 	return nil
 }
 
-func lxcStatusCode(state lxc.State) api.StatusCode {
+func lxcStatusCode(state liblxc.State) api.StatusCode {
 	return map[int]api.StatusCode{
 		1: api.Stopped,
 		2: api.Starting,
@@ -441,7 +441,7 @@ type lxc struct {
 	profiles        []string
 
 	// Cache
-	c       *lxc.Container
+	c       *liblxc.Container
 	cConfig bool
 
 	state    *state.State
@@ -684,7 +684,7 @@ func (c *lxc) initLXC(config bool) error {
 
 	// Load the go-lxc struct
 	cname := project.Prefix(c.Project(), c.Name())
-	cc, err := lxc.NewContainer(cname, c.state.OS.LxcPath)
+	cc, err := liblxc.NewContainer(cname, c.state.OS.LxcPath)
 	if err != nil {
 		return err
 	}
@@ -1561,7 +1561,7 @@ func (c *lxc) deviceDetachNIC(configCopy map[string]string, netIF []deviceConfig
 	if stopHookNetnsPath == "" {
 		// For some reason, having network config confuses detach, so get our own go-lxc struct.
 		cname := project.Prefix(c.Project(), c.Name())
-		cc, err := lxc.NewContainer(cname, c.state.OS.LxcPath)
+		cc, err := liblxc.NewContainer(cname, c.state.OS.LxcPath)
 		if err != nil {
 			return err
 		}
@@ -2957,18 +2957,18 @@ var LxcMonitorStateError = fmt.Errorf("Monitor is hung")
 // If we don't get a reply, assume the lxc monitor is hung
 func (c *lxc) getLxcState() (liblxc.State, error) {
 	if c.IsSnapshot() {
-		return lxc.StateMap["STOPPED"], nil
+		return liblxc.StateMap["STOPPED"], nil
 	}
 
 	// Load the go-lxc struct
 	err := c.initLXC(false)
 	if err != nil {
-		return lxc.StateMap["STOPPED"], err
+		return liblxc.StateMap["STOPPED"], err
 	}
 
-	monitor := make(chan lxc.State, 1)
+	monitor := make(chan liblxc.State, 1)
 
-	go func(c *lxc.Container) {
+	go func(c *liblxc.Container) {
 		monitor <- c.State()
 	}(c.c)
 
@@ -6115,7 +6115,7 @@ func (c *lxc) FillNetworkDevice(name string, m deviceConfig.Device) (deviceConfi
 
 		// Attempt to include all existing interfaces
 		cname := project.Prefix(c.Project(), c.Name())
-		cc, err := lxc.NewContainer(cname, c.state.OS.LxcPath)
+		cc, err := liblxc.NewContainer(cname, c.state.OS.LxcPath)
 		if err == nil {
 			defer cc.Release()
 
@@ -6747,12 +6747,12 @@ func (c *lxc) cgroup(cc *liblxc.Container) (*cgroup.CGroup, error) {
 		return nil, err
 	}
 
-	cg.UnifiedCapable = lxc.HasApiExtension("cgroup2")
+	cg.UnifiedCapable = liblxc.HasApiExtension("cgroup2")
 	return cg, nil
 }
 
 type lxcCgroupReadWriter struct {
-	cc      *lxc.Container
+	cc      *liblxc.Container
 	conf    bool
 	cgroup2 bool
 }

From 783e08e135c21fa8d65a77fe00c133487dc6ffb5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:53:37 +0000
Subject: [PATCH 18/62] lxd/instance/drivers/driver/lxc:
 db.StoragePoolVolumeTypeContainer usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 31b745cf62..9e0ed0b63b 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -233,7 +233,7 @@ func lxcCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error)
 	}
 
 	// Create a new database entry for the container's storage volume
-	_, err = s.Cluster.StoragePoolVolumeCreate(args.Project, args.Name, "", storagePoolVolumeTypeContainer, c.IsSnapshot(), poolID, volumeConfig)
+	_, err = s.Cluster.StoragePoolVolumeCreate(args.Project, args.Name, "", db.StoragePoolVolumeTypeContainer, c.IsSnapshot(), poolID, volumeConfig)
 	if err != nil {
 		c.Delete()
 		return nil, err
@@ -243,7 +243,7 @@ func lxcCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error)
 	pool, err := storagePools.GetPoolByInstance(c.state, c)
 	if err != nil {
 		c.Delete()
-		s.Cluster.StoragePoolVolumeDelete(args.Project, args.Name, storagePoolVolumeTypeContainer, poolID)
+		s.Cluster.StoragePoolVolumeDelete(args.Project, args.Name, db.StoragePoolVolumeTypeContainer, poolID)
 		logger.Error("Failed to initialize container storage", ctxMap)
 		return nil, err
 	}

From 57a93d2d73a1a4da28711f788dd23498fe2b4cb6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:54:52 +0000
Subject: [PATCH 19/62] lxd/instance/drivers/driver/lxc: Adds devLxdSendEvent

Updates usage.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 85 +++++++++++++++++-------------
 1 file changed, 47 insertions(+), 38 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 9e0ed0b63b..be5c29f8bc 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -1264,6 +1264,15 @@ func (c *lxc) initLXC(config bool) error {
 	return nil
 }
 
+func (c *LXC) devlxdEventSend(eventType string, eventMessage interface{}) error {
+	event := shared.Jmap{}
+	event["type"] = eventType
+	event["timestamp"] = time.Now()
+	event["metadata"] = eventMessage
+
+	return c.state.DevlxdEvents.Send(strconv.Itoa(c.ID()), eventType, eventMessage)
+}
+
 // runHooks executes the callback functions returned from a function.
 func (c *lxc) runHooks(hooks []func() error) error {
 	// Run any post start hooks.
@@ -4359,7 +4368,7 @@ func (c *lxc) Update(args db.InstanceArgs, userRequested bool) error {
 				"value":     c.expandedConfig[key],
 			}
 
-			err = devlxdEventSend(c, "config", msg)
+			err = c.devlxdEventSend("config", msg)
 			if err != nil {
 				return err
 			}
@@ -4373,7 +4382,7 @@ func (c *lxc) Update(args db.InstanceArgs, userRequested bool) error {
 				"config": m,
 			}
 
-			err = devlxdEventSend(c, "device", msg)
+			err = c.devlxdEventSend("device", msg)
 			if err != nil {
 				return err
 			}
@@ -4386,7 +4395,7 @@ func (c *lxc) Update(args db.InstanceArgs, userRequested bool) error {
 				"config": m,
 			}
 
-			err = devlxdEventSend(c, "device", msg)
+			err = c.devlxdEventSend("device", msg)
 			if err != nil {
 				return err
 			}
@@ -4399,7 +4408,7 @@ func (c *lxc) Update(args db.InstanceArgs, userRequested bool) error {
 				"config": m,
 			}
 
-			err = devlxdEventSend(c, "device", msg)
+			err = c.devlxdEventSend("device", msg)
 			if err != nil {
 				return err
 			}
@@ -4732,11 +4741,11 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 		"created":      c.creationDate,
 		"ephemeral":    c.ephemeral,
 		"used":         c.lastUsedDate,
-		"statedir":     args.stateDir,
-		"actionscript": args.actionScript,
-		"predumpdir":   args.preDumpDir,
-		"features":     args.features,
-		"stop":         args.stop}
+		"statedir":     args.StateDir,
+		"actionscript": args.ActionScript,
+		"predumpdir":   args.PreDumpDir,
+		"features":     args.Features,
+		"stop":         args.Stop}
 
 	_, err := exec.LookPath("criu")
 	if err != nil {
@@ -4746,18 +4755,18 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 	logger.Info("Migrating container", ctxMap)
 
 	prettyCmd := ""
-	switch args.cmd {
-	case lxc.MIGRATE_PRE_DUMP:
+	switch args.Cmd {
+	case liblxc.MIGRATE_PRE_DUMP:
 		prettyCmd = "pre-dump"
-	case lxc.MIGRATE_DUMP:
+	case liblxc.MIGRATE_DUMP:
 		prettyCmd = "dump"
-	case lxc.MIGRATE_RESTORE:
+	case liblxc.MIGRATE_RESTORE:
 		prettyCmd = "restore"
-	case lxc.MIGRATE_FEATURE_CHECK:
+	case liblxc.MIGRATE_FEATURE_CHECK:
 		prettyCmd = "feature-check"
 	default:
 		prettyCmd = "unknown"
-		logger.Warn("Unknown migrate call", log.Ctx{"cmd": args.cmd})
+		logger.Warn("Unknown migrate call", log.Ctx{"cmd": args.Cmd})
 	}
 
 	pool, err := c.getStoragePool()
@@ -4774,14 +4783,14 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 		preservesInodes = false
 	}
 
-	finalStateDir := args.stateDir
+	finalStateDir := args.StateDir
 	var migrateErr error
 
 	/* For restore, we need an extra fork so that we daemonize monitor
 	 * instead of having it be a child of LXD, so let's hijack the command
 	 * here and do the extra fork.
 	 */
-	if args.cmd == lxc.MIGRATE_RESTORE {
+	if args.Cmd == liblxc.MIGRATE_RESTORE {
 		// Run the shared start
 		_, postStartHooks, err := c.startCommon()
 		if err != nil {
@@ -4811,11 +4820,11 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 			}
 
 			if storageType == "zfs" {
-				err = idmapset.ShiftRootfs(args.stateDir, shiftZfsSkipper)
+				err = idmapset.ShiftRootfs(args.StateDir, storageDrivers.ShiftZFSSkipper)
 			} else if storageType == "btrfs" {
-				err = ShiftBtrfsRootfs(args.stateDir, idmapset)
+				err = storageDrivers.ShiftBtrfsRootfs(args.StateDir, idmapset)
 			} else {
-				err = idmapset.ShiftRootfs(args.stateDir, nil)
+				err = idmapset.ShiftRootfs(args.StateDir, nil)
 			}
 			if ourStart {
 				_, err2 := c.unmount()
@@ -4831,8 +4840,8 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 
 		configPath := filepath.Join(c.LogPath(), "lxc.conf")
 
-		if args.dumpDir != "" {
-			finalStateDir = fmt.Sprintf("%s/%s", args.stateDir, args.dumpDir)
+		if args.DumpDir != "" {
+			finalStateDir = fmt.Sprintf("%s/%s", args.StateDir, args.DumpDir)
 		}
 
 		_, migrateErr = shared.RunCommand(
@@ -4853,16 +4862,16 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 				return err
 			}
 		}
-	} else if args.cmd == lxc.MIGRATE_FEATURE_CHECK {
+	} else if args.Cmd == liblxc.MIGRATE_FEATURE_CHECK {
 		err := c.initLXC(true)
 		if err != nil {
 			return err
 		}
 
-		opts := lxc.MigrateOptions{
-			FeaturesToCheck: args.features,
+		opts := liblxc.MigrateOptions{
+			FeaturesToCheck: args.Features,
 		}
-		migrateErr = c.c.Migrate(args.cmd, opts)
+		migrateErr = c.c.Migrate(args.Cmd, opts)
 		if migrateErr != nil {
 			logger.Info("CRIU feature check failed", ctxMap)
 			return migrateErr
@@ -4875,12 +4884,12 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 		}
 
 		script := ""
-		if args.actionScript {
-			script = filepath.Join(args.stateDir, "action.sh")
+		if args.ActionScript {
+			script = filepath.Join(args.StateDir, "action.sh")
 		}
 
-		if args.dumpDir != "" {
-			finalStateDir = fmt.Sprintf("%s/%s", args.stateDir, args.dumpDir)
+		if args.DumpDir != "" {
+			finalStateDir = fmt.Sprintf("%s/%s", args.StateDir, args.DumpDir)
 		}
 
 		// TODO: make this configurable? Ultimately I think we don't
@@ -4891,27 +4900,27 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 		// slow.
 		ghostLimit := uint64(256 * 1024 * 1024)
 
-		opts := lxc.MigrateOptions{
-			Stop:            args.stop,
+		opts := liblxc.MigrateOptions{
+			Stop:            args.Stop,
 			Directory:       finalStateDir,
 			Verbose:         true,
 			PreservesInodes: preservesInodes,
 			ActionScript:    script,
 			GhostLimit:      ghostLimit,
 		}
-		if args.preDumpDir != "" {
-			opts.PredumpDir = fmt.Sprintf("../%s", args.preDumpDir)
+		if args.PreDumpDir != "" {
+			opts.PredumpDir = fmt.Sprintf("../%s", args.PreDumpDir)
 		}
 
 		if !c.IsRunning() {
 			// otherwise the migration will needlessly fail
-			args.stop = false
+			args.Stop = false
 		}
 
-		migrateErr = c.c.Migrate(args.cmd, opts)
+		migrateErr = c.c.Migrate(args.Cmd, opts)
 	}
 
-	collectErr := collectCRIULogFile(c, finalStateDir, args.function, prettyCmd)
+	collectErr := collectCRIULogFile(c, finalStateDir, args.Function, prettyCmd)
 	if collectErr != nil {
 		logger.Error("Error collecting checkpoint log file", log.Ctx{"err": collectErr})
 	}
@@ -4920,7 +4929,7 @@ func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 		log, err2 := getCRIULogErrors(finalStateDir, prettyCmd)
 		if err2 == nil {
 			logger.Info("Failed migrating container", ctxMap)
-			migrateErr = fmt.Errorf("%s %s failed\n%s", args.function, prettyCmd, log)
+			migrateErr = fmt.Errorf("%s %s failed\n%s", args.Function, prettyCmd, log)
 		}
 
 		return migrateErr

From 00f2672161a3f14783cd63e66cb896fafb64999e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:55:32 +0000
Subject: [PATCH 20/62] lxd/instance/drivers/driver/lxc: Adds RegisterDevices
 function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index be5c29f8bc..dae1574968 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -1288,6 +1288,29 @@ func (c *lxc) runHooks(hooks []func() error) error {
 	return nil
 }
 
+// RegisterDevices calls the Register() function on all of the instance's devices.
+func (c *LXC) RegisterDevices() {
+	devices := c.ExpandedDevices()
+	for _, dev := range devices.Sorted() {
+		d, _, err := c.deviceLoad(dev.Name, dev.Config)
+		if err == device.ErrUnsupportedDevType {
+			continue
+		}
+
+		if err != nil {
+			logger.Error("Failed to load device to register", log.Ctx{"err": err, "instance": c.Name(), "device": dev.Name})
+			continue
+		}
+
+		// Check whether device wants to register for any events.
+		err = d.Register()
+		if err != nil {
+			logger.Error("Failed to register device", log.Ctx{"err": err, "instance": c.Name(), "device": dev.Name})
+			continue
+		}
+	}
+}
+
 // deviceLoad instantiates and validates a new device and returns it along with enriched config.
 func (c *lxc) deviceLoad(deviceName string, rawConfig deviceConfig.Device) (device.Device, deviceConfig.Device, error) {
 	var configCopy deviceConfig.Device

From 83b4f27dbd3531457236d7b086da44233f25cb2d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:56:08 +0000
Subject: [PATCH 21/62] lxd/instance/drivers/driver/lxc: Moves storage util
 functions and updates usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 58 +++---------------------------
 1 file changed, 4 insertions(+), 54 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index dae1574968..8a587921bb 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -1857,56 +1857,6 @@ func (c *lxc) expandDevices(profiles []api.Profile) error {
 	return nil
 }
 
-func shiftZfsSkipper(dir string, absPath string, fi os.FileInfo) bool {
-	strippedPath := absPath
-	if dir != "" {
-		strippedPath = absPath[len(dir):]
-	}
-
-	if fi.IsDir() && strippedPath == "/.zfs/snapshot" {
-		return true
-	}
-
-	return false
-}
-
-func shiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet, shift bool) error {
-	var err error
-	roSubvols := []string{}
-	subvols, _ := btrfsSubVolumesGet(path)
-	sort.Sort(sort.StringSlice(subvols))
-	for _, subvol := range subvols {
-		subvol = filepath.Join(path, subvol)
-
-		if !btrfsSubVolumeIsRo(subvol) {
-			continue
-		}
-
-		roSubvols = append(roSubvols, subvol)
-		btrfsSubVolumeMakeRw(subvol)
-	}
-
-	if shift {
-		err = diskIdmap.ShiftRootfs(path, nil)
-	} else {
-		err = diskIdmap.UnshiftRootfs(path, nil)
-	}
-
-	for _, subvol := range roSubvols {
-		btrfsSubVolumeMakeRo(subvol)
-	}
-
-	return err
-}
-
-func ShiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet) error {
-	return shiftBtrfsRootfs(path, diskIdmap, true)
-}
-
-func UnshiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet) error {
-	return shiftBtrfsRootfs(path, diskIdmap, false)
-}
-
 // Start functions
 func (c *lxc) startCommon() (string, []func() error, error) {
 	var ourStart bool
@@ -1966,9 +1916,9 @@ func (c *lxc) startCommon() (string, []func() error, error) {
 
 		if diskIdmap != nil {
 			if storageType == "zfs" {
-				err = diskIdmap.UnshiftRootfs(c.RootfsPath(), shiftZfsSkipper)
+				err = diskIdmap.UnshiftRootfs(c.RootfsPath(), storageDrivers.ShiftZFSSkipper)
 			} else if storageType == "btrfs" {
-				err = UnshiftBtrfsRootfs(c.RootfsPath(), diskIdmap)
+				err = storageDrivers.UnshiftBtrfsRootfs(c.RootfsPath(), diskIdmap)
 			} else {
 				err = diskIdmap.UnshiftRootfs(c.RootfsPath(), nil)
 			}
@@ -1982,9 +1932,9 @@ func (c *lxc) startCommon() (string, []func() error, error) {
 
 		if nextIdmap != nil && !c.state.OS.Shiftfs {
 			if storageType == "zfs" {
-				err = nextIdmap.ShiftRootfs(c.RootfsPath(), shiftZfsSkipper)
+				err = nextIdmap.ShiftRootfs(c.RootfsPath(), storageDrivers.ShiftZFSSkipper)
 			} else if storageType == "btrfs" {
-				err = ShiftBtrfsRootfs(c.RootfsPath(), nextIdmap)
+				err = storageDrivers.ShiftBtrfsRootfs(c.RootfsPath(), nextIdmap)
 			} else {
 				err = nextIdmap.ShiftRootfs(c.RootfsPath(), nil)
 			}

From e0c42cd5fb4b71bcac4de8dc8330650f128d87fd Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:56:26 +0000
Subject: [PATCH 22/62] lxd/instance/drivers/driver/lxc: SetupSharedMounts
 usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 8a587921bb..d55556bc87 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -2251,7 +2251,7 @@ func (c *lxc) Start(stateful bool) error {
 	}
 	defer op.Done(nil)
 
-	err = setupSharedMounts()
+	err = SetupSharedMounts()
 	if err != nil {
 		return fmt.Errorf("Daemon failed to setup shared mounts base: %s.\nDoes security.nesting need to be turned on?", err)
 	}

From c708c093e396b5b37eb15c98327bb77a66096b21 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:56:47 +0000
Subject: [PATCH 23/62] lxd/instance/drivers/driver/lxc: Adds SaveConfigFile
 function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index d55556bc87..5bbede9f30 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -6774,3 +6774,21 @@ func (c *lxc) UpdateBackupFile() error {
 
 	return pool.UpdateInstanceBackupFile(c, nil)
 }
+
+// SaveConfigFile generates the LXC config file on disk.
+func (c *LXC) SaveConfigFile() error {
+	err := c.initLXC(true)
+	if err != nil {
+		return errors.Wrapf(err, "Failed to generate LXC config")
+	}
+
+	// Generate the LXC config.
+	configPath := filepath.Join(c.LogPath(), "lxc.conf")
+	err = c.c.SaveConfigFile(configPath)
+	if err != nil {
+		os.Remove(configPath)
+		return fmt.Errorf("Failed to save LXC config to file %q", configPath, err)
+	}
+
+	return nil
+}

From 1d586af50a821e0bb0e73ce44d38ec3927db74c0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:59:56 +0000
Subject: [PATCH 24/62] lxd/instance/drivers/driver/lxc/cmd: Renames
 ContainerLXCCmd to lxcCmd

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc_cmd.go | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc_cmd.go b/lxd/instance/drivers/driver_lxc_cmd.go
index ea9543022a..7d80898e47 100644
--- a/lxd/instance/drivers/driver_lxc_cmd.go
+++ b/lxd/instance/drivers/driver_lxc_cmd.go
@@ -1,4 +1,4 @@
-package main
+package drivers
 
 import (
 	"os/exec"
@@ -10,19 +10,19 @@ import (
 	"github.com/lxc/lxd/shared/logger"
 )
 
-// ContainerLXCCmd represents a running command for an LXC container.
-type ContainerLXCCmd struct {
+// lxcCmd represents a running command for an LXC container.
+type lxcCmd struct {
 	attachedChildPid int
 	cmd              *exec.Cmd
 }
 
 // PID returns the attached child's process ID.
-func (c *ContainerLXCCmd) PID() int {
+func (c *lxcCmd) PID() int {
 	return c.attachedChildPid
 }
 
 // Signal sends a signal to the command.
-func (c *ContainerLXCCmd) Signal(sig unix.Signal) error {
+func (c *lxcCmd) Signal(sig unix.Signal) error {
 	err := unix.Kill(c.attachedChildPid, sig)
 	if err != nil {
 		return err
@@ -33,7 +33,7 @@ func (c *ContainerLXCCmd) Signal(sig unix.Signal) error {
 }
 
 // Wait for the command to end and returns its exit code and any error.
-func (c *ContainerLXCCmd) Wait() (int, error) {
+func (c *lxcCmd) Wait() (int, error) {
 	err := c.cmd.Wait()
 	if err != nil {
 		exitErr, ok := err.(*exec.ExitError)
@@ -56,7 +56,7 @@ func (c *ContainerLXCCmd) Wait() (int, error) {
 }
 
 // WindowResize resizes the running command's window.
-func (c *ContainerLXCCmd) WindowResize(fd, winchWidth, winchHeight int) error {
+func (c *lxcCmd) WindowResize(fd, winchWidth, winchHeight int) error {
 	err := shared.SetSize(fd, winchWidth, winchHeight)
 	if err != nil {
 		return err

From cd9e57ad691d08e69ed9b71fd4dd7623674b4ec1 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:00:17 +0000
Subject: [PATCH 25/62] lxd/instance/drivers/driver/qemu: Adds RegisterDevices
 as a no-op

Just satifies the Instance interface.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_qemu.go | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index a8f0e41006..ca97f5ccc6 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -970,6 +970,11 @@ func (vm *qemu) deviceVolatileSetFunc(devName string) func(save map[string]strin
 	}
 }
 
+// RegisterDevices is not used by VMs.
+func (vm *qemu) RegisterDevices() {
+	return
+}
+
 // deviceLoad instantiates and validates a new device and returns it along with enriched config.
 func (vm *qemu) deviceLoad(deviceName string, rawConfig deviceConfig.Device) (device.Device, deviceConfig.Device, error) {
 	var configCopy deviceConfig.Device

From 38be1c589a2939e00a3717537952e2a76adeade2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:00:52 +0000
Subject: [PATCH 26/62] lxd/instance/instance/interface: Adds RegisterDevices

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/instance_interface.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/instance/instance_interface.go b/lxd/instance/instance_interface.go
index 1018ddf780..8b2a532343 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -33,6 +33,7 @@ type Instance interface {
 	Start(stateful bool) error
 	Stop(stateful bool) error
 	Unfreeze() error
+	RegisterDevices()
 
 	IsPrivileged() bool
 

From 73c774db2b3a80cf684102b3adcab25eae9d5e13 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:01:06 +0000
Subject: [PATCH 27/62] lxd/instance/drivers/load: LXC loader functions renamed

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/load.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/instance/drivers/load.go b/lxd/instance/drivers/load.go
index 548112c7b2..b534365fd0 100644
--- a/lxd/instance/drivers/load.go
+++ b/lxd/instance/drivers/load.go
@@ -32,7 +32,7 @@ func load(s *state.State, args db.InstanceArgs, profiles []api.Profile) (instanc
 	var err error
 
 	if args.Type == instancetype.Container {
-		inst, err = LXCLoad(s, args, profiles)
+		inst, err = lxcLoad(s, args, profiles)
 	} else if args.Type == instancetype.VM {
 		inst, err = qemuLoad(s, args, profiles)
 	} else {
@@ -88,7 +88,7 @@ func validDevices(state *state.State, cluster *db.Cluster, instanceType instance
 
 func create(s *state.State, args db.InstanceArgs) (instance.Instance, error) {
 	if args.Type == instancetype.Container {
-		return LXCCreate(s, args)
+		return lxcCreate(s, args)
 	} else if args.Type == instancetype.VM {
 		return qemuCreate(s, args)
 	}

From 69a8b179431457f7af0108242df622554ec1438e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:10:44 +0000
Subject: [PATCH 28/62] lxd/migrate/container: instance.CriuMigrationArgs and
 instance.Container usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/migrate_container.go | 92 ++++++++++++++++++++--------------------
 1 file changed, 46 insertions(+), 46 deletions(-)

diff --git a/lxd/migrate_container.go b/lxd/migrate_container.go
index 70751a70a7..4488fb102c 100644
--- a/lxd/migrate_container.go
+++ b/lxd/migrate_container.go
@@ -129,22 +129,22 @@ func snapshotToProtobuf(c instance.Instance) *migration.Snapshot {
 func (s *migrationSourceWs) checkForPreDumpSupport() (bool, int) {
 	// Ask CRIU if this architecture/kernel/criu combination
 	// supports pre-copy (dirty memory tracking)
-	criuMigrationArgs := CriuMigrationArgs{
-		cmd:          lxc.MIGRATE_FEATURE_CHECK,
-		stateDir:     "",
-		function:     "feature-check",
-		stop:         false,
-		actionScript: false,
-		dumpDir:      "",
-		preDumpDir:   "",
-		features:     lxc.FEATURE_MEM_TRACK,
+	criuMigrationArgs := instance.CriuMigrationArgs{
+		Cmd:          lxc.MIGRATE_FEATURE_CHECK,
+		StateDir:     "",
+		Function:     "feature-check",
+		Stop:         false,
+		ActionScript: false,
+		DumpDir:      "",
+		PreDumpDir:   "",
+		Features:     lxc.FEATURE_MEM_TRACK,
 	}
 
 	if s.instance.Type() != instancetype.Container {
 		return false, 0
 	}
 
-	c := s.instance.(*containerLXC)
+	c := s.instance.(instance.Container)
 	err := c.Migrate(&criuMigrationArgs)
 
 	if err != nil {
@@ -241,14 +241,14 @@ type preDumpLoopArgs struct {
 // of memory pages transferred by pre-dumping has been reached.
 func (s *migrationSourceWs) preDumpLoop(args *preDumpLoopArgs) (bool, error) {
 	// Do a CRIU pre-dump
-	criuMigrationArgs := CriuMigrationArgs{
-		cmd:          lxc.MIGRATE_PRE_DUMP,
-		stop:         false,
-		actionScript: false,
-		preDumpDir:   args.preDumpDir,
-		dumpDir:      args.dumpDir,
-		stateDir:     args.checkpointDir,
-		function:     "migration",
+	criuMigrationArgs := instance.CriuMigrationArgs{
+		Cmd:          lxc.MIGRATE_PRE_DUMP,
+		Stop:         false,
+		ActionScript: false,
+		PreDumpDir:   args.preDumpDir,
+		DumpDir:      args.dumpDir,
+		StateDir:     args.checkpointDir,
+		Function:     "migration",
 	}
 
 	logger.Debugf("Doing another pre-dump in %s", args.preDumpDir)
@@ -259,7 +259,7 @@ func (s *migrationSourceWs) preDumpLoop(args *preDumpLoopArgs) (bool, error) {
 		return false, fmt.Errorf("Instance is not container type")
 	}
 
-	c := s.instance.(*containerLXC)
+	c := s.instance.(instance.Container)
 	err := c.Migrate(&criuMigrationArgs)
 	if err != nil {
 		return final, err
@@ -337,7 +337,7 @@ func (s *migrationSourceWs) Do(state *state.State, migrateOp *operations.Operati
 		return fmt.Errorf("Instance is not container type")
 	}
 
-	ct := s.instance.(*containerLXC)
+	ct := s.instance.(instance.Container)
 
 	var offerHeader migration.MigrationHeader
 	var poolMigrationTypes []migration.Type
@@ -609,14 +609,14 @@ func (s *migrationSourceWs) Do(state *state.State, migrateOp *operations.Operati
 			}
 
 			go func() {
-				criuMigrationArgs := CriuMigrationArgs{
-					cmd:          lxc.MIGRATE_DUMP,
-					stop:         true,
-					actionScript: true,
-					preDumpDir:   preDumpDir,
-					dumpDir:      "final",
-					stateDir:     checkpointDir,
-					function:     "migration",
+				criuMigrationArgs := instance.CriuMigrationArgs{
+					Cmd:          lxc.MIGRATE_DUMP,
+					Stop:         true,
+					ActionScript: true,
+					PreDumpDir:   preDumpDir,
+					DumpDir:      "final",
+					StateDir:     checkpointDir,
+					Function:     "migration",
 				}
 
 				// Do the final CRIU dump. This is needs no special handling if
@@ -636,14 +636,14 @@ func (s *migrationSourceWs) Do(state *state.State, migrateOp *operations.Operati
 		} else {
 			logger.Debugf("The version of liblxc is older than 2.0.4 and the live migration will probably fail")
 			defer os.RemoveAll(checkpointDir)
-			criuMigrationArgs := CriuMigrationArgs{
-				cmd:          lxc.MIGRATE_DUMP,
-				stateDir:     checkpointDir,
-				function:     "migration",
-				stop:         true,
-				actionScript: false,
-				dumpDir:      "final",
-				preDumpDir:   "",
+			criuMigrationArgs := instance.CriuMigrationArgs{
+				Cmd:          lxc.MIGRATE_DUMP,
+				StateDir:     checkpointDir,
+				Function:     "migration",
+				Stop:         true,
+				ActionScript: false,
+				DumpDir:      "final",
+				PreDumpDir:   "",
 			}
 
 			err = ct.Migrate(&criuMigrationArgs)
@@ -1044,7 +1044,7 @@ func (c *migrationSink) Do(state *state.State, migrateOp *operations.Operation)
 			// stream, then at the end we need to record that map as last_state so that
 			// LXD can shift on startup if needed.
 			if c.src.instance.Type() == instancetype.Container {
-				ct := c.src.instance.(*containerLXC)
+				ct := c.src.instance.(instance.Container)
 				err = resetContainerDiskIdmap(ct, srcIdmap)
 				if err != nil {
 					fsTransfer <- err
@@ -1122,20 +1122,20 @@ func (c *migrationSink) Do(state *state.State, migrateOp *operations.Operation)
 		}
 
 		if live {
-			criuMigrationArgs := CriuMigrationArgs{
-				cmd:          lxc.MIGRATE_RESTORE,
-				stateDir:     imagesDir,
-				function:     "migration",
-				stop:         false,
-				actionScript: false,
-				dumpDir:      "final",
-				preDumpDir:   "",
+			criuMigrationArgs := instance.CriuMigrationArgs{
+				Cmd:          lxc.MIGRATE_RESTORE,
+				StateDir:     imagesDir,
+				Function:     "migration",
+				Stop:         false,
+				ActionScript: false,
+				DumpDir:      "final",
+				PreDumpDir:   "",
 			}
 
 			// Currently we only do a single CRIU pre-dump so we can hardcode "final"
 			// here since we know that "final" is the folder for CRIU's final dump.
 			if c.src.instance.Type() == instancetype.Container {
-				ct := c.src.instance.(*containerLXC)
+				ct := c.src.instance.(instance.Container)
 				err = ct.Migrate(&criuMigrationArgs)
 				if err != nil {
 					restore <- err

From dc0b655dfd071d07226752dea58b3ff27b9f5108 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:11:53 +0000
Subject: [PATCH 29/62] lxd/patches: Updates patchContainerConfigRegen to use
 LXC.SaveConfigFile()

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/patches.go | 22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/lxd/patches.go b/lxd/patches.go
index bd13a029eb..e160fe29e2 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -19,6 +19,7 @@ import (
 	"github.com/lxc/lxd/lxd/db/query"
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
 	"github.com/lxc/lxd/lxd/instance"
+	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/rsync"
 	driver "github.com/lxc/lxd/lxd/storage"
 	storagePools "github.com/lxc/lxd/lxd/storage"
@@ -2068,34 +2069,23 @@ func patchContainerConfigRegen(name string, d *Daemon) error {
 
 	for _, ct := range cts {
 		// Load the container from the database.
-		c, err := instance.LoadByProjectAndName(d.State(), "default", ct)
+		inst, err := instance.LoadByProjectAndName(d.State(), "default", ct)
 		if err != nil {
 			logger.Errorf("Failed to open container '%s': %v", ct, err)
 			continue
 		}
 
-		if !c.IsRunning() {
-			continue
-		}
-
-		lxcCt, ok := c.(*containerLXC)
-		if !ok {
+		if inst.Type() != instancetype.Container {
 			continue
 		}
 
-		err = lxcCt.initLXC(true)
-		if err != nil {
-			logger.Errorf("Failed to generate LXC config for '%s': %v", ct, err)
+		if !inst.IsRunning() {
 			continue
 		}
 
-		// Generate the LXC config
-		configPath := filepath.Join(lxcCt.LogPath(), "lxc.conf")
-		err = lxcCt.c.SaveConfigFile(configPath)
+		err = inst.SaveConfigFile()
 		if err != nil {
-			os.Remove(configPath)
-			logger.Errorf("Failed to save LXC config for '%s': %v", ct, err)
-			continue
+			logger.Errorf("Failed to save LXC config for %q: %v", inst.Name(), err)
 		}
 	}
 

From 14cbd0476623179b8246e14cfb13c47d4f5ba44c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:12:17 +0000
Subject: [PATCH 30/62] lxd/patches: BTRFS storage functions usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/patches.go | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lxd/patches.go b/lxd/patches.go
index e160fe29e2..b657bdd859 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -3320,17 +3320,17 @@ func patchStorageApiRenameContainerSnapshotsDir(name string, d *Daemon) error {
 				// Disable the read-only properties
 				if hasBtrfs {
 					path := snapshotsDir.Name()
-					subvols, _ := btrfsSubVolumesGet(path)
+					subvols, _ := storageDrivers.BTRFSSubVolumesGet(path)
 					for _, subvol := range subvols {
 						subvol = filepath.Join(path, subvol)
 						newSubvol := filepath.Join(shared.VarPath("storage-pools", poolName, "containers-snapshots", entry), subvol)
 
-						if !btrfsSubVolumeIsRo(subvol) {
+						if !storageDrivers.BTRFSSubVolumeIsRo(subvol) {
 							continue
 						}
 
-						btrfsSubVolumeMakeRw(subvol)
-						defer btrfsSubVolumeMakeRo(newSubvol)
+						storageDrivers.BTRFSSubVolumeMakeRw(subvol)
+						defer storageDrivers.BTRFSSubVolumeMakeRo(newSubvol)
 					}
 				}
 

From 07a6e4c643c38fff10853ce579530ab5ed75d4f3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:12:47 +0000
Subject: [PATCH 31/62] lxd/patches/utils: storageDrivers.BTRFSSubVolumesGet
 and removes unused functions

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/patches_utils.go | 74 ++------------------------------------------
 1 file changed, 2 insertions(+), 72 deletions(-)

diff --git a/lxd/patches_utils.go b/lxd/patches_utils.go
index c58f4b2007..41182c8016 100644
--- a/lxd/patches_utils.go
+++ b/lxd/patches_utils.go
@@ -11,10 +11,9 @@ import (
 	"strings"
 	"syscall"
 
-	"golang.org/x/sys/unix"
-
 	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
+	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/units"
 )
@@ -102,7 +101,7 @@ func btrfsSubVolumeDelete(subvol string) error {
 
 func btrfsSubVolumesDelete(subvol string) error {
 	// Delete subsubvols.
-	subsubvols, err := btrfsSubVolumesGet(subvol)
+	subsubvols, err := storageDrivers.BTRFSSubVolumesGet(subvol)
 	if err != nil {
 		return err
 	}
@@ -155,75 +154,6 @@ func btrfsSnapshot(s *state.State, source string, dest string, readonly bool) er
 	return err
 }
 
-func btrfsIsSubVolume(subvolPath string) bool {
-	fs := unix.Stat_t{}
-	err := unix.Lstat(subvolPath, &fs)
-	if err != nil {
-		return false
-	}
-
-	// Check if BTRFS_FIRST_FREE_OBJECTID
-	if fs.Ino != 256 {
-		return false
-	}
-
-	return true
-}
-
-func btrfsSubVolumeIsRo(path string) bool {
-	output, err := shared.RunCommand("btrfs", "property", "get", "-ts", path)
-	if err != nil {
-		return false
-	}
-
-	return strings.HasPrefix(string(output), "ro=true")
-}
-
-func btrfsSubVolumeMakeRo(path string) error {
-	_, err := shared.RunCommand("btrfs", "property", "set", "-ts", path, "ro", "true")
-	return err
-}
-
-func btrfsSubVolumeMakeRw(path string) error {
-	_, err := shared.RunCommand("btrfs", "property", "set", "-ts", path, "ro", "false")
-	return err
-}
-
-func btrfsSubVolumesGet(path string) ([]string, error) {
-	result := []string{}
-
-	if !strings.HasSuffix(path, "/") {
-		path = path + "/"
-	}
-
-	// Unprivileged users can't get to fs internals
-	filepath.Walk(path, func(fpath string, fi os.FileInfo, err error) error {
-		// Skip walk errors
-		if err != nil {
-			return nil
-		}
-
-		// Ignore the base path
-		if strings.TrimRight(fpath, "/") == strings.TrimRight(path, "/") {
-			return nil
-		}
-
-		// Subvolumes can only be directories
-		if !fi.IsDir() {
-			return nil
-		}
-
-		// Check if a btrfs subvolume
-		if btrfsIsSubVolume(fpath) {
-			result = append(result, strings.TrimPrefix(fpath, path))
-		}
-
-		return nil
-	})
-
-	return result, nil
-}
-
 // For 'lvm' storage backend.
 func lvmLVRename(vgName string, oldName string, newName string) error {
 	_, err := shared.TryRunCommand("lvrename", vgName, oldName, newName)

From 09b78b6037f11297c31813864e46e0095a95980f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:13:35 +0000
Subject: [PATCH 32/62] lxd/storage: instance.Container usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage.go | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lxd/storage.go b/lxd/storage.go
index e0c848e8ac..e25b5122fe 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -46,7 +46,7 @@ func readStoragePoolDriversCache() map[string]string {
 	return drivers.(map[string]string)
 }
 
-func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName string, volumeType int, c *containerLXC) error {
+func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName string, volumeType int, c instance.Container) error {
 	// Load the DB records
 	poolID, pool, err := s.Cluster.StoragePoolGet(poolName)
 	if err != nil {
@@ -121,7 +121,7 @@ func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName
 						continue
 					}
 
-					ct := instt.(*containerLXC)
+					ct := instt.(instance.Container)
 
 					var ctNextIdmap *idmap.IdmapSet
 					if ct.IsRunning() {
@@ -206,7 +206,7 @@ func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName
 	return nil
 }
 
-func resetContainerDiskIdmap(container *containerLXC, srcIdmap *idmap.IdmapSet) error {
+func resetContainerDiskIdmap(container instance.Container, srcIdmap *idmap.IdmapSet) error {
 	dstIdmap, err := container.DiskIdmap()
 	if err != nil {
 		return err
@@ -332,7 +332,7 @@ func storagePoolDriversCacheUpdate(s *state.State) {
 // storageVolumeMount initialises a new storage interface and checks the pool and volume are
 // mounted. If they are not then they are mounted.
 func storageVolumeMount(state *state.State, poolName string, volumeName string, volumeTypeName string, inst instance.Instance) error {
-	c, ok := inst.(*containerLXC)
+	c, ok := inst.(instance.Container)
 	if !ok {
 		return fmt.Errorf("Received non-LXC container instance")
 	}

From dd911c7db8051c3b5a422fbcf3edf0ec864ba3f3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:14:02 +0000
Subject: [PATCH 33/62] lxd/storage: storageDrivers util functions usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lxd/storage.go b/lxd/storage.go
index e25b5122fe..c4f1b8ba37 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -69,7 +69,7 @@ func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName
 	// Get the on-disk idmap for the volume
 	var lastIdmap *idmap.IdmapSet
 	if poolVolumePut.Config["volatile.idmap.last"] != "" {
-		lastIdmap, err = idmapsetFromString(poolVolumePut.Config["volatile.idmap.last"])
+		lastIdmap, err = storageDrivers.IDMapsetFromString(poolVolumePut.Config["volatile.idmap.last"])
 		if err != nil {
 			logger.Errorf("Failed to unmarshal last idmapping: %s", poolVolumePut.Config["volatile.idmap.last"])
 			return err
@@ -152,7 +152,7 @@ func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName
 			var err error
 
 			if pool.Driver == "zfs" {
-				err = lastIdmap.UnshiftRootfs(remapPath, shiftZfsSkipper)
+				err = lastIdmap.UnshiftRootfs(remapPath, storageDrivers.ShiftZFSSkipper)
 			} else {
 				err = lastIdmap.UnshiftRootfs(remapPath, nil)
 			}
@@ -170,7 +170,7 @@ func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName
 			var err error
 
 			if pool.Driver == "zfs" {
-				err = nextIdmap.ShiftRootfs(remapPath, shiftZfsSkipper)
+				err = nextIdmap.ShiftRootfs(remapPath, storageDrivers.ShiftZFSSkipper)
 			} else {
 				err = nextIdmap.ShiftRootfs(remapPath, nil)
 			}

From 8913bcaabedef3fb9e7e9fed17d7566f570788f0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 18:14:21 +0000
Subject: [PATCH 34/62] lxd/storage/drivers/utils: Adds util functions moved
 from main pkg

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/drivers/utils.go | 140 +++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index cae780a036..66b85d81f5 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -1,11 +1,13 @@
 package drivers
 
 import (
+	"encoding/json"
 	"fmt"
 	"io"
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"sort"
 	"strings"
 	"time"
 
@@ -14,6 +16,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/shared"
+	"github.com/lxc/lxd/shared/idmap"
 	"github.com/lxc/lxd/shared/units"
 )
 
@@ -581,3 +584,140 @@ func copyDevice(inputPath, outputPath string) error {
 func loopFilePath(poolName string) string {
 	return filepath.Join(shared.VarPath("disks"), fmt.Sprintf("%s.img", poolName))
 }
+
+func ShiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet) error {
+	return shiftBtrfsRootfs(path, diskIdmap, true)
+}
+
+func UnshiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet) error {
+	return shiftBtrfsRootfs(path, diskIdmap, false)
+}
+
+func shiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet, shift bool) error {
+	var err error
+	roSubvols := []string{}
+	subvols, _ := BTRFSSubVolumesGet(path)
+	sort.Sort(sort.StringSlice(subvols))
+	for _, subvol := range subvols {
+		subvol = filepath.Join(path, subvol)
+
+		if !BTRFSSubVolumeIsRo(subvol) {
+			continue
+		}
+
+		roSubvols = append(roSubvols, subvol)
+		BTRFSSubVolumeMakeRw(subvol)
+	}
+
+	if shift {
+		err = diskIdmap.ShiftRootfs(path, nil)
+	} else {
+		err = diskIdmap.UnshiftRootfs(path, nil)
+	}
+
+	for _, subvol := range roSubvols {
+		BTRFSSubVolumeMakeRo(subvol)
+	}
+
+	return err
+}
+
+// BTRFSSubVolumesGet gets subvolumes.
+func BTRFSSubVolumesGet(path string) ([]string, error) {
+	result := []string{}
+
+	if !strings.HasSuffix(path, "/") {
+		path = path + "/"
+	}
+
+	// Unprivileged users can't get to fs internals
+	filepath.Walk(path, func(fpath string, fi os.FileInfo, err error) error {
+		// Skip walk errors
+		if err != nil {
+			return nil
+		}
+
+		// Ignore the base path
+		if strings.TrimRight(fpath, "/") == strings.TrimRight(path, "/") {
+			return nil
+		}
+
+		// Subvolumes can only be directories
+		if !fi.IsDir() {
+			return nil
+		}
+
+		// Check if a btrfs subvolume
+		if btrfsIsSubVolume(fpath) {
+			result = append(result, strings.TrimPrefix(fpath, path))
+		}
+
+		return nil
+	})
+
+	return result, nil
+}
+
+func btrfsIsSubVolume(subvolPath string) bool {
+	fs := unix.Stat_t{}
+	err := unix.Lstat(subvolPath, &fs)
+	if err != nil {
+		return false
+	}
+
+	// Check if BTRFS_FIRST_FREE_OBJECTID
+	if fs.Ino != 256 {
+		return false
+	}
+
+	return true
+}
+
+// BTRFSSubVolumeIsRo returns if subvolume is read only.
+func BTRFSSubVolumeIsRo(path string) bool {
+	output, err := shared.RunCommand("btrfs", "property", "get", "-ts", path)
+	if err != nil {
+		return false
+	}
+
+	return strings.HasPrefix(string(output), "ro=true")
+}
+
+// BTRFSSubVolumeMakeRo makes a subvolume read only.
+func BTRFSSubVolumeMakeRo(path string) error {
+	_, err := shared.RunCommand("btrfs", "property", "set", "-ts", path, "ro", "true")
+	return err
+}
+
+// BTRFSSubVolumeMakeRw makes a sub volume read/write.
+func BTRFSSubVolumeMakeRw(path string) error {
+	_, err := shared.RunCommand("btrfs", "property", "set", "-ts", path, "ro", "false")
+	return err
+}
+
+func IDMapsetFromString(idmapString string) (*idmap.IdmapSet, error) {
+	lastIdmap := new(idmap.IdmapSet)
+	err := json.Unmarshal([]byte(idmapString), &lastIdmap.Idmap)
+	if err != nil {
+		return nil, err
+	}
+
+	if len(lastIdmap.Idmap) == 0 {
+		return nil, nil
+	}
+
+	return lastIdmap, nil
+}
+
+func ShiftZFSSkipper(dir string, absPath string, fi os.FileInfo) bool {
+	strippedPath := absPath
+	if dir != "" {
+		strippedPath = absPath[len(dir):]
+	}
+
+	if fi.IsDir() && strippedPath == "/.zfs/snapshot" {
+		return true
+	}
+
+	return false
+}

From 4ce1e5ba8db327b8bc5a705cd37a207f3cffb71f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:04:27 +0000
Subject: [PATCH 35/62] lxd/apparmor/apparmor: Removes dependency on
 c.DaemonState()

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/apparmor/apparmor.go | 32 ++++++++++++--------------------
 1 file changed, 12 insertions(+), 20 deletions(-)

diff --git a/lxd/apparmor/apparmor.go b/lxd/apparmor/apparmor.go
index e7119d3cc1..54533e325f 100644
--- a/lxd/apparmor/apparmor.go
+++ b/lxd/apparmor/apparmor.go
@@ -503,7 +503,6 @@ type instance interface {
 	Project() string
 	Name() string
 	IsNesting() bool
-	DaemonState() *state.State
 	IsPrivileged() bool
 	ExpandedConfig() map[string]string
 }
@@ -544,7 +543,7 @@ func profileShort(c instance) string {
 
 // getProfileContent generates the apparmor profile template from the given container.
 // This includes the stock lxc includes as well as stuff from raw.apparmor.
-func getAAProfileContent(c instance) string {
+func getAAProfileContent(state *state.State, c instance) string {
 	profile := strings.TrimLeft(profileBase, "\n")
 
 	// Apply new features
@@ -566,7 +565,6 @@ func getAAProfileContent(c instance) string {
 		profile += "  mount fstype=cgroup2 -> /sys/fs/cgroup/**,\n"
 	}
 
-	state := c.DaemonState()
 	if state.OS.AppArmorStacking && !state.OS.AppArmorStacked {
 		profile += "\n  ### Feature: apparmor stacking\n"
 		profile += `  ### Configuration: apparmor profile loading (in namespace)
@@ -633,8 +631,7 @@ profile "%s" flags=(attach_disconnected,mediate_deleted) {
 `, ProfileFull(c), strings.Trim(profile, "\n"))
 }
 
-func runApparmor(command string, c instance) error {
-	state := c.DaemonState()
+func runApparmor(state *state.State, command string, c instance) error {
 	if !state.OS.AppArmorAvailable {
 		return nil
 	}
@@ -674,8 +671,7 @@ func getCacheDir() string {
 	return strings.TrimSpace(output)
 }
 
-func mkApparmorNamespace(c instance, namespace string) error {
-	state := c.DaemonState()
+func mkApparmorNamespace(state *state.State, c instance, namespace string) error {
 	if !state.OS.AppArmorStacking || state.OS.AppArmorStacked {
 		return nil
 	}
@@ -689,13 +685,12 @@ func mkApparmorNamespace(c instance, namespace string) error {
 }
 
 // LoadProfile ensures that the instances's policy is loaded into the kernel so the it can boot.
-func LoadProfile(c instance) error {
-	state := c.DaemonState()
+func LoadProfile(state *state.State, c instance) error {
 	if !state.OS.AppArmorAdmin {
 		return nil
 	}
 
-	if err := mkApparmorNamespace(c, Namespace(c)); err != nil {
+	if err := mkApparmorNamespace(state, c, Namespace(c)); err != nil {
 		return err
 	}
 
@@ -716,7 +711,7 @@ func LoadProfile(c instance) error {
 		return err
 	}
 
-	updated := getAAProfileContent(c)
+	updated := getAAProfileContent(state, c)
 
 	if string(content) != string(updated) {
 		if err := os.MkdirAll(path.Join(aaPath, "cache"), 0700); err != nil {
@@ -732,13 +727,12 @@ func LoadProfile(c instance) error {
 		}
 	}
 
-	return runApparmor(cmdLoad, c)
+	return runApparmor(state, cmdLoad, c)
 }
 
 // Destroy ensures that the instances's policy namespace is unloaded to free kernel memory.
 // This does not delete the policy from disk or cache.
-func Destroy(c instance) error {
-	state := c.DaemonState()
+func Destroy(state *state.State, c instance) error {
 	if !state.OS.AppArmorAdmin {
 		return nil
 	}
@@ -750,22 +744,20 @@ func Destroy(c instance) error {
 		}
 	}
 
-	return runApparmor(cmdUnload, c)
+	return runApparmor(state, cmdUnload, c)
 }
 
 // ParseProfile parses the profile without loading it into the kernel.
-func ParseProfile(c instance) error {
-	state := c.DaemonState()
+func ParseProfile(state *state.State, c instance) error {
 	if !state.OS.AppArmorAvailable {
 		return nil
 	}
 
-	return runApparmor(cmdParse, c)
+	return runApparmor(state, cmdParse, c)
 }
 
 // DeleteProfile removes the policy from cache/disk.
-func DeleteProfile(c instance) {
-	state := c.DaemonState()
+func DeleteProfile(state *state.State, c instance) {
 	if !state.OS.AppArmorAdmin {
 		return
 	}

From 81dcf594465cc9bb8cddd891aca037d8f9a8e77c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:05:00 +0000
Subject: [PATCH 36/62] lxd/container/snapshot: Removes dependency on
 sc.DaemonState()

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_snapshot.go | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lxd/container_snapshot.go b/lxd/container_snapshot.go
index 78b817b6dc..313f928bd5 100644
--- a/lxd/container_snapshot.go
+++ b/lxd/container_snapshot.go
@@ -16,6 +16,7 @@ import (
 	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/lxd/response"
+	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/lxd/util"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
@@ -220,7 +221,7 @@ func containerSnapshotHandler(d *Daemon, r *http.Request) response.Response {
 	case "POST":
 		return snapshotPost(d, r, inst, containerName)
 	case "DELETE":
-		return snapshotDelete(inst, snapshotName)
+		return snapshotDelete(d.State(), inst, snapshotName)
 	case "PUT":
 		return snapshotPut(d, r, inst, snapshotName)
 	default:
@@ -425,7 +426,7 @@ func snapshotPost(d *Daemon, r *http.Request, sc instance.Instance, containerNam
 	return operations.OperationResponse(op)
 }
 
-func snapshotDelete(sc instance.Instance, name string) response.Response {
+func snapshotDelete(s *state.State, sc instance.Instance, name string) response.Response {
 	remove := func(op *operations.Operation) error {
 		return sc.Delete()
 	}
@@ -433,7 +434,7 @@ func snapshotDelete(sc instance.Instance, name string) response.Response {
 	resources := map[string][]string{}
 	resources["containers"] = []string{sc.Name()}
 
-	op, err := operations.OperationCreate(sc.DaemonState(), sc.Project(), operations.OperationClassTask, db.OperationSnapshotDelete, resources, nil, remove, nil, nil)
+	op, err := operations.OperationCreate(s, sc.Project(), operations.OperationClassTask, db.OperationSnapshotDelete, resources, nil, remove, nil, nil)
 	if err != nil {
 		return response.InternalError(err)
 	}

From a714f6682f43db1e7555d0bc56edf80985f51e11 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:05:20 +0000
Subject: [PATCH 37/62] lxd/container/test: instanceDrivers.PrepareEqualTest
 usage to fix crash

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_test.go | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/lxd/container_test.go b/lxd/container_test.go
index e4677eec76..0a69b2f1a0 100644
--- a/lxd/container_test.go
+++ b/lxd/container_test.go
@@ -9,6 +9,7 @@ import (
 	"github.com/lxc/lxd/lxd/db"
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
 	"github.com/lxc/lxd/lxd/instance"
+	instanceDrivers "github.com/lxc/lxd/lxd/instance/drivers"
 	"github.com/lxc/lxd/lxd/instance/instancetype"
 	driver "github.com/lxc/lxd/lxd/storage"
 	"github.com/lxc/lxd/shared"
@@ -141,12 +142,7 @@ func (suite *containerTestSuite) TestContainer_LoadFromDB() {
 	_, err = c2.StorageStart()
 	suite.Req.Nil(err)
 
-	// When loading from DB, we won't have a full LXC config
-	c.(*instanceDrivers.LXC).c = nil
-	c.(*instanceDrivers.LXC).cConfig = false
-	c2.(*instanceDrivers.LXC).c = nil
-	c2.(*instanceDrivers.LXC).cConfig = false
-
+	instanceDrivers.PrepareEqualTest(c, c2)
 	suite.Exactly(
 		c,
 		c2,

From c1107ce2b46e6d536082655fc55e48c4f1f76c27 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:08:06 +0000
Subject: [PATCH 38/62] lxd/instance/drivers/driver/lxc: golint fixes

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 136 +++++++++++++++++++----------
 1 file changed, 92 insertions(+), 44 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 5bbede9f30..8366c937f7 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -461,6 +461,7 @@ type lxc struct {
 	expiryDate time.Time
 }
 
+// Type returns the instance type.
 func (c *lxc) Type() instancetype.Type {
 	return c.dbType
 }
@@ -1264,7 +1265,7 @@ func (c *lxc) initLXC(config bool) error {
 	return nil
 }
 
-func (c *LXC) devlxdEventSend(eventType string, eventMessage interface{}) error {
+func (c *lxc) devlxdEventSend(eventType string, eventMessage interface{}) error {
 	event := shared.Jmap{}
 	event["type"] = eventType
 	event["timestamp"] = time.Now()
@@ -1289,7 +1290,7 @@ func (c *lxc) runHooks(hooks []func() error) error {
 }
 
 // RegisterDevices calls the Register() function on all of the instance's devices.
-func (c *LXC) RegisterDevices() {
+func (c *lxc) RegisterDevices() {
 	devices := c.ExpandedDevices()
 	for _, dev := range devices.Sorted() {
 		d, _, err := c.deviceLoad(dev.Name, dev.Config)
@@ -2241,6 +2242,7 @@ func (c *lxc) detachInterfaceRename(netns string, ifName string, hostName string
 	return nil
 }
 
+// Start starts the instance.
 func (c *lxc) Start(stateful bool) error {
 	var ctxMap log.Ctx
 
@@ -2393,6 +2395,7 @@ func (c *lxc) Start(stateful bool) error {
 	return nil
 }
 
+// OnStart implements the start hook.
 func (c *lxc) OnStart() error {
 	// Make sure we can't call go-lxc functions by mistake
 	c.fromHook = true
@@ -2624,6 +2627,7 @@ func (c *lxc) Stop(stateful bool) error {
 	return nil
 }
 
+// Shutdown stops the instance.
 func (c *lxc) Shutdown(timeout time.Duration) error {
 	var ctxMap log.Ctx
 
@@ -2829,7 +2833,7 @@ func (c *lxc) cleanupDevices(netns string) {
 	}
 }
 
-// Freezer functions
+// Freeze functions.
 func (c *lxc) Freeze() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
@@ -2883,6 +2887,7 @@ func (c *lxc) Freeze() error {
 	return err
 }
 
+// Unfreeze unfreezes the instance.
 func (c *lxc) Unfreeze() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
@@ -2933,8 +2938,6 @@ func (c *lxc) Unfreeze() error {
 	return err
 }
 
-var LxcMonitorStateError = fmt.Errorf("Monitor is hung")
-
 // Get lxc container state, with 1 second timeout
 // If we don't get a reply, assume the lxc monitor is hung
 func (c *lxc) getLxcState() (liblxc.State, error) {
@@ -2958,10 +2961,11 @@ func (c *lxc) getLxcState() (liblxc.State, error) {
 	case state := <-monitor:
 		return state, nil
 	case <-time.After(5 * time.Second):
-		return liblxc.StateMap["FROZEN"], LxcMonitorStateError
+		return liblxc.StateMap["FROZEN"], fmt.Errorf("Monitor is hung")
 	}
 }
 
+// Render renders the state of the instance.
 func (c *lxc) Render() (interface{}, interface{}, error) {
 	// Ignore err as the arch string on error is correct (unknown)
 	architectureName, _ := osarch.ArchitectureName(c.architecture)
@@ -3021,6 +3025,7 @@ func (c *lxc) Render() (interface{}, interface{}, error) {
 	return &ct, etag, nil
 }
 
+// RenderFull renders the full state of the instance.
 func (c *lxc) RenderFull() (*api.InstanceFull, interface{}, error) {
 	if c.IsSnapshot() {
 		return nil, nil, fmt.Errorf("RenderFull only works with containers")
@@ -3079,6 +3084,7 @@ func (c *lxc) RenderFull() (*api.InstanceFull, interface{}, error) {
 	return &ct, etag, nil
 }
 
+// RenderState renders just the running state of the instance.
 func (c *lxc) RenderState() (*api.InstanceState, error) {
 	cState, err := c.getLxcState()
 	if err != nil {
@@ -3103,6 +3109,7 @@ func (c *lxc) RenderState() (*api.InstanceState, error) {
 	return &status, nil
 }
 
+// Snapshots returns the snapshots of the instance.
 func (c *lxc) Snapshots() ([]instance.Instance, error) {
 	var snaps []db.Instance
 
@@ -3138,6 +3145,7 @@ func (c *lxc) Snapshots() ([]instance.Instance, error) {
 	return instances, nil
 }
 
+// Backups returns the backups of the instance.
 func (c *lxc) Backups() ([]backup.Backup, error) {
 	// Get all the backups
 	backupNames, err := c.state.Cluster.ContainerGetBackups(c.project, c.name)
@@ -3348,6 +3356,7 @@ func (c *lxc) cleanup() {
 	os.RemoveAll(c.ShmountsPath())
 }
 
+// Delete deletes the instance.
 func (c *lxc) Delete() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
@@ -3462,6 +3471,7 @@ func (c *lxc) Delete() error {
 	return nil
 }
 
+// Rename renames the instance.
 func (c *lxc) Rename(newName string) error {
 	oldName := c.Name()
 	ctxMap := log.Ctx{
@@ -3608,6 +3618,7 @@ func (c *lxc) Rename(newName string) error {
 	return nil
 }
 
+// CGroupGet gets a cgroup value for the instance.
 func (c *lxc) CGroupGet(key string) (string, error) {
 	// Load the go-lxc struct
 	err := c.initLXC(false)
@@ -3624,6 +3635,7 @@ func (c *lxc) CGroupGet(key string) (string, error) {
 	return strings.Join(value, "\n"), nil
 }
 
+// CGroupSet sets a cgroup value for the instance.
 func (c *lxc) CGroupSet(key string, value string) error {
 	// Load the go-lxc struct
 	err := c.initLXC(false)
@@ -3644,6 +3656,7 @@ func (c *lxc) CGroupSet(key string, value string) error {
 	return nil
 }
 
+// VolatileSet sets volatile config.
 func (c *lxc) VolatileSet(changes map[string]string) error {
 	// Sanity check
 	for key := range changes {
@@ -3682,6 +3695,7 @@ func (c *lxc) VolatileSet(changes map[string]string) error {
 	return nil
 }
 
+// Update applies updated config.
 func (c *lxc) Update(args db.InstanceArgs, userRequested bool) error {
 	// Set sane defaults for unset keys
 	if args.Project == "" {
@@ -4460,6 +4474,7 @@ func (c *lxc) updateDevices(removeDevices deviceConfig.Devices, addDevices devic
 	return nil
 }
 
+// Export backs up the instance.
 func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
@@ -4707,6 +4722,7 @@ func getCRIULogErrors(imagesDir string, method string) (string, error) {
 	return strings.Join(ret, "\n"), nil
 }
 
+// Migrate migrates the instance to another node.
 func (c *lxc) Migrate(args *instance.CriuMigrationArgs) error {
 	ctxMap := log.Ctx{
 		"project":      c.project,
@@ -4944,18 +4960,18 @@ func (c *lxc) templateApplyNow(trigger string) error {
 		return errors.Wrapf(err, "Could not parse %s", fname)
 	}
 
-	// Find rootUid and rootGid
+	// Find rootUID and rootGID
 	idmapset, err := c.DiskIdmap()
 	if err != nil {
 		return errors.Wrap(err, "Failed to set ID map")
 	}
 
-	rootUid := int64(0)
-	rootGid := int64(0)
+	rootUID := int64(0)
+	rootGID := int64(0)
 
 	// Get the right uid and gid for the container
 	if idmapset != nil {
-		rootUid, rootGid = idmapset.ShiftIntoNs(0, 0)
+		rootUID, rootGID = idmapset.ShiftIntoNs(0, 0)
 	}
 
 	// Figure out the container architecture
@@ -5015,7 +5031,7 @@ func (c *lxc) templateApplyNow(trigger string) error {
 			}
 		} else {
 			// Create the directories leading to the file
-			shared.MkdirAllOwner(path.Dir(fullpath), 0755, int(rootUid), int(rootGid))
+			shared.MkdirAllOwner(path.Dir(fullpath), 0755, int(rootUID), int(rootGID))
 
 			// Create the file itself
 			w, err = os.Create(fullpath)
@@ -5024,7 +5040,7 @@ func (c *lxc) templateApplyNow(trigger string) error {
 			}
 
 			// Fix ownership and mode
-			w.Chown(int(rootUid), int(rootGid))
+			w.Chown(int(rootUID), int(rootGID))
 			w.Chmod(0644)
 		}
 		defer w.Close()
@@ -5066,6 +5082,7 @@ func (c *lxc) templateApplyNow(trigger string) error {
 	return nil
 }
 
+// FileExists returns whether file exists inside instance.
 func (c *lxc) FileExists(path string) error {
 	// Setup container storage if needed
 	var ourStart bool
@@ -5114,6 +5131,7 @@ func (c *lxc) FileExists(path string) error {
 	return nil
 }
 
+// FilePull gets a file from the instance.
 func (c *lxc) FilePull(srcpath string, dstpath string) (int64, int64, os.FileMode, string, []string, error) {
 	// Check for ongoing operations (that may involve shifting).
 	op := operationlock.Get(c.id)
@@ -5154,7 +5172,7 @@ func (c *lxc) FilePull(srcpath string, dstpath string) (int64, int64, os.FileMod
 	uid := int64(-1)
 	gid := int64(-1)
 	mode := -1
-	type_ := "unknown"
+	fileType := "unknown"
 	var dirEnts []string
 	var errStr string
 
@@ -5210,7 +5228,7 @@ func (c *lxc) FilePull(srcpath string, dstpath string) (int64, int64, os.FileMod
 		}
 
 		if strings.HasPrefix(line, "type: ") {
-			type_ = strings.TrimPrefix(line, "type: ")
+			fileType = strings.TrimPrefix(line, "type: ")
 			continue
 		}
 
@@ -5240,18 +5258,19 @@ func (c *lxc) FilePull(srcpath string, dstpath string) (int64, int64, os.FileMod
 		}
 	}
 
-	return uid, gid, os.FileMode(mode), type_, dirEnts, nil
+	return uid, gid, os.FileMode(mode), fileType, dirEnts, nil
 }
 
-func (c *lxc) FilePush(type_ string, srcpath string, dstpath string, uid int64, gid int64, mode int, write string) error {
+// FilePush sends a file into the instance.
+func (c *lxc) FilePush(fileType string, srcpath string, dstpath string, uid int64, gid int64, mode int, write string) error {
 	// Check for ongoing operations (that may involve shifting).
 	op := operationlock.Get(c.id)
 	if op != nil {
 		op.Wait()
 	}
 
-	var rootUid int64
-	var rootGid int64
+	var rootUID int64
+	var rootGID int64
 	var errStr string
 
 	// Map uid and gid if needed
@@ -5263,7 +5282,7 @@ func (c *lxc) FilePush(type_ string, srcpath string, dstpath string, uid int64,
 
 		if idmapset != nil {
 			uid, gid = idmapset.ShiftIntoNs(uid, gid)
-			rootUid, rootGid = idmapset.ShiftIntoNs(0, 0)
+			rootUID, rootGID = idmapset.ShiftIntoNs(0, 0)
 		}
 	}
 
@@ -5278,7 +5297,7 @@ func (c *lxc) FilePush(type_ string, srcpath string, dstpath string, uid int64,
 	}
 
 	defaultMode := 0640
-	if type_ == "directory" {
+	if fileType == "directory" {
 		defaultMode = 0750
 	}
 
@@ -5292,12 +5311,12 @@ func (c *lxc) FilePush(type_ string, srcpath string, dstpath string, uid int64,
 		fmt.Sprintf("%d", c.InitPID()),
 		srcpath,
 		dstpath,
-		type_,
+		fileType,
 		fmt.Sprintf("%d", uid),
 		fmt.Sprintf("%d", gid),
 		fmt.Sprintf("%d", mode),
-		fmt.Sprintf("%d", rootUid),
-		fmt.Sprintf("%d", rootGid),
+		fmt.Sprintf("%d", rootUID),
+		fmt.Sprintf("%d", rootGID),
 		fmt.Sprintf("%d", int(os.FileMode(defaultMode)&os.ModePerm)),
 		write,
 	)
@@ -5339,6 +5358,7 @@ func (c *lxc) FilePush(type_ string, srcpath string, dstpath string, uid int64,
 	return nil
 }
 
+// FileRemove removes a file inside the instance.
 func (c *lxc) FileRemove(path string) error {
 	var errStr string
 	var ourStart bool
@@ -5400,6 +5420,7 @@ func (c *lxc) FileRemove(path string) error {
 	return nil
 }
 
+// Console attaches to the instance console.
 func (c *lxc) Console() (*os.File, chan error, error) {
 	chDisconnect := make(chan error, 1)
 
@@ -5453,6 +5474,7 @@ func (c *lxc) Console() (*os.File, chan error, error) {
 	return master, chDisconnect, nil
 }
 
+// ConsoleLog returns console log.
 func (c *lxc) ConsoleLog(opts liblxc.ConsoleLogOptions) (string, error) {
 	msg, err := c.c.ConsoleLog(opts)
 	if err != nil {
@@ -5462,6 +5484,7 @@ func (c *lxc) ConsoleLog(opts liblxc.ConsoleLogOptions) (string, error) {
 	return string(msg), nil
 }
 
+// Exec executes a command inside the instance.
 func (c *lxc) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os.File, stderr *os.File) (instance.Cmd, error) {
 	// Prepare the environment
 	envSlice := []string{}
@@ -5975,6 +5998,7 @@ func (c *lxc) removeMount(mount string) error {
 	return nil
 }
 
+// InsertSeccompUnixDevice inserts a seccomp device.
 func (c *lxc) InsertSeccompUnixDevice(prefix string, m deviceConfig.Device, pid int) error {
 	if pid < 0 {
 		return fmt.Errorf("Invalid request PID specified")
@@ -6290,36 +6314,39 @@ func (c *lxc) setNetworkPriority() error {
 
 	// Check that we at least succeeded to set an entry
 	success := false
-	var last_error error
+	var lastError error
 	for _, netif := range netifs {
 		err = cg.SetNetIfPrio(fmt.Sprintf("%s %d", netif.Name, networkInt))
 		if err == nil {
 			success = true
 		} else {
-			last_error = err
+			lastError = err
 		}
 	}
 
 	if !success {
-		return fmt.Errorf("Failed to set network device priority: %s", last_error)
+		return fmt.Errorf("Failed to set network device priority: %s", lastError)
 	}
 
 	return nil
 }
 
-// Various state query functions
+// IsStateful returns is instance is stateful.
 func (c *lxc) IsStateful() bool {
 	return c.stateful
 }
 
+// IsEphemeral returns if instance is ephemeral.
 func (c *lxc) IsEphemeral() bool {
 	return c.ephemeral
 }
 
+// IsFrozen returns if instance is frozen.
 func (c *lxc) IsFrozen() bool {
 	return c.State() == "FROZEN"
 }
 
+// IsNesting returns if instance is nested.
 func (c *lxc) IsNesting() bool {
 	return shared.IsTrue(c.expandedConfig["security.nesting"])
 }
@@ -6337,43 +6364,53 @@ func (c *lxc) isCurrentlyPrivileged() bool {
 	return idmap == nil
 }
 
+// IsPrivileged returns if instance is privileged.
 func (c *lxc) IsPrivileged() bool {
 	return shared.IsTrue(c.expandedConfig["security.privileged"])
 }
 
+// IsRunning returns if instance is running.
 func (c *lxc) IsRunning() bool {
 	state := c.State()
 	return state != "BROKEN" && state != "STOPPED"
 }
 
+// IsSnapshot returns if instance is a snapshot.
 func (c *lxc) IsSnapshot() bool {
 	return c.snapshot
 }
 
-// Various property query functions
+// Architecture returns architecture of instance.
 func (c *lxc) Architecture() int {
 	return c.architecture
 }
 
+// CreationDate returns creation date of instance.
 func (c *lxc) CreationDate() time.Time {
 	return c.creationDate
 }
+
+// LastUsedDate returns last used date time of instance.
 func (c *lxc) LastUsedDate() time.Time {
 	return c.lastUsedDate
 }
+
+// ExpandedConfig returns expanded config.
 func (c *lxc) ExpandedConfig() map[string]string {
 	return c.expandedConfig
 }
 
+// ExpandedDevices returns expanded devices config.
 func (c *lxc) ExpandedDevices() deviceConfig.Devices {
 	return c.expandedDevices
 }
 
-// ID gets container's ID.
+// ID gets instances's ID.
 func (c *lxc) ID() int {
 	return c.id
 }
 
+// InitPID returns PID of init process.
 func (c *lxc) InitPID() int {
 	// Load the go-lxc struct
 	err := c.initLXC(false)
@@ -6384,14 +6421,17 @@ func (c *lxc) InitPID() int {
 	return c.c.InitPid()
 }
 
+// LocalConfig returns local config.
 func (c *lxc) LocalConfig() map[string]string {
 	return c.localConfig
 }
 
+// LocalDevices returns local device config.
 func (c *lxc) LocalDevices() deviceConfig.Devices {
 	return c.localDevices
 }
 
+// CurrentIdmap returns current IDMAP.
 func (c *lxc) CurrentIdmap() (*idmap.IdmapSet, error) {
 	jsonIdmap, ok := c.LocalConfig()["volatile.idmap.current"]
 	if !ok {
@@ -6401,6 +6441,7 @@ func (c *lxc) CurrentIdmap() (*idmap.IdmapSet, error) {
 	return storageDrivers.IDMapsetFromString(jsonIdmap)
 }
 
+// DiskIdmap returns DISK IDMAP.
 func (c *lxc) DiskIdmap() (*idmap.IdmapSet, error) {
 	jsonIdmap, ok := c.LocalConfig()["volatile.last_state.idmap"]
 	if !ok {
@@ -6410,6 +6451,7 @@ func (c *lxc) DiskIdmap() (*idmap.IdmapSet, error) {
 	return storageDrivers.IDMapsetFromString(jsonIdmap)
 }
 
+// NextIdmap returns next IDMAP.
 func (c *lxc) NextIdmap() (*idmap.IdmapSet, error) {
 	jsonIdmap, ok := c.LocalConfig()["volatile.idmap.next"]
 	if !ok {
@@ -6419,36 +6461,32 @@ func (c *lxc) NextIdmap() (*idmap.IdmapSet, error) {
 	return storageDrivers.IDMapsetFromString(jsonIdmap)
 }
 
-func (c *lxc) DaemonState() *state.State {
-	// FIXME: This function should go away, since the abstract container
-	//        interface should not be coupled with internal state details.
-	//        However this is not currently possible, because many
-	//        higher-level APIs use container variables as "implicit
-	//        handles" to database/OS state and then need a way to get a
-	//        reference to it.
-	return c.state
-}
-
+// Location returns instance location.
 func (c *lxc) Location() string {
 	return c.node
 }
 
+// Project returns instance project.
 func (c *lxc) Project() string {
 	return c.project
 }
 
+// Name returns instance name.
 func (c *lxc) Name() string {
 	return c.name
 }
 
+// Description returns instance description.
 func (c *lxc) Description() string {
 	return c.description
 }
 
+// Profiles returns instance profiles.
 func (c *lxc) Profiles() []string {
 	return c.profiles
 }
 
+// State returns instance state.
 func (c *lxc) State() string {
 	state, err := c.getLxcState()
 	if err != nil {
@@ -6457,42 +6495,50 @@ func (c *lxc) State() string {
 	return state.String()
 }
 
-// Various container paths
+// Path instance path.
 func (c *lxc) Path() string {
 	return storagePools.InstancePath(c.Type(), c.Project(), c.Name(), c.IsSnapshot())
 }
 
+// DevicesPath devices path.
 func (c *lxc) DevicesPath() string {
 	name := project.Prefix(c.Project(), c.Name())
 	return shared.VarPath("devices", name)
 }
 
+// ShmountsPath shared mounts path.
 func (c *lxc) ShmountsPath() string {
 	name := project.Prefix(c.Project(), c.Name())
 	return shared.VarPath("shmounts", name)
 }
 
+// LogPath log path.
 func (c *lxc) LogPath() string {
 	name := project.Prefix(c.Project(), c.Name())
 	return shared.LogPath(name)
 }
 
+// LogFilePath log file path.
 func (c *lxc) LogFilePath() string {
 	return filepath.Join(c.LogPath(), "lxc.log")
 }
 
+// ConsoleBufferLogPath console buffer log path.
 func (c *lxc) ConsoleBufferLogPath() string {
 	return filepath.Join(c.LogPath(), "console.log")
 }
 
+// RootfsPath root filesystem path.
 func (c *lxc) RootfsPath() string {
 	return filepath.Join(c.Path(), "rootfs")
 }
 
+// TemplatesPath templates path.
 func (c *lxc) TemplatesPath() string {
 	return filepath.Join(c.Path(), "templates")
 }
 
+// StatePath state path.
 func (c *lxc) StatePath() string {
 	/* FIXME: backwards compatibility: we used to use Join(RootfsPath(),
 	 * "state"), which was bad. Let's just check to see if that directory
@@ -6505,6 +6551,7 @@ func (c *lxc) StatePath() string {
 	return filepath.Join(c.Path(), "state")
 }
 
+// StoragePool storage pool name.
 func (c *lxc) StoragePool() (string, error) {
 	poolName, err := c.state.Cluster.InstancePool(c.Project(), c.Name())
 	if err != nil {
@@ -6514,11 +6561,12 @@ func (c *lxc) StoragePool() (string, error) {
 	return poolName, nil
 }
 
-// Progress tracking
+// SetOperation handles progress tracking.
 func (c *lxc) SetOperation(op *operations.Operation) {
 	c.op = op
 }
 
+// ExpiryDate sets expiry date.
 func (c *lxc) ExpiryDate() time.Time {
 	if c.IsSnapshot() {
 		return c.expiryDate
@@ -6544,7 +6592,7 @@ func (c *lxc) updateProgress(progress string) {
 	}
 }
 
-// Internal MAAS handling
+// Internal MAAS handling.
 func (c *lxc) maasInterfaces(devices map[string]map[string]string) ([]maas.ContainerInterface, error) {
 	interfaces := []maas.ContainerInterface{}
 	for k, m := range devices {
@@ -6776,7 +6824,7 @@ func (c *lxc) UpdateBackupFile() error {
 }
 
 // SaveConfigFile generates the LXC config file on disk.
-func (c *LXC) SaveConfigFile() error {
+func (c *lxc) SaveConfigFile() error {
 	err := c.initLXC(true)
 	if err != nil {
 		return errors.Wrapf(err, "Failed to generate LXC config")
@@ -6787,7 +6835,7 @@ func (c *LXC) SaveConfigFile() error {
 	err = c.c.SaveConfigFile(configPath)
 	if err != nil {
 		os.Remove(configPath)
-		return fmt.Errorf("Failed to save LXC config to file %q", configPath, err)
+		return errors.Wrapf(err, "Failed to save LXC config to file %q", configPath)
 	}
 
 	return nil

From dc73a833cc6ca37ca66051a07b1faead2ebaea8f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:08:40 +0000
Subject: [PATCH 39/62] lxd/instance/drivers/driver/lxc: Removes DaemonState
 function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_lxc.go | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 8366c937f7..67927f52d7 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -997,7 +997,7 @@ func (c *lxc) initLXC(config bool) error {
 
 		// Setup notification socket
 		// System requirement errors are handled during policy generation instead of here
-		ok, err := seccomp.InstanceNeedsIntercept(c)
+		ok, err := seccomp.InstanceNeedsIntercept(c.state, c)
 		if err == nil && ok {
 			err = lxcSetConfigItem(cc, "lxc.seccomp.notify.proxy", fmt.Sprintf("unix:%s", shared.VarPath("seccomp.socket")))
 			if err != nil {
@@ -1982,7 +1982,7 @@ func (c *lxc) startCommon() (string, []func() error, error) {
 	}
 
 	// Generate the Seccomp profile
-	if err := seccomp.CreateProfile(c); err != nil {
+	if err := seccomp.CreateProfile(c.state, c); err != nil {
 		return "", postStartHooks, err
 	}
 
@@ -2407,7 +2407,7 @@ func (c *lxc) OnStart() error {
 	}
 
 	// Load the container AppArmor profile
-	err = apparmor.LoadProfile(c)
+	err = apparmor.LoadProfile(c.state, c)
 	if err != nil {
 		if ourStart {
 			c.unmount()
@@ -2421,7 +2421,7 @@ func (c *lxc) OnStart() error {
 		// Run any template that needs running
 		err = c.templateApplyNow(c.localConfig[key])
 		if err != nil {
-			apparmor.Destroy(c)
+			apparmor.Destroy(c.state, c)
 			if ourStart {
 				c.unmount()
 			}
@@ -2431,7 +2431,7 @@ func (c *lxc) OnStart() error {
 		// Remove the volatile key from the DB
 		err := c.state.Cluster.ContainerConfigRemove(c.id, key)
 		if err != nil {
-			apparmor.Destroy(c)
+			apparmor.Destroy(c.state, c)
 			if ourStart {
 				c.unmount()
 			}
@@ -2441,7 +2441,7 @@ func (c *lxc) OnStart() error {
 
 	err = c.templateApplyNow("start")
 	if err != nil {
-		apparmor.Destroy(c)
+		apparmor.Destroy(c.state, c)
 		if ourStart {
 			c.unmount()
 		}
@@ -2784,7 +2784,7 @@ func (c *lxc) OnStop(target string) error {
 		c.IsRunning()
 
 		// Unload the apparmor profile
-		err = apparmor.Destroy(c)
+		err = apparmor.Destroy(c.state, c)
 		if err != nil {
 			logger.Error("Failed to destroy apparmor namespace", log.Ctx{"container": c.Name(), "err": err})
 		}
@@ -3346,7 +3346,7 @@ func (c *lxc) cleanup() {
 	c.removeDiskDevices()
 
 	// Remove the security profiles
-	apparmor.DeleteProfile(c)
+	apparmor.DeleteProfile(c.state, c)
 	seccomp.DeleteProfile(c)
 
 	// Remove the devices path
@@ -3939,7 +3939,7 @@ func (c *lxc) Update(args db.InstanceArgs, userRequested bool) error {
 
 	// If apparmor changed, re-validate the apparmor profile
 	if shared.StringInSlice("raw.apparmor", changedConfig) || shared.StringInSlice("security.nesting", changedConfig) {
-		err = apparmor.ParseProfile(c)
+		err = apparmor.ParseProfile(c.state, c)
 		if err != nil {
 			return errors.Wrap(err, "Parse AppArmor profile")
 		}
@@ -4011,7 +4011,7 @@ func (c *lxc) Update(args db.InstanceArgs, userRequested bool) error {
 
 			if key == "raw.apparmor" || key == "security.nesting" {
 				// Update the AppArmor profile
-				err = apparmor.LoadProfile(c)
+				err = apparmor.LoadProfile(c.state, c)
 				if err != nil {
 					return err
 				}

From 0a43c3c721e5491c7fae11f09368a01c33ab4a1f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:09:35 +0000
Subject: [PATCH 40/62] lxd/instance/drivers/driver/qemu: Adds SaveConfigFile
 placeholder

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_qemu.go | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index ca97f5ccc6..9f01cd8adc 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -975,6 +975,11 @@ func (vm *qemu) RegisterDevices() {
 	return
 }
 
+// SaveConfigFile is not used by VMs.
+func (vm *qemu) SaveConfigFile() error {
+	return fmt.Errorf("SaveConfigFile Not Implemented")
+}
+
 // deviceLoad instantiates and validates a new device and returns it along with enriched config.
 func (vm *qemu) deviceLoad(deviceName string, rawConfig deviceConfig.Device) (device.Device, deviceConfig.Device, error) {
 	var configCopy deviceConfig.Device

From 8799e7fa3fddaa25ceeaee2ca730c7a6402a9944 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:09:48 +0000
Subject: [PATCH 41/62] lxd/instance/drivers/driver/qemu: Removes DaemonState
 function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_qemu.go | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index 9f01cd8adc..f9a17f58b2 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -3449,17 +3449,6 @@ func (vm *qemu) DeferTemplateApply(trigger string) error {
 	return nil
 }
 
-// DaemonState returns the state of the daemon. Deprecated.
-func (vm *qemu) DaemonState() *state.State {
-	// FIXME: This function should go away, since the abstract instance
-	//        interface should not be coupled with internal state details.
-	//        However this is not currently possible, because many
-	//        higher-level APIs use instance variables as "implicit
-	//        handles" to database/OS state and then need a way to get a
-	//        reference to it.
-	return vm.state
-}
-
 // FillNetworkDevice takes a nic or infiniband device type and enriches it with automatically
 // generated name and hwaddr properties if these are missing from the device.
 func (vm *qemu) FillNetworkDevice(name string, m deviceConfig.Device) (deviceConfig.Device, error) {

From 5ab5556b42b4b660d1ba608d240690c26b574d1f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:10:08 +0000
Subject: [PATCH 42/62] lxd/instance/drivers/driver/utils: Adds
 PrepareEqualTest function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/drivers/driver_utils.go | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/lxd/instance/drivers/driver_utils.go b/lxd/instance/drivers/driver_utils.go
index 283fd24b10..07d3d71061 100644
--- a/lxd/instance/drivers/driver_utils.go
+++ b/lxd/instance/drivers/driver_utils.go
@@ -5,6 +5,8 @@ import (
 
 	"golang.org/x/sys/unix"
 
+	"github.com/lxc/lxd/lxd/instance"
+	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/shared"
 )
 
@@ -44,3 +46,15 @@ func SetupSharedMounts() error {
 	sharedMounted = true
 	return nil
 }
+
+// PrepareEqualTest modifies any unexported variables required for reflect.DeepEqual to complete safely.
+// This is used for tests to avoid infinite recursion loops.
+func PrepareEqualTest(insts ...instance.Instance) {
+	for _, inst := range insts {
+		if inst.Type() == instancetype.Container {
+			// When loading from DB, we won't have a full LXC config.
+			inst.(*lxc).c = nil
+			inst.(*lxc).cConfig = false
+		}
+	}
+}

From 1fb1752d0751cae5f8bc65f2a6e2737a1d971d3e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:10:29 +0000
Subject: [PATCH 43/62] lxd/instance/instance/interface: Removes DaemonState
 function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/instance_interface.go | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lxd/instance/instance_interface.go b/lxd/instance/instance_interface.go
index 8b2a532343..efcf506004 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -10,7 +10,6 @@ import (
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
 	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/operations"
-	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared/api"
 )
 
@@ -115,5 +114,4 @@ type Instance interface {
 	StorageStart() (bool, error)
 	StorageStop() (bool, error)
 	DeferTemplateApply(trigger string) error
-	DaemonState() *state.State
 }

From 0c34a2e8d21dd7b07525e5f3620a48aed88f8664 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:10:44 +0000
Subject: [PATCH 44/62] lxd/instance/instance/interface: Adds SaveConfigFile

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/instance_interface.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/instance/instance_interface.go b/lxd/instance/instance_interface.go
index efcf506004..4cda3ed62f 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -33,6 +33,7 @@ type Instance interface {
 	Stop(stateful bool) error
 	Unfreeze() error
 	RegisterDevices()
+	SaveConfigFile() error
 
 	IsPrivileged() bool
 

From 0f66edb05283a08f6ea74eb7e9760d136b836f46 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:11:09 +0000
Subject: [PATCH 45/62] lxd/migrate/container: Removes s.instance.DaemonState
 dependency

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/migrate_container.go | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lxd/migrate_container.go b/lxd/migrate_container.go
index 4488fb102c..67cf6e35c5 100644
--- a/lxd/migrate_container.go
+++ b/lxd/migrate_container.go
@@ -239,7 +239,7 @@ type preDumpLoopArgs struct {
 // This function contains the actual pre-dump, the corresponding rsync
 // transfer and it tells the outer loop to abort if the threshold
 // of memory pages transferred by pre-dumping has been reached.
-func (s *migrationSourceWs) preDumpLoop(args *preDumpLoopArgs) (bool, error) {
+func (s *migrationSourceWs) preDumpLoop(state *state.State, args *preDumpLoopArgs) (bool, error) {
 	// Do a CRIU pre-dump
 	criuMigrationArgs := instance.CriuMigrationArgs{
 		Cmd:          lxc.MIGRATE_PRE_DUMP,
@@ -267,7 +267,6 @@ func (s *migrationSourceWs) preDumpLoop(args *preDumpLoopArgs) (bool, error) {
 
 	// Send the pre-dump.
 	ctName, _, _ := shared.InstanceGetParentAndSnapshotName(s.instance.Name())
-	state := s.instance.DaemonState()
 	err = rsync.Send(ctName, shared.AddSlash(args.checkpointDir), &shared.WebsocketIO{Conn: s.criuConn}, nil, args.rsyncFeatures, args.bwlimit, state.OS.ExecPath)
 	if err != nil {
 		return final, err
@@ -590,7 +589,7 @@ func (s *migrationSourceWs) Do(state *state.State, migrateOp *operations.Operati
 						final:         final,
 						rsyncFeatures: rsyncFeatures,
 					}
-					final, err = s.preDumpLoop(&loopArgs)
+					final, err = s.preDumpLoop(state, &loopArgs)
 					if err != nil {
 						os.RemoveAll(checkpointDir)
 						return abort(err)
@@ -900,7 +899,7 @@ func (c *migrationSink) Do(state *state.State, migrateOp *operations.Operation)
 				// Check if snapshot exists already and if not then create
 				// a new snapshot DB record so that the storage layer can
 				// populate the volume on the storage device.
-				_, err := instance.LoadByProjectAndName(args.Instance.DaemonState(), args.Instance.Project(), snapArgs.Name)
+				_, err := instance.LoadByProjectAndName(state, args.Instance.Project(), snapArgs.Name)
 				if err != nil {
 					// Create the snapshot as it doesn't seem to exist.
 					_, err := instanceCreateInternal(state, snapArgs)

From 3784573a87284820a1b143aa4b6a86b996f11381 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:11:53 +0000
Subject: [PATCH 46/62] lxd/profiles/utils: Removes use of containerLXC type

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/profiles_utils.go | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/lxd/profiles_utils.go b/lxd/profiles_utils.go
index e506d56e64..bef9d19324 100644
--- a/lxd/profiles_utils.go
+++ b/lxd/profiles_utils.go
@@ -208,30 +208,33 @@ func doProfileUpdateContainer(d *Daemon, name string, old api.ProfilePut, nodeNa
 	if err != nil {
 		return err
 	}
+
 	for i, profileName := range args.Profiles {
 		if profileName == name {
-			// Use the old config and devices.
+			// Overwrite the new config from the database with the old config and devices.
 			profiles[i].Config = old.Config
 			profiles[i].Devices = old.Devices
 			break
 		}
 	}
 
-	c := containerLXCInstantiate(d.State(), args, nil)
-
-	c.(*containerLXC).expandConfig(profiles)
-	c.(*containerLXC).expandDevices(profiles)
-
-	return c.Update(db.InstanceArgs{
-		Architecture: c.Architecture(),
-		Config:       c.LocalConfig(),
-		Description:  c.Description(),
-		Devices:      c.LocalDevices(),
-		Ephemeral:    c.IsEphemeral(),
-		Profiles:     c.Profiles(),
-		Project:      c.Project(),
-		Type:         c.Type(),
-		Snapshot:     c.IsSnapshot(),
+	// Load the instance using the old profile config.
+	inst, err := instance.Load(d.State(), args, profiles)
+	if err != nil {
+		return err
+	}
+
+	// Update will internally load the new profile configs and detect the changes to apply.
+	return inst.Update(db.InstanceArgs{
+		Architecture: inst.Architecture(),
+		Config:       inst.LocalConfig(),
+		Description:  inst.Description(),
+		Devices:      inst.LocalDevices(),
+		Ephemeral:    inst.IsEphemeral(),
+		Profiles:     inst.Profiles(),
+		Project:      inst.Project(),
+		Type:         inst.Type(),
+		Snapshot:     inst.IsSnapshot(),
 	}, true)
 }
 

From 7b460e52216e02ac05e3fecb32d572995b38eb9f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:12:25 +0000
Subject: [PATCH 47/62] lxd/seccomp/seccomp: Removes c.DaemonState dependency

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/seccomp/seccomp.go | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/lxd/seccomp/seccomp.go b/lxd/seccomp/seccomp.go
index 35b1a8244c..22c52a996a 100644
--- a/lxd/seccomp/seccomp.go
+++ b/lxd/seccomp/seccomp.go
@@ -366,7 +366,6 @@ type Instance interface {
 	Project() string
 	ExpandedConfig() map[string]string
 	IsPrivileged() bool
-	DaemonState() *state.State
 	Architecture() int
 	RootfsPath() string
 	CurrentIdmap() (*idmap.IdmapSet, error)
@@ -429,14 +428,14 @@ func InstanceNeedsPolicy(c Instance) bool {
 }
 
 // InstanceNeedsIntercept returns whether instance needs intercept.
-func InstanceNeedsIntercept(c Instance) (bool, error) {
+func InstanceNeedsIntercept(s *state.State, c Instance) (bool, error) {
 	// No need if privileged
 	if c.IsPrivileged() {
 		return false, nil
 	}
 
 	// If nested, assume the host handles it
-	if c.DaemonState().OS.RunningInUserNS {
+	if s.OS.RunningInUserNS {
 		return false, nil
 	}
 
@@ -454,7 +453,7 @@ func InstanceNeedsIntercept(c Instance) (bool, error) {
 			continue
 		}
 
-		if !isSupported(c.DaemonState()) {
+		if !isSupported(s) {
 			return needed, fmt.Errorf("System doesn't support syscall interception")
 		}
 
@@ -464,7 +463,7 @@ func InstanceNeedsIntercept(c Instance) (bool, error) {
 	return needed, nil
 }
 
-func seccompGetPolicyContent(c Instance) (string, error) {
+func seccompGetPolicyContent(s *state.State, c Instance) (string, error) {
 	config := c.ExpandedConfig()
 
 	// Full policy override
@@ -489,7 +488,7 @@ func seccompGetPolicyContent(c Instance) (string, error) {
 	}
 
 	// Syscall interception
-	ok, err := InstanceNeedsIntercept(c)
+	ok, err := InstanceNeedsIntercept(s, c)
 	if err != nil {
 		return "", err
 	}
@@ -539,7 +538,7 @@ func seccompGetPolicyContent(c Instance) (string, error) {
 }
 
 // CreateProfile creates a seccomp profile.
-func CreateProfile(c Instance) error {
+func CreateProfile(s *state.State, c Instance) error {
 	/* Unlike apparmor, there is no way to "cache" profiles, and profiles
 	 * are automatically unloaded when a task dies. Thus, we don't need to
 	 * unload them when a container stops, and we don't have to worry about
@@ -550,7 +549,7 @@ func CreateProfile(c Instance) error {
 		return nil
 	}
 
-	profile, err := seccompGetPolicyContent(c)
+	profile, err := seccompGetPolicyContent(s, c)
 	if err != nil {
 		return err
 	}
@@ -1557,7 +1556,7 @@ func (s *Server) MountSyscallShift(c Instance) bool {
 			return false
 		}
 
-		if diskIdmap == nil && c.DaemonState().OS.Shiftfs {
+		if diskIdmap == nil && s.s.OS.Shiftfs {
 			return true
 		}
 	}

From 17c45930c302471a6405f08bfac3b7502c67b5dc Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:12:42 +0000
Subject: [PATCH 48/62] lxd/storage/drivers/utils: golint fixes

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/drivers/utils.go | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index 66b85d81f5..e77b59d553 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -585,10 +585,12 @@ func loopFilePath(poolName string) string {
 	return filepath.Join(shared.VarPath("disks"), fmt.Sprintf("%s.img", poolName))
 }
 
+// ShiftBtrfsRootfs shifts the BTRFS root filesystem.
 func ShiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet) error {
 	return shiftBtrfsRootfs(path, diskIdmap, true)
 }
 
+// UnshiftBtrfsRootfs unshifts the BTRFS root filesystem.
 func UnshiftBtrfsRootfs(path string, diskIdmap *idmap.IdmapSet) error {
 	return shiftBtrfsRootfs(path, diskIdmap, false)
 }
@@ -695,6 +697,7 @@ func BTRFSSubVolumeMakeRw(path string) error {
 	return err
 }
 
+// IDMapsetFromString returns an IdmapSet from string.
 func IDMapsetFromString(idmapString string) (*idmap.IdmapSet, error) {
 	lastIdmap := new(idmap.IdmapSet)
 	err := json.Unmarshal([]byte(idmapString), &lastIdmap.Idmap)
@@ -709,6 +712,7 @@ func IDMapsetFromString(idmapString string) (*idmap.IdmapSet, error) {
 	return lastIdmap, nil
 }
 
+// ShiftZFSSkipper indicates which files not to shift for ZFS.
 func ShiftZFSSkipper(dir string, absPath string, fi os.FileInfo) bool {
 	strippedPath := absPath
 	if dir != "" {

From 8b2ce7fa0087e5b1d197994557d14d5e499b7e3e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 12:23:30 +0000
Subject: [PATCH 49/62] lxd/instance/instance/interface: Adds Container
 interface

This interface provides an easy way to see the differences between the common Instance interface and the more specific container implementations.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/instance_interface.go | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/lxd/instance/instance_interface.go b/lxd/instance/instance_interface.go
index 4cda3ed62f..f2704ce5db 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -11,6 +11,7 @@ import (
 	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/shared/api"
+	"github.com/lxc/lxd/shared/idmap"
 )
 
 // ConfigReader is used to read instance config.
@@ -22,7 +23,7 @@ type ConfigReader interface {
 	LocalDevices() deviceConfig.Devices
 }
 
-// The Instance interface.
+// Instance interface.
 type Instance interface {
 	ConfigReader
 
@@ -116,3 +117,22 @@ type Instance interface {
 	StorageStop() (bool, error)
 	DeferTemplateApply(trigger string) error
 }
+
+// Container interface is for container specific functions.
+type Container interface {
+	Instance
+
+	CurrentIdmap() (*idmap.IdmapSet, error)
+	DiskIdmap() (*idmap.IdmapSet, error)
+	NextIdmap() (*idmap.IdmapSet, error)
+
+	OnStart() error
+	OnStopNS(target string, netns string) error
+	OnStop(target string) error
+
+	ConsoleLog(opts liblxc.ConsoleLogOptions) (string, error)
+
+	Migrate(args *CriuMigrationArgs) error
+
+	InsertSeccompUnixDevice(prefix string, m deviceConfig.Device, pid int) error
+}

From 2f31f32da03fbdae30084041fde72e37a2f7d84e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 12:24:23 +0000
Subject: [PATCH 50/62] lxd/instance/instance/interface: Adds CriuMigrationArgs
 type

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/instance/instance_interface.go | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/lxd/instance/instance_interface.go b/lxd/instance/instance_interface.go
index f2704ce5db..c9257f6ce4 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -5,6 +5,8 @@ import (
 	"os"
 	"time"
 
+	liblxc "gopkg.in/lxc/go-lxc.v2"
+
 	"github.com/lxc/lxd/lxd/backup"
 	"github.com/lxc/lxd/lxd/db"
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
@@ -136,3 +138,15 @@ type Container interface {
 
 	InsertSeccompUnixDevice(prefix string, m deviceConfig.Device, pid int) error
 }
+
+// CriuMigrationArgs arguments for CRIU migration.
+type CriuMigrationArgs struct {
+	Cmd          uint
+	StateDir     string
+	Function     string
+	Stop         bool
+	ActionScript bool
+	DumpDir      string
+	PreDumpDir   string
+	Features     liblxc.CriuFeatures
+}

From 69cbae8d3154302e2e99326d3fe38171ed10c477 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 12:25:00 +0000
Subject: [PATCH 51/62] lxd/backup/backup: Comment clarifying existence of
 Instance interface

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/backup/backup.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/backup/backup.go b/lxd/backup/backup.go
index 323bd3edc7..cd514bf04f 100644
--- a/lxd/backup/backup.go
+++ b/lxd/backup/backup.go
@@ -18,6 +18,7 @@ import (
 )
 
 // Instance represents the backup relevant subset of a LXD instance.
+// This is used rather than instance.Instance to avoid import loops.
 type Instance interface {
 	Name() string
 	Project() string

From c8389216f904450687d9027da86d21ce6e3b6678 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 12:27:37 +0000
Subject: [PATCH 52/62] lxd/seccomp/seccomp: Comment clarifying existence of
 Instance interface

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/seccomp/seccomp.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/seccomp/seccomp.go b/lxd/seccomp/seccomp.go
index 22c52a996a..18db1c47e7 100644
--- a/lxd/seccomp/seccomp.go
+++ b/lxd/seccomp/seccomp.go
@@ -361,6 +361,7 @@ stub_x32_execveat errno 38
 `
 
 // Instance is a seccomp specific instance interface.
+// This is used rather than instance.Instance to avoid import loops.
 type Instance interface {
 	Name() string
 	Project() string

From b9e99e1fbf31bdf9a00c721b33ca55da71dfcb7a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:18:23 +0000
Subject: [PATCH 53/62] lxd/container/lxc/utils: Removes unused file

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_lxc_utils.go | 16 ----------------
 1 file changed, 16 deletions(-)
 delete mode 100644 lxd/container_lxc_utils.go

diff --git a/lxd/container_lxc_utils.go b/lxd/container_lxc_utils.go
deleted file mode 100644
index 7ea2afea2b..0000000000
--- a/lxd/container_lxc_utils.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package main
-
-import (
-	"encoding/json"
-
-	"github.com/lxc/lxd/shared/idmap"
-)
-
-func idmapsetToJSON(idmapSet *idmap.IdmapSet) (string, error) {
-	idmapBytes, err := json.Marshal(idmapSet.Idmap)
-	if err != nil {
-		return "", err
-	}
-
-	return string(idmapBytes), nil
-}

From 41974edce4d9a6fce1923404ed71975d2b418461 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:18:39 +0000
Subject: [PATCH 54/62] lxd/device/device/utils/disk: Adds diskIDMapsetToJSON
 function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/device_utils_disk.go | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/lxd/device/device_utils_disk.go b/lxd/device/device_utils_disk.go
index 25f21090fa..739f42eccb 100644
--- a/lxd/device/device_utils_disk.go
+++ b/lxd/device/device_utils_disk.go
@@ -2,6 +2,7 @@ package device
 
 import (
 	"bufio"
+	"encoding/json"
 	"fmt"
 	"os"
 	"os/exec"
@@ -14,6 +15,7 @@ import (
 	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
+	"github.com/lxc/lxd/shared/idmap"
 )
 
 // StorageVolumeMount checks if storage volume is mounted and if not tries to mount it.
@@ -273,3 +275,12 @@ func diskCephfsOptions(clusterName string, userName string, fsName string, fsPat
 
 	return srcpath, fsOptions, nil
 }
+
+func diskIDMapsetToJSON(idmapSet *idmap.IdmapSet) (string, error) {
+	idmapBytes, err := json.Marshal(idmapSet.Idmap)
+	if err != nil {
+		return "", err
+	}
+
+	return string(idmapBytes), nil
+}

From 47a4edb023009fe8252d116a8255ad622568a418 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:19:28 +0000
Subject: [PATCH 55/62] lxd/device/disk: Replaces call to StorageVolumeMount
 with functions on disk device

StorageVolumeMount was only used by disk device.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/disk.go | 206 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 201 insertions(+), 5 deletions(-)

diff --git a/lxd/device/disk.go b/lxd/device/disk.go
index 9f10a0d157..18be1fc2a4 100644
--- a/lxd/device/disk.go
+++ b/lxd/device/disk.go
@@ -19,9 +19,12 @@ import (
 	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/project"
+	"github.com/lxc/lxd/lxd/revert"
 	storagePools "github.com/lxc/lxd/lxd/storage"
+	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/lxd/util"
 	"github.com/lxc/lxd/shared"
+	"github.com/lxc/lxd/shared/idmap"
 	"github.com/lxc/lxd/shared/logger"
 	"github.com/lxc/lxd/shared/units"
 )
@@ -579,6 +582,9 @@ func (d *disk) generateLimits(runConf *deviceConfig.RunConfig) error {
 
 // createDevice creates a disk device mount on host.
 func (d *disk) createDevice() (string, error) {
+	revert := revert.New()
+	defer revert.Fail()
+
 	// Paths.
 	devPath := d.getDevicePath(d.name, d.config)
 	srcPath := shared.HostPath(d.config["source"])
@@ -701,17 +707,43 @@ func (d *disk) createDevice() (string, error) {
 		case db.StoragePoolVolumeTypeNameImage:
 			return "", fmt.Errorf("Using image storage volumes is not supported")
 		default:
-			return "", fmt.Errorf("Unknown storage type prefix \"%s\" found", volumeTypeName)
+			return "", fmt.Errorf("Unknown storage type prefix %q found", volumeTypeName)
 		}
 
-		err := StorageVolumeMount(d.state, d.config["pool"], volumeName, volumeTypeName, d.inst)
+		volumeType, err := storagePools.VolumeTypeNameToType(volumeTypeName)
+		if err != nil {
+			return "", err
+		}
+
+		pool, err := storagePools.GetPoolByName(d.state, d.config["pool"])
+		if err != nil {
+			return "", err
+		}
+
+		// Mount and prepare the volume to be attached.
+		err = func() error {
+			ourMount, err := pool.MountCustomVolume(volumeName, nil)
+			if err != nil {
+				return errors.Wrapf(err, "Could not mount storage volume %q of type %q on storage pool %q", volumeName, volumeTypeName, d.config["pool"])
+			}
+
+			if ourMount {
+				revert.Add(func() { pool.UnmountCustomVolume(volumeName, nil) })
+			}
+
+			err = d.storagePoolVolumeAttachPrepare(pool.Name(), volumeName, volumeType)
+			if err != nil {
+				return errors.Wrapf(err, "Could not attach storage volume %q of type %q on storage pool %q", volumeName, volumeTypeName, d.config["pool"])
+			}
+
+			return nil
+		}()
 		if err != nil {
-			msg := fmt.Sprintf("Could not mount storage volume \"%s\" of type \"%s\" on storage pool \"%s\": %s.", volumeName, volumeTypeName, d.config["pool"], err)
 			if !isRequired {
 				// Will fail the PathExists test below.
-				logger.Warn(msg)
+				logger.Warn(err.Error())
 			} else {
-				return "", fmt.Errorf(msg)
+				return "", err
 			}
 		}
 	}
@@ -761,9 +793,173 @@ func (d *disk) createDevice() (string, error) {
 		return "", err
 	}
 
+	revert.Success()
 	return devPath, nil
 }
 
+func (d *disk) storagePoolVolumeAttachPrepare(poolName string, volumeName string, volumeType int) error {
+	// Load the DB records
+	poolID, pool, err := d.state.Cluster.StoragePoolGet(poolName)
+	if err != nil {
+		return err
+	}
+
+	// Custom storage volumes do not currently support projects, so hardcode "default" project.
+	_, volume, err := d.state.Cluster.StoragePoolNodeVolumeGetTypeByProject("default", volumeName, volumeType, poolID)
+	if err != nil {
+		return err
+	}
+
+	poolVolumePut := volume.Writable()
+
+	// Check if unmapped
+	if shared.IsTrue(poolVolumePut.Config["security.unmapped"]) {
+		// No need to look at containers and maps for unmapped volumes
+		return nil
+	}
+
+	// Get the on-disk idmap for the volume
+	var lastIdmap *idmap.IdmapSet
+	if poolVolumePut.Config["volatile.idmap.last"] != "" {
+		lastIdmap, err = storageDrivers.IDMapsetFromString(poolVolumePut.Config["volatile.idmap.last"])
+		if err != nil {
+			logger.Errorf("Failed to unmarshal last idmapping: %s", poolVolumePut.Config["volatile.idmap.last"])
+			return err
+		}
+	}
+
+	var nextIdmap *idmap.IdmapSet
+	nextJSONMap := "[]"
+	if !shared.IsTrue(poolVolumePut.Config["security.shifted"]) {
+		c := d.inst.(instance.Container)
+		// Get the container's idmap
+		if c.IsRunning() {
+			nextIdmap, err = c.CurrentIdmap()
+		} else {
+			nextIdmap, err = c.NextIdmap()
+		}
+		if err != nil {
+			return err
+		}
+
+		if nextIdmap != nil {
+			nextJSONMap, err = diskIDMapsetToJSON(nextIdmap)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	poolVolumePut.Config["volatile.idmap.next"] = nextJSONMap
+
+	// Get mountpoint of storage volume
+	remapPath := storagePools.GetStoragePoolVolumeMountPoint(poolName, volumeName)
+
+	if !nextIdmap.Equals(lastIdmap) {
+		logger.Debugf("Shifting storage volume")
+
+		if !shared.IsTrue(poolVolumePut.Config["security.shifted"]) {
+			// Custom storage volumes do not currently support projects, so hardcode "default" project.
+			volumeUsedBy, err := storagePools.VolumeUsedByInstancesGet(d.state, "default", poolName, volumeName)
+			if err != nil {
+				return err
+			}
+
+			if len(volumeUsedBy) > 1 {
+				for _, ctName := range volumeUsedBy {
+					instt, err := instance.LoadByProjectAndName(d.state, d.inst.Project(), ctName)
+					if err != nil {
+						continue
+					}
+
+					if instt.Type() != instancetype.Container {
+						continue
+					}
+
+					ct := instt.(instance.Container)
+
+					var ctNextIdmap *idmap.IdmapSet
+					if ct.IsRunning() {
+						ctNextIdmap, err = ct.CurrentIdmap()
+					} else {
+						ctNextIdmap, err = ct.NextIdmap()
+					}
+					if err != nil {
+						return fmt.Errorf("Failed to retrieve idmap of container")
+					}
+
+					if !nextIdmap.Equals(ctNextIdmap) {
+						return fmt.Errorf("Idmaps of container %v and storage volume %v are not identical", ctName, volumeName)
+					}
+				}
+			} else if len(volumeUsedBy) == 1 {
+				// If we're the only one who's attached that container
+				// we can shift the storage volume.
+				// I'm not sure if we want some locking here.
+				if volumeUsedBy[0] != d.inst.Name() {
+					return fmt.Errorf("idmaps of container and storage volume are not identical")
+				}
+			}
+		}
+
+		// Unshift rootfs
+		if lastIdmap != nil {
+			var err error
+
+			if pool.Driver == "zfs" {
+				err = lastIdmap.UnshiftRootfs(remapPath, storageDrivers.ShiftZFSSkipper)
+			} else {
+				err = lastIdmap.UnshiftRootfs(remapPath, nil)
+			}
+
+			if err != nil {
+				logger.Errorf("Failed to unshift \"%s\"", remapPath)
+				return err
+			}
+
+			logger.Debugf("Unshifted \"%s\"", remapPath)
+		}
+
+		// Shift rootfs
+		if nextIdmap != nil {
+			var err error
+
+			if pool.Driver == "zfs" {
+				err = nextIdmap.ShiftRootfs(remapPath, storageDrivers.ShiftZFSSkipper)
+			} else {
+				err = nextIdmap.ShiftRootfs(remapPath, nil)
+			}
+
+			if err != nil {
+				logger.Errorf("Failed to shift \"%s\"", remapPath)
+				return err
+			}
+
+			logger.Debugf("Shifted \"%s\"", remapPath)
+		}
+		logger.Debugf("Shifted storage volume")
+	}
+
+	jsonIdmap := "[]"
+	if nextIdmap != nil {
+		var err error
+		jsonIdmap, err = diskIDMapsetToJSON(nextIdmap)
+		if err != nil {
+			logger.Errorf("Failed to marshal idmap")
+			return err
+		}
+	}
+
+	// Update last idmap
+	poolVolumePut.Config["volatile.idmap.last"] = jsonIdmap
+
+	err = d.state.Cluster.StoragePoolVolumeUpdateByProject("default", volumeName, volumeType, poolID, poolVolumePut.Description, poolVolumePut.Config)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
 // Stop is run when the device is removed from the instance.
 func (d *disk) Stop() (*deviceConfig.RunConfig, error) {
 	if d.inst.Type() == instancetype.VM {

From d669d3b12015fb9fb099ac8980a26cd230aeda2c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:20:18 +0000
Subject: [PATCH 56/62] lxd/storage: Removes storageVolumeMount and
 storagePoolVolumeAttachPrepare

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage.go | 209 -------------------------------------------------
 1 file changed, 209 deletions(-)

diff --git a/lxd/storage.go b/lxd/storage.go
index c4f1b8ba37..7ddd8ac8cc 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -11,7 +11,6 @@ import (
 	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/device"
 	"github.com/lxc/lxd/lxd/instance"
-	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/state"
 	storagePools "github.com/lxc/lxd/lxd/storage"
 	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
@@ -22,9 +21,6 @@ import (
 )
 
 func init() {
-	// Expose storageVolumeMount to the device package as StorageVolumeMount.
-	device.StorageVolumeMount = storageVolumeMount
-
 	// Expose storageVolumeUmount to the device package as StorageVolumeUmount.
 	device.StorageVolumeUmount = storageVolumeUmount
 
@@ -46,166 +42,6 @@ func readStoragePoolDriversCache() map[string]string {
 	return drivers.(map[string]string)
 }
 
-func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName string, volumeType int, c instance.Container) error {
-	// Load the DB records
-	poolID, pool, err := s.Cluster.StoragePoolGet(poolName)
-	if err != nil {
-		return err
-	}
-
-	_, volume, err := s.Cluster.StoragePoolNodeVolumeGetTypeByProject("default", volumeName, volumeType, poolID)
-	if err != nil {
-		return err
-	}
-
-	poolVolumePut := volume.Writable()
-
-	// Check if unmapped
-	if shared.IsTrue(poolVolumePut.Config["security.unmapped"]) {
-		// No need to look at containers and maps for unmapped volumes
-		return nil
-	}
-
-	// Get the on-disk idmap for the volume
-	var lastIdmap *idmap.IdmapSet
-	if poolVolumePut.Config["volatile.idmap.last"] != "" {
-		lastIdmap, err = storageDrivers.IDMapsetFromString(poolVolumePut.Config["volatile.idmap.last"])
-		if err != nil {
-			logger.Errorf("Failed to unmarshal last idmapping: %s", poolVolumePut.Config["volatile.idmap.last"])
-			return err
-		}
-	}
-
-	var nextIdmap *idmap.IdmapSet
-	nextJsonMap := "[]"
-	if !shared.IsTrue(poolVolumePut.Config["security.shifted"]) {
-		// Get the container's idmap
-		if c.IsRunning() {
-			nextIdmap, err = c.CurrentIdmap()
-		} else {
-			nextIdmap, err = c.NextIdmap()
-		}
-		if err != nil {
-			return err
-		}
-
-		if nextIdmap != nil {
-			nextJsonMap, err = idmapsetToJSON(nextIdmap)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	poolVolumePut.Config["volatile.idmap.next"] = nextJsonMap
-
-	// Get mountpoint of storage volume
-	remapPath := storagePools.GetStoragePoolVolumeMountPoint(poolName, volumeName)
-
-	if !nextIdmap.Equals(lastIdmap) {
-		logger.Debugf("Shifting storage volume")
-
-		if !shared.IsTrue(poolVolumePut.Config["security.shifted"]) {
-			volumeUsedBy, err := storagePoolVolumeUsedByInstancesGet(s, "default", poolName, volumeName)
-			if err != nil {
-				return err
-			}
-
-			if len(volumeUsedBy) > 1 {
-				for _, ctName := range volumeUsedBy {
-					instt, err := instance.LoadByProjectAndName(s, c.Project(), ctName)
-					if err != nil {
-						continue
-					}
-
-					if instt.Type() != instancetype.Container {
-						continue
-					}
-
-					ct := instt.(instance.Container)
-
-					var ctNextIdmap *idmap.IdmapSet
-					if ct.IsRunning() {
-						ctNextIdmap, err = ct.CurrentIdmap()
-					} else {
-						ctNextIdmap, err = ct.NextIdmap()
-					}
-					if err != nil {
-						return fmt.Errorf("Failed to retrieve idmap of container")
-					}
-
-					if !nextIdmap.Equals(ctNextIdmap) {
-						return fmt.Errorf("Idmaps of container %v and storage volume %v are not identical", ctName, volumeName)
-					}
-				}
-			} else if len(volumeUsedBy) == 1 {
-				// If we're the only one who's attached that container
-				// we can shift the storage volume.
-				// I'm not sure if we want some locking here.
-				if volumeUsedBy[0] != c.Name() {
-					return fmt.Errorf("idmaps of container and storage volume are not identical")
-				}
-			}
-		}
-
-		// Unshift rootfs
-		if lastIdmap != nil {
-			var err error
-
-			if pool.Driver == "zfs" {
-				err = lastIdmap.UnshiftRootfs(remapPath, storageDrivers.ShiftZFSSkipper)
-			} else {
-				err = lastIdmap.UnshiftRootfs(remapPath, nil)
-			}
-
-			if err != nil {
-				logger.Errorf("Failed to unshift \"%s\"", remapPath)
-				return err
-			}
-
-			logger.Debugf("Unshifted \"%s\"", remapPath)
-		}
-
-		// Shift rootfs
-		if nextIdmap != nil {
-			var err error
-
-			if pool.Driver == "zfs" {
-				err = nextIdmap.ShiftRootfs(remapPath, storageDrivers.ShiftZFSSkipper)
-			} else {
-				err = nextIdmap.ShiftRootfs(remapPath, nil)
-			}
-
-			if err != nil {
-				logger.Errorf("Failed to shift \"%s\"", remapPath)
-				return err
-			}
-
-			logger.Debugf("Shifted \"%s\"", remapPath)
-		}
-		logger.Debugf("Shifted storage volume")
-	}
-
-	jsonIdmap := "[]"
-	if nextIdmap != nil {
-		var err error
-		jsonIdmap, err = idmapsetToJSON(nextIdmap)
-		if err != nil {
-			logger.Errorf("Failed to marshal idmap")
-			return err
-		}
-	}
-
-	// Update last idmap
-	poolVolumePut.Config["volatile.idmap.last"] = jsonIdmap
-
-	err = s.Cluster.StoragePoolVolumeUpdateByProject("default", volumeName, volumeType, poolID, poolVolumePut.Description, poolVolumePut.Config)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
 func resetContainerDiskIdmap(container instance.Container, srcIdmap *idmap.IdmapSet) error {
 	dstIdmap, err := container.DiskIdmap()
 	if err != nil {
@@ -329,51 +165,6 @@ func storagePoolDriversCacheUpdate(s *state.State) {
 	return
 }
 
-// storageVolumeMount initialises a new storage interface and checks the pool and volume are
-// mounted. If they are not then they are mounted.
-func storageVolumeMount(state *state.State, poolName string, volumeName string, volumeTypeName string, inst instance.Instance) error {
-	c, ok := inst.(instance.Container)
-	if !ok {
-		return fmt.Errorf("Received non-LXC container instance")
-	}
-
-	volumeType, err := storagePools.VolumeTypeNameToType(volumeTypeName)
-	if err != nil {
-		return err
-	}
-
-	pool, err := storagePools.GetPoolByName(state, poolName)
-	if err != nil {
-		return err
-	}
-
-	// Mount the storage volume.
-	ourMount, err := pool.MountCustomVolume(volumeName, nil)
-	if err != nil {
-		return err
-	}
-
-	revert := true
-	if ourMount {
-		defer func() {
-			if !revert {
-				return
-			}
-
-			pool.UnmountCustomVolume(volumeName, nil)
-		}()
-	}
-
-	// Custom storage volumes do not currently support projects, so hardcode "default" project.
-	err = storagePoolVolumeAttachPrepare(state, poolName, volumeName, volumeType, c)
-	if err != nil {
-		return err
-	}
-
-	revert = false
-	return nil
-}
-
 // storageVolumeUmount unmounts a storage volume on a pool.
 func storageVolumeUmount(state *state.State, poolName string, volumeName string, volumeType int) error {
 	pool, err := storagePools.GetPoolByName(state, poolName)

From a7e3bb5e2c521e2ad49cd6f0893e00076f66a060 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:20:36 +0000
Subject: [PATCH 57/62] lxd/storage/utils: Adds VolumeUsedByInstancesGet

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/utils.go | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go
index 8fc854c05a..b1dc2d8675 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -628,3 +628,27 @@ func InstanceContentType(inst instance.Instance) drivers.ContentType {
 
 	return contentType
 }
+
+// VolumeUsedByInstancesGet gets a list of instance names using a volume.
+func VolumeUsedByInstancesGet(s *state.State, project, poolName string, volumeName string) ([]string, error) {
+	insts, err := instance.LoadByProject(s, project)
+	if err != nil {
+		return []string{}, err
+	}
+
+	instUsingVolume := []string{}
+	for _, inst := range insts {
+		for _, dev := range inst.LocalDevices() {
+			if dev["type"] != "disk" {
+				continue
+			}
+
+			if dev["pool"] == poolName && dev["source"] == volumeName {
+				instUsingVolume = append(instUsingVolume, inst.Name())
+				break
+			}
+		}
+	}
+
+	return instUsingVolume, nil
+}

From 4901fa9381bb5bc58ac39788cd44d668e7e314bc Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:20:50 +0000
Subject: [PATCH 58/62] lxd/storage/volumes/utils:
 storagePools.VolumeUsedByInstancesGet usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage_volumes_utils.go | 26 +-------------------------
 1 file changed, 1 insertion(+), 25 deletions(-)

diff --git a/lxd/storage_volumes_utils.go b/lxd/storage_volumes_utils.go
index 8569e23426..e4abfd2d77 100644
--- a/lxd/storage_volumes_utils.go
+++ b/lxd/storage_volumes_utils.go
@@ -5,7 +5,6 @@ import (
 	"path/filepath"
 
 	"github.com/lxc/lxd/lxd/db"
-	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/state"
 	storagePools "github.com/lxc/lxd/lxd/storage"
 	"github.com/lxc/lxd/shared"
@@ -76,29 +75,6 @@ func storagePoolVolumeTypeToAPIEndpoint(volumeType int) (string, error) {
 	return "", fmt.Errorf("invalid storage volume type")
 }
 
-func storagePoolVolumeUsedByInstancesGet(s *state.State, project, poolName string, volumeName string) ([]string, error) {
-	insts, err := instance.LoadByProject(s, project)
-	if err != nil {
-		return []string{}, err
-	}
-
-	instUsingVolume := []string{}
-	for _, inst := range insts {
-		for _, dev := range inst.LocalDevices() {
-			if dev["type"] != "disk" {
-				continue
-			}
-
-			if dev["pool"] == poolName && dev["source"] == volumeName {
-				instUsingVolume = append(instUsingVolume, inst.Name())
-				break
-			}
-		}
-	}
-
-	return instUsingVolume, nil
-}
-
 func storagePoolVolumeUpdateUsers(d *Daemon, oldPoolName string,
 	oldVolumeName string, newPoolName string, newVolumeName string) error {
 
@@ -311,7 +287,7 @@ func storagePoolVolumeUsedByGet(s *state.State, project, poolName string, volume
 	}
 
 	// Look for containers using this volume
-	ctsUsingVolume, err := storagePoolVolumeUsedByInstancesGet(s, project, poolName, volumeName)
+	ctsUsingVolume, err := storagePools.VolumeUsedByInstancesGet(s, project, poolName, volumeName)
 	if err != nil {
 		return []string{}, err
 	}

From f6d8e1186db754acda8480aef0d9130f27db8369 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:28:29 +0000
Subject: [PATCH 59/62] lxd/storage: Removes unused functions

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage.go | 40 ----------------------------------------
 1 file changed, 40 deletions(-)

diff --git a/lxd/storage.go b/lxd/storage.go
index 7ddd8ac8cc..b95b9a7ca1 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -9,7 +9,6 @@ import (
 	"github.com/pkg/errors"
 
 	"github.com/lxc/lxd/lxd/db"
-	"github.com/lxc/lxd/lxd/device"
 	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/state"
 	storagePools "github.com/lxc/lxd/lxd/storage"
@@ -20,14 +19,6 @@ import (
 	"github.com/lxc/lxd/shared/version"
 )
 
-func init() {
-	// Expose storageVolumeUmount to the device package as StorageVolumeUmount.
-	device.StorageVolumeUmount = storageVolumeUmount
-
-	// Expose storageRootFSApplyQuota to the device package as StorageRootFSApplyQuota.
-	device.StorageRootFSApplyQuota = storageRootFSApplyQuota
-}
-
 // Simply cache used to storage the activated drivers on this LXD instance. This
 // allows us to avoid querying the database everytime and API call is made.
 var storagePoolDriversCacheVal atomic.Value
@@ -164,34 +155,3 @@ func storagePoolDriversCacheUpdate(s *state.State) {
 
 	return
 }
-
-// storageVolumeUmount unmounts a storage volume on a pool.
-func storageVolumeUmount(state *state.State, poolName string, volumeName string, volumeType int) error {
-	pool, err := storagePools.GetPoolByName(state, poolName)
-	if err != nil {
-		return err
-	}
-
-	_, err = pool.UnmountCustomVolume(volumeName, nil)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// storageRootFSApplyQuota applies a quota to an instance if it can, if it cannot then it will
-// return false indicating that the quota needs to be stored in volatile to be applied on next boot.
-func storageRootFSApplyQuota(state *state.State, inst instance.Instance, size string) error {
-	pool, err := storagePools.GetPoolByInstance(state, inst)
-	if err != nil {
-		return err
-	}
-
-	err = pool.SetInstanceQuota(inst, size, nil)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}

From 549ee02079d5ef76f0e5032b00eec0bd3698aea7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:28:54 +0000
Subject: [PATCH 60/62] lxd/device: Removes usage of StorageRootFSApplyQuota,
 StorageVolumeMount and StorageVolumeUmount

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/device_utils_disk.go | 11 -----------
 lxd/device/disk.go              | 20 ++++++++++++++++++--
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/lxd/device/device_utils_disk.go b/lxd/device/device_utils_disk.go
index 739f42eccb..1078ff6ef6 100644
--- a/lxd/device/device_utils_disk.go
+++ b/lxd/device/device_utils_disk.go
@@ -12,21 +12,10 @@ import (
 
 	"golang.org/x/sys/unix"
 
-	"github.com/lxc/lxd/lxd/instance"
-	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/idmap"
 )
 
-// StorageVolumeMount checks if storage volume is mounted and if not tries to mount it.
-var StorageVolumeMount func(s *state.State, poolName string, volumeName string, volumeTypeName string, inst instance.Instance) error
-
-// StorageVolumeUmount unmounts a storage volume.
-var StorageVolumeUmount func(s *state.State, poolName string, volumeName string, volumeType int) error
-
-// StorageRootFSApplyQuota applies a new quota.
-var StorageRootFSApplyQuota func(s *state.State, inst instance.Instance, size string) error
-
 // BlockFsDetect detects the type of block device.
 func BlockFsDetect(dev string) (string, error) {
 	out, err := shared.RunCommand("blkid", "-s", "TYPE", "-o", "value", dev)
diff --git a/lxd/device/disk.go b/lxd/device/disk.go
index 18be1fc2a4..0c41be7986 100644
--- a/lxd/device/disk.go
+++ b/lxd/device/disk.go
@@ -494,7 +494,17 @@ func (d *disk) Update(oldDevices deviceConfig.Devices, isRunning bool) error {
 }
 
 func (d *disk) applyQuota(newSize string) error {
-	return StorageRootFSApplyQuota(d.state, d.inst, newSize)
+	pool, err := storagePools.GetPoolByInstance(d.state, d.inst)
+	if err != nil {
+		return err
+	}
+
+	err = pool.SetInstanceQuota(d.inst, newSize, nil)
+	if err != nil {
+		return err
+	}
+
+	return nil
 }
 
 // generateLimits adds a set of cgroup rules to apply specified limits to the supplied RunConfig.
@@ -991,11 +1001,17 @@ func (d *disk) Stop() (*deviceConfig.RunConfig, error) {
 func (d *disk) postStop() error {
 	// Check if pool-specific action should be taken.
 	if d.config["pool"] != "" {
-		err := StorageVolumeUmount(d.state, d.config["pool"], d.config["source"], db.StoragePoolVolumeTypeCustom)
+		pool, err := storagePools.GetPoolByName(d.state, d.config["pool"])
 		if err != nil {
 			return err
 		}
 
+		_, err = pool.UnmountCustomVolume(d.config["source"], nil)
+		if err != nil {
+			return err
+		}
+
+		return nil
 	}
 
 	devPath := d.getDevicePath(d.name, d.config)

From 742486983b1ab47b03b04a125e9362809f866f2a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:42:16 +0000
Subject: [PATCH 61/62] lxd: Removes old storagePoolVolumeType constants

Replaces with db.StoragePoolVolumeType constants.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/api_internal.go             |  8 ++--
 lxd/daemon_storage.go           |  4 +-
 lxd/migrate_storage_volumes.go  |  5 ++-
 lxd/patches.go                  | 78 ++++++++++++++++-----------------
 lxd/storage_pools_utils.go      |  2 +-
 lxd/storage_volumes.go          | 12 ++---
 lxd/storage_volumes_snapshot.go |  8 ++--
 lxd/storage_volumes_utils.go    | 21 +++------
 8 files changed, 65 insertions(+), 73 deletions(-)

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index a8fe617433..3f7e20f9d1 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -511,7 +511,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response {
 	}
 
 	// Check if a storage volume entry for the container already exists.
-	_, volume, ctVolErr := d.cluster.StoragePoolNodeVolumeGetTypeByProject(projectName, req.Name, storagePoolVolumeTypeContainer, pool.ID())
+	_, volume, ctVolErr := d.cluster.StoragePoolNodeVolumeGetTypeByProject(projectName, req.Name, db.StoragePoolVolumeTypeContainer, pool.ID())
 	if ctVolErr != nil {
 		if ctVolErr != db.ErrNoSuchObject {
 			return response.SmartError(ctVolErr)
@@ -550,7 +550,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response {
 		}
 
 		// Remove the storage volume db entry for the container since force was specified.
-		err := d.cluster.StoragePoolVolumeDelete(projectName, req.Name, storagePoolVolumeTypeContainer, pool.ID())
+		err := d.cluster.StoragePoolVolumeDelete(projectName, req.Name, db.StoragePoolVolumeTypeContainer, pool.ID())
 		if err != nil {
 			return response.SmartError(err)
 		}
@@ -651,7 +651,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response {
 		}
 
 		// Check if a storage volume entry for the snapshot already exists.
-		_, _, csVolErr := d.cluster.StoragePoolNodeVolumeGetTypeByProject(projectName, snap.Name, storagePoolVolumeTypeContainer, pool.ID())
+		_, _, csVolErr := d.cluster.StoragePoolNodeVolumeGetTypeByProject(projectName, snap.Name, db.StoragePoolVolumeTypeContainer, pool.ID())
 		if csVolErr != nil {
 			if csVolErr != db.ErrNoSuchObject {
 				return response.SmartError(csVolErr)
@@ -671,7 +671,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response {
 		}
 
 		if csVolErr == nil {
-			err := d.cluster.StoragePoolVolumeDelete(projectName, snap.Name, storagePoolVolumeTypeContainer, pool.ID())
+			err := d.cluster.StoragePoolVolumeDelete(projectName, snap.Name, db.StoragePoolVolumeTypeContainer, pool.ID())
 			if err != nil {
 				return response.SmartError(err)
 			}
diff --git a/lxd/daemon_storage.go b/lxd/daemon_storage.go
index 4ff8b30fde..86d72ec743 100644
--- a/lxd/daemon_storage.go
+++ b/lxd/daemon_storage.go
@@ -128,12 +128,12 @@ func daemonStorageValidate(s *state.State, target string) error {
 	}
 
 	// Confirm volume exists.
-	_, _, err = s.Cluster.StoragePoolNodeVolumeGetType(volumeName, storagePoolVolumeTypeCustom, poolID)
+	_, _, err = s.Cluster.StoragePoolNodeVolumeGetType(volumeName, db.StoragePoolVolumeTypeCustom, poolID)
 	if err != nil {
 		return errors.Wrapf(err, "Unable to load storage volume \"%s\"", target)
 	}
 
-	snapshots, err := s.Cluster.StoragePoolVolumeSnapshotsGetType(volumeName, storagePoolVolumeTypeCustom, poolID)
+	snapshots, err := s.Cluster.StoragePoolVolumeSnapshotsGetType(volumeName, db.StoragePoolVolumeTypeCustom, poolID)
 	if err != nil {
 		return errors.Wrapf(err, "Unable to load storage volume snapshots \"%s\"", target)
 	}
diff --git a/lxd/migrate_storage_volumes.go b/lxd/migrate_storage_volumes.go
index 7d362a3a29..c68133e276 100644
--- a/lxd/migrate_storage_volumes.go
+++ b/lxd/migrate_storage_volumes.go
@@ -6,6 +6,7 @@ import (
 	"github.com/golang/protobuf/proto"
 	"github.com/gorilla/websocket"
 
+	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/migration"
 	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/lxd/state"
@@ -66,12 +67,12 @@ func (s *migrationSourceWs) DoStorage(state *state.State, poolName string, volNa
 	// Only send snapshots when requested.
 	if !s.volumeOnly {
 		var err error
-		snaps, err := storagePools.VolumeSnapshotsGet(state, poolName, volName, storagePoolVolumeTypeCustom)
+		snaps, err := storagePools.VolumeSnapshotsGet(state, poolName, volName, db.StoragePoolVolumeTypeCustom)
 		if err == nil {
 			poolID, err := state.Cluster.StoragePoolGetID(poolName)
 			if err == nil {
 				for _, snap := range snaps {
-					_, snapVolume, err := state.Cluster.StoragePoolNodeVolumeGetType(snap.Name, storagePoolVolumeTypeCustom, poolID)
+					_, snapVolume, err := state.Cluster.StoragePoolNodeVolumeGetType(snap.Name, db.StoragePoolVolumeTypeCustom, poolID)
 					if err != nil {
 						continue
 					}
diff --git a/lxd/patches.go b/lxd/patches.go
index b657bdd859..fbfaea3420 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -213,7 +213,7 @@ func patchRenameCustomVolumeLVs(name string, d *Daemon) error {
 			continue
 		}
 
-		volumes, err := d.cluster.StoragePoolNodeVolumesGetType(storagePoolVolumeTypeCustom, poolID)
+		volumes, err := d.cluster.StoragePoolNodeVolumesGetType(db.StoragePoolVolumeTypeCustom, poolID)
 		if err != nil {
 			return err
 		}
@@ -540,16 +540,16 @@ func upgradeFromStorageTypeBtrfs(name string, d *Daemon, defaultPoolName string,
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, storagePoolVolumeTypeContainer, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, db.StoragePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the container")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, db.StoragePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", storagePoolVolumeTypeContainer, false, poolID, containerPoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", db.StoragePoolVolumeTypeContainer, false, poolID, containerPoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for container \"%s\"", ct)
 				return err
@@ -628,16 +628,16 @@ func upgradeFromStorageTypeBtrfs(name string, d *Daemon, defaultPoolName string,
 				return err
 			}
 
-			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, storagePoolVolumeTypeContainer, poolID)
+			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, db.StoragePoolVolumeTypeContainer, poolID)
 			if err == nil {
 				logger.Warnf("Storage volumes database already contains an entry for the snapshot")
-				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
+				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, db.StoragePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
 				if err != nil {
 					return err
 				}
 			} else if err == db.ErrNoSuchObject {
 				// Insert storage volumes for containers into the database.
-				_, err := d.cluster.StoragePoolVolumeCreate("default", cs, "", storagePoolVolumeTypeContainer, false, poolID, snapshotPoolVolumeConfig)
+				_, err := d.cluster.StoragePoolVolumeCreate("default", cs, "", db.StoragePoolVolumeTypeContainer, false, poolID, snapshotPoolVolumeConfig)
 				if err != nil {
 					logger.Errorf("Could not insert a storage volume for snapshot \"%s\"", cs)
 					return err
@@ -709,16 +709,16 @@ func upgradeFromStorageTypeBtrfs(name string, d *Daemon, defaultPoolName string,
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, storagePoolVolumeTypeImage, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, db.StoragePoolVolumeTypeImage, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the image")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, db.StoragePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", img, "", storagePoolVolumeTypeImage, false, poolID, imagePoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", img, "", db.StoragePoolVolumeTypeImage, false, poolID, imagePoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for image \"%s\"", img)
 				return err
@@ -830,16 +830,16 @@ func upgradeFromStorageTypeDir(name string, d *Daemon, defaultPoolName string, d
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, storagePoolVolumeTypeContainer, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, db.StoragePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the container")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, db.StoragePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", storagePoolVolumeTypeContainer, false, poolID, containerPoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", db.StoragePoolVolumeTypeContainer, false, poolID, containerPoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for container \"%s\"", ct)
 				return err
@@ -947,16 +947,16 @@ func upgradeFromStorageTypeDir(name string, d *Daemon, defaultPoolName string, d
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, storagePoolVolumeTypeContainer, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, db.StoragePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the snapshot")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, db.StoragePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", cs, "", storagePoolVolumeTypeContainer, false, poolID, snapshotPoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", cs, "", db.StoragePoolVolumeTypeContainer, false, poolID, snapshotPoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for snapshot \"%s\"", cs)
 				return err
@@ -977,16 +977,16 @@ func upgradeFromStorageTypeDir(name string, d *Daemon, defaultPoolName string, d
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, storagePoolVolumeTypeImage, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, db.StoragePoolVolumeTypeImage, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the image")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, db.StoragePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", img, "", storagePoolVolumeTypeImage, false, poolID, imagePoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", img, "", db.StoragePoolVolumeTypeImage, false, poolID, imagePoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for image \"%s\"", img)
 				return err
@@ -1139,16 +1139,16 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, storagePoolVolumeTypeContainer, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, db.StoragePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the container")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, db.StoragePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", storagePoolVolumeTypeContainer, false, poolID, containerPoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", db.StoragePoolVolumeTypeContainer, false, poolID, containerPoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for container \"%s\"", ct)
 				return err
@@ -1300,16 +1300,16 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 				return err
 			}
 
-			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, storagePoolVolumeTypeContainer, poolID)
+			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, db.StoragePoolVolumeTypeContainer, poolID)
 			if err == nil {
 				logger.Warnf("Storage volumes database already contains an entry for the snapshot")
-				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
+				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, db.StoragePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
 				if err != nil {
 					return err
 				}
 			} else if err == db.ErrNoSuchObject {
 				// Insert storage volumes for containers into the database.
-				_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", storagePoolVolumeTypeContainer, false, poolID, snapshotPoolVolumeConfig)
+				_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", db.StoragePoolVolumeTypeContainer, false, poolID, snapshotPoolVolumeConfig)
 				if err != nil {
 					logger.Errorf("Could not insert a storage volume for snapshot \"%s\"", cs)
 					return err
@@ -1483,16 +1483,16 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, storagePoolVolumeTypeImage, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, db.StoragePoolVolumeTypeImage, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the image")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, db.StoragePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", img, "", storagePoolVolumeTypeImage, false, poolID, imagePoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", img, "", db.StoragePoolVolumeTypeImage, false, poolID, imagePoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for image \"%s\"", img)
 				return err
@@ -1544,7 +1544,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 			// This image didn't exist as a logical volume on the
 			// old LXD instance so we need to kick it from the
 			// storage volumes database for this pool.
-			err := d.cluster.StoragePoolVolumeDelete("default", img, storagePoolVolumeTypeImage, poolID)
+			err := d.cluster.StoragePoolVolumeDelete("default", img, db.StoragePoolVolumeTypeImage, poolID)
 			if err != nil {
 				return err
 			}
@@ -1675,16 +1675,16 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, storagePoolVolumeTypeContainer, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, db.StoragePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the container")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, db.StoragePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", storagePoolVolumeTypeContainer, false, poolID, containerPoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", ct, "", db.StoragePoolVolumeTypeContainer, false, poolID, containerPoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for container \"%s\"", ct)
 				return err
@@ -1761,16 +1761,16 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
 				return err
 			}
 
-			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, storagePoolVolumeTypeContainer, poolID)
+			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, db.StoragePoolVolumeTypeContainer, poolID)
 			if err == nil {
 				logger.Warnf("Storage volumes database already contains an entry for the snapshot")
-				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
+				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, db.StoragePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
 				if err != nil {
 					return err
 				}
 			} else if err == db.ErrNoSuchObject {
 				// Insert storage volumes for containers into the database.
-				_, err := d.cluster.StoragePoolVolumeCreate("default", cs, "", storagePoolVolumeTypeContainer, false, poolID, snapshotPoolVolumeConfig)
+				_, err := d.cluster.StoragePoolVolumeCreate("default", cs, "", db.StoragePoolVolumeTypeContainer, false, poolID, snapshotPoolVolumeConfig)
 				if err != nil {
 					logger.Errorf("Could not insert a storage volume for snapshot \"%s\"", cs)
 					return err
@@ -1817,16 +1817,16 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
 			return err
 		}
 
-		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, storagePoolVolumeTypeImage, poolID)
+		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, db.StoragePoolVolumeTypeImage, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the image")
-			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, db.StoragePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
 			if err != nil {
 				return err
 			}
 		} else if err == db.ErrNoSuchObject {
 			// Insert storage volumes for containers into the database.
-			_, err := d.cluster.StoragePoolVolumeCreate("default", img, "", storagePoolVolumeTypeImage, false, poolID, imagePoolVolumeConfig)
+			_, err := d.cluster.StoragePoolVolumeCreate("default", img, "", db.StoragePoolVolumeTypeImage, false, poolID, imagePoolVolumeConfig)
 			if err != nil {
 				logger.Errorf("Could not insert a storage volume for image \"%s\"", img)
 				return err
@@ -3025,7 +3025,7 @@ func patchStorageApiPermissions(name string, d *Daemon) error {
 			return err
 		}
 
-		volumes, err := d.cluster.StoragePoolNodeVolumesGetType(storagePoolVolumeTypeCustom, poolID)
+		volumes, err := d.cluster.StoragePoolNodeVolumesGetType(db.StoragePoolVolumeTypeCustom, poolID)
 		if err != nil && err != db.ErrNoSuchObject {
 			return err
 		}
diff --git a/lxd/storage_pools_utils.go b/lxd/storage_pools_utils.go
index c8721f0c16..a069b8b200 100644
--- a/lxd/storage_pools_utils.go
+++ b/lxd/storage_pools_utils.go
@@ -29,7 +29,7 @@ func storagePoolUpdate(state *state.State, name, newDescription string, newConfi
 // /1.0/profiles/default
 func storagePoolUsedByGet(state *state.State, project string, poolID int64, poolName string) ([]string, error) {
 	// Retrieve all non-custom volumes that exist on this storage pool.
-	volumes, err := state.Cluster.StoragePoolNodeVolumesGet(project, poolID, []int{storagePoolVolumeTypeContainer, storagePoolVolumeTypeImage, storagePoolVolumeTypeCustom, storagePoolVolumeTypeVM})
+	volumes, err := state.Cluster.StoragePoolNodeVolumesGet(project, poolID, []int{db.StoragePoolVolumeTypeContainer, db.StoragePoolVolumeTypeImage, db.StoragePoolVolumeTypeCustom, db.StoragePoolVolumeTypeVM})
 	if err != nil && err != db.ErrNoSuchObject {
 		return []string{}, err
 	}
diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go
index 6cd6bcf2fc..08d97662e4 100644
--- a/lxd/storage_volumes.go
+++ b/lxd/storage_volumes.go
@@ -108,7 +108,7 @@ func storagePoolVolumesGet(d *Daemon, r *http.Request) response.Response {
 		return response.SmartError(err)
 	}
 
-	imageVolumes, err := d.cluster.StoragePoolVolumesGet("default", poolID, []int{storagePoolVolumeTypeImage})
+	imageVolumes, err := d.cluster.StoragePoolVolumesGet("default", poolID, []int{db.StoragePoolVolumeTypeImage})
 	if err != nil && err != db.ErrNoSuchObject {
 		return response.SmartError(err)
 	}
@@ -1079,9 +1079,9 @@ func storagePoolVolumeTypeDelete(d *Daemon, r *http.Request, volumeTypeName stri
 	}
 
 	switch volumeType {
-	case storagePoolVolumeTypeCustom:
+	case db.StoragePoolVolumeTypeCustom:
 		// allowed
-	case storagePoolVolumeTypeImage:
+	case db.StoragePoolVolumeTypeImage:
 		// allowed
 	default:
 		return response.BadRequest(fmt.Errorf("Storage volumes of type %q cannot be deleted with the storage API", volumeTypeName))
@@ -1093,7 +1093,7 @@ func storagePoolVolumeTypeDelete(d *Daemon, r *http.Request, volumeTypeName stri
 	}
 
 	if len(volumeUsedBy) > 0 {
-		if len(volumeUsedBy) != 1 || volumeType != storagePoolVolumeTypeImage || volumeUsedBy[0] != fmt.Sprintf("/%s/images/%s", version.APIVersion, volumeName) {
+		if len(volumeUsedBy) != 1 || volumeType != db.StoragePoolVolumeTypeImage || volumeUsedBy[0] != fmt.Sprintf("/%s/images/%s", version.APIVersion, volumeName) {
 			return response.BadRequest(fmt.Errorf("The storage volume is still in use"))
 		}
 	}
@@ -1104,9 +1104,9 @@ func storagePoolVolumeTypeDelete(d *Daemon, r *http.Request, volumeTypeName stri
 	}
 
 	switch volumeType {
-	case storagePoolVolumeTypeCustom:
+	case db.StoragePoolVolumeTypeCustom:
 		err = pool.DeleteCustomVolume(volumeName, nil)
-	case storagePoolVolumeTypeImage:
+	case db.StoragePoolVolumeTypeImage:
 		err = pool.DeleteImage(volumeName, nil)
 	default:
 		return response.BadRequest(fmt.Errorf(`Storage volumes of type %q cannot be deleted with the storage api`, volumeTypeName))
diff --git a/lxd/storage_volumes_snapshot.go b/lxd/storage_volumes_snapshot.go
index 0325936ba2..dca4382915 100644
--- a/lxd/storage_volumes_snapshot.go
+++ b/lxd/storage_volumes_snapshot.go
@@ -243,7 +243,7 @@ func storagePoolVolumeSnapshotTypePost(d *Daemon, r *http.Request) response.Resp
 	}
 
 	// Check that the storage volume type is valid.
-	if volumeType != storagePoolVolumeTypeCustom {
+	if volumeType != db.StoragePoolVolumeTypeCustom {
 		return response.BadRequest(fmt.Errorf("invalid storage volume type %s", volumeTypeName))
 	}
 
@@ -304,7 +304,7 @@ func storagePoolVolumeSnapshotTypeGet(d *Daemon, r *http.Request) response.Respo
 	}
 
 	// Check that the storage volume type is valid.
-	if volumeType != storagePoolVolumeTypeCustom {
+	if volumeType != db.StoragePoolVolumeTypeCustom {
 		return response.BadRequest(fmt.Errorf("invalid storage volume type %s", volumeTypeName))
 	}
 
@@ -361,7 +361,7 @@ func storagePoolVolumeSnapshotTypePut(d *Daemon, r *http.Request) response.Respo
 	}
 
 	// Check that the storage volume type is valid.
-	if volumeType != storagePoolVolumeTypeCustom {
+	if volumeType != db.StoragePoolVolumeTypeCustom {
 		return response.BadRequest(fmt.Errorf("Invalid storage volume type %s", volumeTypeName))
 	}
 
@@ -441,7 +441,7 @@ func storagePoolVolumeSnapshotTypeDelete(d *Daemon, r *http.Request) response.Re
 	}
 
 	// Check that the storage volume type is valid.
-	if volumeType != storagePoolVolumeTypeCustom {
+	if volumeType != db.StoragePoolVolumeTypeCustom {
 		return response.BadRequest(fmt.Errorf("invalid storage volume type %s", volumeTypeName))
 	}
 
diff --git a/lxd/storage_volumes_utils.go b/lxd/storage_volumes_utils.go
index e4abfd2d77..bf2e413a72 100644
--- a/lxd/storage_volumes_utils.go
+++ b/lxd/storage_volumes_utils.go
@@ -12,15 +12,6 @@ import (
 	"github.com/lxc/lxd/shared/version"
 )
 
-// XXX: backward compatible declarations, introduced when the db code was
-//      extracted to its own package. We should eventually clean this up.
-const (
-	storagePoolVolumeTypeContainer = db.StoragePoolVolumeTypeContainer
-	storagePoolVolumeTypeVM        = db.StoragePoolVolumeTypeVM
-	storagePoolVolumeTypeImage     = db.StoragePoolVolumeTypeImage
-	storagePoolVolumeTypeCustom    = db.StoragePoolVolumeTypeCustom
-)
-
 const (
 	storagePoolVolumeTypeNameContainer = db.StoragePoolVolumeTypeNameContainer
 	storagePoolVolumeTypeNameVM        = db.StoragePoolVolumeTypeNameVM
@@ -38,8 +29,8 @@ const (
 	storagePoolVolumeAPIEndpointCustom     string = "custom"
 )
 
-var supportedVolumeTypesExceptImages = []int{storagePoolVolumeTypeContainer, storagePoolVolumeTypeVM, storagePoolVolumeTypeCustom}
-var supportedVolumeTypes = append(supportedVolumeTypesExceptImages, storagePoolVolumeTypeImage)
+var supportedVolumeTypesExceptImages = []int{db.StoragePoolVolumeTypeContainer, db.StoragePoolVolumeTypeVM, db.StoragePoolVolumeTypeCustom}
+var supportedVolumeTypes = append(supportedVolumeTypesExceptImages, db.StoragePoolVolumeTypeImage)
 
 func init() {
 	storagePools.VolumeUsedByInstancesWithProfiles = storagePoolVolumeUsedByRunningInstancesWithProfilesGet
@@ -62,13 +53,13 @@ func storagePoolVolumeTypeNameToAPIEndpoint(volumeTypeName string) (string, erro
 
 func storagePoolVolumeTypeToAPIEndpoint(volumeType int) (string, error) {
 	switch volumeType {
-	case storagePoolVolumeTypeContainer:
+	case db.StoragePoolVolumeTypeContainer:
 		return storagePoolVolumeAPIEndpointContainers, nil
-	case storagePoolVolumeTypeVM:
+	case db.StoragePoolVolumeTypeVM:
 		return storagePoolVolumeAPIEndpointVMs, nil
-	case storagePoolVolumeTypeImage:
+	case db.StoragePoolVolumeTypeImage:
 		return storagePoolVolumeAPIEndpointImages, nil
-	case storagePoolVolumeTypeCustom:
+	case db.StoragePoolVolumeTypeCustom:
 		return storagePoolVolumeAPIEndpointCustom, nil
 	}
 

From 1eb809573ed0a870e4fafeaa48a2fd0fc76424b8 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 15:44:42 +0000
Subject: [PATCH 62/62] lxd: Removes storagePoolVolumeType constants

Replaces with db.storagePoolVolumeType constants.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage_volumes.go       |  6 +++---
 lxd/storage_volumes_utils.go | 23 ++++++++---------------
 2 files changed, 11 insertions(+), 18 deletions(-)

diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go
index 08d97662e4..1c5a63db55 100644
--- a/lxd/storage_volumes.go
+++ b/lxd/storage_volumes.go
@@ -274,7 +274,7 @@ func storagePoolVolumesTypePost(d *Daemon, r *http.Request) response.Response {
 	// We currently only allow to create storage volumes of type
 	// storagePoolVolumeTypeCustom. So check, that nothing else was
 	// requested.
-	if req.Type != storagePoolVolumeTypeNameCustom {
+	if req.Type != db.StoragePoolVolumeTypeNameCustom {
 		return response.BadRequest(fmt.Errorf(`Currently not allowed to create `+
 			`storage volumes of type %s`, req.Type))
 	}
@@ -376,7 +376,7 @@ func storagePoolVolumesPost(d *Daemon, r *http.Request) response.Response {
 	// We currently only allow to create storage volumes of type
 	// storagePoolVolumeTypeCustom. So check, that nothing else was
 	// requested.
-	if req.Type != storagePoolVolumeTypeNameCustom {
+	if req.Type != db.StoragePoolVolumeTypeNameCustom {
 		return response.BadRequest(fmt.Errorf(`Currently not allowed to create `+
 			`storage volumes of type %s`, req.Type))
 	}
@@ -522,7 +522,7 @@ func storagePoolVolumeTypePost(d *Daemon, r *http.Request, volumeTypeName string
 
 	// We currently only allow to create storage volumes of type storagePoolVolumeTypeCustom.
 	// So check, that nothing else was requested.
-	if volumeTypeName != storagePoolVolumeTypeNameCustom {
+	if volumeTypeName != db.StoragePoolVolumeTypeNameCustom {
 		return response.BadRequest(fmt.Errorf("Renaming storage volumes of type %s is not allowed", volumeTypeName))
 	}
 
diff --git a/lxd/storage_volumes_utils.go b/lxd/storage_volumes_utils.go
index bf2e413a72..f478a519e9 100644
--- a/lxd/storage_volumes_utils.go
+++ b/lxd/storage_volumes_utils.go
@@ -12,13 +12,6 @@ import (
 	"github.com/lxc/lxd/shared/version"
 )
 
-const (
-	storagePoolVolumeTypeNameContainer = db.StoragePoolVolumeTypeNameContainer
-	storagePoolVolumeTypeNameVM        = db.StoragePoolVolumeTypeNameVM
-	storagePoolVolumeTypeNameImage     = db.StoragePoolVolumeTypeNameImage
-	storagePoolVolumeTypeNameCustom    = db.StoragePoolVolumeTypeNameCustom
-)
-
 // Leave the string type in here! This guarantees that go treats this is as a
 // typed string constant. Removing it causes go to treat these as untyped string
 // constants which is not what we want.
@@ -38,13 +31,13 @@ func init() {
 
 func storagePoolVolumeTypeNameToAPIEndpoint(volumeTypeName string) (string, error) {
 	switch volumeTypeName {
-	case storagePoolVolumeTypeNameContainer:
+	case db.StoragePoolVolumeTypeNameContainer:
 		return storagePoolVolumeAPIEndpointContainers, nil
-	case storagePoolVolumeTypeNameVM:
+	case db.StoragePoolVolumeTypeNameVM:
 		return storagePoolVolumeAPIEndpointVMs, nil
-	case storagePoolVolumeTypeNameImage:
+	case db.StoragePoolVolumeTypeNameImage:
 		return storagePoolVolumeAPIEndpointImages, nil
-	case storagePoolVolumeTypeNameCustom:
+	case db.StoragePoolVolumeTypeNameCustom:
 		return storagePoolVolumeAPIEndpointCustom, nil
 	}
 
@@ -95,7 +88,7 @@ func storagePoolVolumeUpdateUsers(d *Daemon, oldPoolName string,
 
 			dir, file := filepath.Split(devices[k]["source"])
 			dir = filepath.Clean(dir)
-			if dir != storagePoolVolumeTypeNameCustom {
+			if dir != db.StoragePoolVolumeTypeNameCustom {
 				continue
 			}
 
@@ -114,7 +107,7 @@ func storagePoolVolumeUpdateUsers(d *Daemon, oldPoolName string,
 			if oldVolumeName != newVolumeName {
 				newSource := newVolumeName
 				if dir != "" {
-					newSource = fmt.Sprintf("%s/%s", storagePoolVolumeTypeNameCustom, newVolumeName)
+					newSource = fmt.Sprintf("%s/%s", db.StoragePoolVolumeTypeNameCustom, newVolumeName)
 				}
 				devices[k]["source"] = newSource
 			}
@@ -171,7 +164,7 @@ func storagePoolVolumeUpdateUsers(d *Daemon, oldPoolName string,
 
 			dir, file := filepath.Split(profile.Devices[k]["source"])
 			dir = filepath.Clean(dir)
-			if dir != storagePoolVolumeTypeNameCustom {
+			if dir != db.StoragePoolVolumeTypeNameCustom {
 				continue
 			}
 
@@ -190,7 +183,7 @@ func storagePoolVolumeUpdateUsers(d *Daemon, oldPoolName string,
 			if oldVolumeName != newVolumeName {
 				newSource := newVolumeName
 				if dir != "" {
-					newSource = fmt.Sprintf("%s/%s", storagePoolVolumeTypeNameCustom, newVolumeName)
+					newSource = fmt.Sprintf("%s/%s", db.StoragePoolVolumeTypeNameCustom, newVolumeName)
 				}
 				profile.Devices[k]["source"] = newSource
 			}


More information about the lxc-devel mailing list