[lxc-devel] [lxd/master] Instance: Moves containerLXC to instance/drivers package as LXC

tomponline on Github lxc-bot at linuxcontainers.org
Fri Feb 28 11:16:41 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200228/b3963c63/attachment-0001.bin>
-------------- next part --------------
From 47dcd2e1332fa81d7e7a4b9393684c35dfb2f929 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/50] 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 dfa57b846f873353ea76829b5928e2716b1e16ae 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/50] 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 3a1c543427738f94a5451b968126554525bc6c56 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/50] 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 9d82b17a2775186ff6dea270442b010808005946 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/50] 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 29c6701690cc448199904fb100fa1bf48bb13ba3 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/50] lxd/api/internal: instanceDrivers.LXC usage

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

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 9d1dab7c1a..a8a9a04bf5 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -22,6 +22,7 @@ import (
 	"github.com/lxc/lxd/lxd/db/query"
 	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/project"
 	"github.com/lxc/lxd/lxd/response"
@@ -135,7 +136,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.(*instanceDrivers.LXC)
 	err = c.OnStart()
 	if err != nil {
 		logger.Error("The start hook failed", log.Ctx{"container": c.Name(), "err": err})
@@ -166,7 +167,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.(*instanceDrivers.LXC)
 	err = c.OnStopNS(target, netns)
 	if err != nil {
 		logger.Error("The stopns hook failed", log.Ctx{"container": c.Name(), "err": err})
@@ -196,7 +197,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.(*instanceDrivers.LXC)
 	err = c.OnStop(target)
 	if err != nil {
 		logger.Error("The stop hook failed", log.Ctx{"container": c.Name(), "err": err})

From efec58877bfcd643dcf98492dbdab84fba10c354 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/50] lxd/container: instanceDrivers.CriuMigrationArgs usage

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

diff --git a/lxd/container.go b/lxd/container.go
index 4b521fbef0..68c3cce7e7 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -21,6 +21,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"
 	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/lxd/state"
@@ -384,14 +385,14 @@ 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 := instanceDrivers.CriuMigrationArgs{
+			Cmd:          lxc.MIGRATE_DUMP,
+			StateDir:     stateDir,
+			Function:     "snapshot",
+			Stop:         false,
+			ActionScript: false,
+			DumpDir:      "",
+			PreDumpDir:   "",
 		}
 
 		c := sourceInstance.(*containerLXC)

From a52ffbfa83f4698065080e4102efaad603db378b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 27 Feb 2020 17:40:33 +0000
Subject: [PATCH 07/50] lxd/container: instanceDrivers.LXC usage

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

diff --git a/lxd/container.go b/lxd/container.go
index 68c3cce7e7..e02d4d1138 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -395,7 +395,7 @@ func instanceCreateAsSnapshot(s *state.State, args db.InstanceArgs, sourceInstan
 			PreDumpDir:   "",
 		}
 
-		c := sourceInstance.(*containerLXC)
+		c := sourceInstance.(*instanceDrivers.LXC)
 		err = c.Migrate(&criuMigrationArgs)
 		if err != nil {
 			os.RemoveAll(sourceInstance.StatePath())

From 611098665d306c4a79671649f826bdeb30d589f3 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 08/50] lxd/container/console: instanceDrivers.LXC usage

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

diff --git a/lxd/container_console.go b/lxd/container_console.go
index e461a9f7ff..a3648eb099 100644
--- a/lxd/container_console.go
+++ b/lxd/container_console.go
@@ -17,6 +17,7 @@ import (
 	"github.com/lxc/lxd/lxd/cluster"
 	"github.com/lxc/lxd/lxd/db"
 	"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/operations"
 	"github.com/lxc/lxd/lxd/response"
@@ -354,7 +355,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.(*instanceDrivers.LXC)
 	ent := response.FileResponseEntry{}
 	if !c.IsRunning() {
 		// Hand back the contents of the console ringbuffer logfile.
@@ -408,7 +409,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.(*instanceDrivers.LXC)
 
 	truncateConsoleLogFile := func(path string) error {
 		// Check that this is a regular file. We don't want to try and unlink

From 14ba261f1cdd90e819b8dd20016e5d7e2bf0c287 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 09/50] lxd/container/exec: instanceDrivers.LXC usage

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

diff --git a/lxd/container_exec.go b/lxd/container_exec.go
index 2302ee54b3..161ace4958 100644
--- a/lxd/container_exec.go
+++ b/lxd/container_exec.go
@@ -18,6 +18,7 @@ import (
 	"github.com/lxc/lxd/lxd/cluster"
 	"github.com/lxc/lxd/lxd/db"
 	"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/operations"
 	"github.com/lxc/lxd/lxd/response"
@@ -426,7 +427,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.(*instanceDrivers.LXC)
 			idmapset, err := c.CurrentIdmap()
 			if err != nil {
 				return response.InternalError(err)

From a6fafdbdada5c7d92d6317064106bfd9b21c997d 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 10/50] 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 28a7035c11407ea4ef50909152eb84d3806e9737 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 11/50] lxd/container/test: instanceDrivers.LXC 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..41335c5d90 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.(*instanceDrivers.LXC).NextIdmap()
 	suite.Req.Nil(err)
-	map2, err := c2.(*containerLXC).NextIdmap()
+	map2, err := c2.(*instanceDrivers.LXC).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.(*instanceDrivers.LXC).NextIdmap()
 	suite.Req.Nil(err)
-	map2, err := c2.(*containerLXC).NextIdmap()
+	map2, err := c2.(*instanceDrivers.LXC).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.(*instanceDrivers.LXC).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.(*instanceDrivers.LXC).NextIdmap()
 		suite.Req.Nil(err)
 
 		maps = append(maps, m)

From 1dc48f2bf3958401de6c3210880e8f82ef73a22d 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 12/50] 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 99fcc06b826d4f904cf330a3e35552db09262411 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 13/50] 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 9cfccd7c99b45c4ca92cf86855b7a544a4f61b0f 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 14/50] 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 6739a63289f25c13d3cb98eeccf5040b91000bd3 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 15/50] lxd/devlxd: instanceDrivers.LXC usage

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

diff --git a/lxd/devlxd.go b/lxd/devlxd.go
index 7eb41c9e98..11f67e8a63 100644
--- a/lxd/devlxd.go
+++ b/lxd/devlxd.go
@@ -18,6 +18,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/daemon"
 	"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/project"
 	"github.com/lxc/lxd/lxd/state"
@@ -308,7 +309,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) (*instanceDrivers.LXC, 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,7 +356,7 @@ func findContainerForPid(pid int32, s *state.State) (*containerLXC, error) {
 				return nil, fmt.Errorf("Instance is not container type")
 			}
 
-			c := inst.(*containerLXC)
+			c := inst.(*instanceDrivers.LXC)
 			return c, nil
 		}
 
@@ -405,7 +406,7 @@ func findContainerForPid(pid int32, s *state.State) (*containerLXC, error) {
 		}
 
 		if origPidNs == pidNs {
-			return inst.(*containerLXC), nil
+			return inst.(*instanceDrivers.LXC), nil
 		}
 	}
 

From b7d9644237a663408f6abb1a7d9e78674298576d 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 16/50] lxd/instance/drivers/driver/lxc: Renames containerLXC
 to LXC

Requires uppercase LXC so it is exported as some other parts of the codebase still need to access this type directly.

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

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 032dfca40d..174cbd16e4 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,
@@ -428,7 +427,7 @@ func containerLXCInstantiate(s *state.State, args db.InstanceArgs, expandedDevic
 }
 
 // The LXC container driver
-type containerLXC struct {
+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
@@ -1273,7 +1272,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 {
@@ -1288,7 +1287,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
 
@@ -1310,7 +1309,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
@@ -1322,7 +1321,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
@@ -1387,7 +1386,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)
@@ -1415,7 +1414,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
@@ -1438,7 +1437,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" {
@@ -1467,7 +1466,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
@@ -1482,7 +1481,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.
@@ -1551,7 +1550,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 {
@@ -1612,7 +1611,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
@@ -1659,7 +1658,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.
@@ -1679,7 +1678,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)
@@ -1694,7 +1693,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 {
@@ -1707,7 +1706,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)
 
@@ -1744,7 +1743,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
@@ -1805,7 +1804,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)
@@ -1819,7 +1818,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)
@@ -1884,7 +1883,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{}
 
@@ -2245,7 +2244,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
@@ -2267,7 +2266,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
@@ -2419,7 +2418,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
 
@@ -2476,7 +2475,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 {
@@ -2509,7 +2508,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
@@ -2650,7 +2649,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
@@ -2713,7 +2712,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})
@@ -2728,7 +2727,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})
@@ -2793,7 +2792,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
 
@@ -2843,7 +2842,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)
@@ -2856,7 +2855,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,
@@ -2909,7 +2908,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,
@@ -2963,7 +2962,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
 	}
@@ -2984,11 +2983,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)
 
@@ -3047,7 +3046,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")
 	}
@@ -3105,7 +3104,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
@@ -3129,7 +3128,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() {
@@ -3164,7 +3163,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 {
@@ -3186,7 +3185,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.
@@ -3358,7 +3357,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()
@@ -3374,7 +3373,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,
@@ -3488,7 +3487,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,
@@ -3634,7 +3633,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 {
@@ -3650,7 +3649,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 {
@@ -3670,7 +3669,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.") {
@@ -3708,7 +3707,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"
@@ -4431,7 +4430,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.
@@ -4486,7 +4485,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,
@@ -4733,18 +4732,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 *CriuMigrationArgs) error {
 	ctxMap := log.Ctx{
 		"project":      c.project,
 		"name":         c.name,
@@ -4952,7 +4940,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")
@@ -4961,7 +4949,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) {
@@ -5103,7 +5091,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
@@ -5151,7 +5139,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 {
@@ -5280,7 +5268,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 {
@@ -5376,7 +5364,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
@@ -5437,7 +5425,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{
@@ -5490,7 +5478,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
@@ -5499,7 +5487,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{}
 
@@ -5581,7 +5569,7 @@ func (c *containerLXC) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os
 		return nil, err
 	}
 
-	instCmd := &ContainerLXCCmd{
+	instCmd := &lxcCmd{
 		cmd:              &cmd,
 		attachedChildPid: attachedPid,
 	}
@@ -5589,7 +5577,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
@@ -5619,7 +5607,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() {
@@ -5653,7 +5641,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 {
@@ -5703,7 +5691,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()
@@ -5761,7 +5749,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 {
@@ -5811,8 +5799,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
 	}
@@ -5827,7 +5815,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
@@ -5837,12 +5825,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
@@ -5866,12 +5854,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
@@ -5895,7 +5883,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
@@ -5953,7 +5941,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 == "" {
@@ -5972,7 +5960,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)
 	}
@@ -5980,7 +5968,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 {
@@ -6012,7 +6000,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")
 	}
@@ -6067,7 +6055,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
@@ -6099,7 +6087,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()
 
@@ -6258,7 +6246,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
@@ -6292,7 +6280,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
@@ -6345,23 +6333,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()
 	}
@@ -6374,44 +6362,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 {
@@ -6421,42 +6409,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
@@ -6466,27 +6454,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()
@@ -6495,42 +6483,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.
@@ -6542,7 +6530,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
@@ -6552,11 +6540,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
 	}
@@ -6565,7 +6553,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
 	}
@@ -6582,7 +6570,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" {
@@ -6632,7 +6620,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 {
@@ -6682,7 +6670,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
@@ -6717,7 +6705,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
@@ -6752,7 +6740,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
@@ -6803,7 +6791,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 1742f3980d7f74431466933446dc9a1d4b479561 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 17/50] 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 174cbd16e4..da39ab875d 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 47193669aae5feccfb174d21d3e12e75c14a9bbe 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 18/50] 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 da39ab875d..e819bb72c1 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
 	}
@@ -1559,7 +1559,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
 		}
@@ -2955,18 +2955,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)
 
@@ -6113,7 +6113,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()
 
@@ -6745,12 +6745,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 112dd9119901b7254bb8cb8e03239310d3ca9b0b 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 19/50] 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 e819bb72c1..daae22b716 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 356d0eafc1f9f3debba0ff4b1a611492c13265f6 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 20/50] lxd/instance/drivers/driver/lxc: Adds CriuMigrationArgs
 and devLxdSendEvent

Updates usage.

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

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index daae22b716..46a6891196 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -417,6 +417,18 @@ func lxcInstantiate(s *state.State, args db.InstanceArgs, expandedDevices device
 	return c
 }
 
+// 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
+}
+
 // The LXC container driver
 type LXC struct {
 	// Properties
@@ -1262,6 +1274,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.
@@ -2302,13 +2323,13 @@ func (c *LXC) Start(stateful bool) error {
 		}
 
 		criuMigrationArgs := CriuMigrationArgs{
-			cmd:          lxc.MIGRATE_RESTORE,
-			stateDir:     c.StatePath(),
-			function:     "snapshot",
-			stop:         false,
-			actionScript: false,
-			dumpDir:      "",
-			preDumpDir:   "",
+			Cmd:          liblxc.MIGRATE_RESTORE,
+			StateDir:     c.StatePath(),
+			Function:     "snapshot",
+			Stop:         false,
+			ActionScript: false,
+			DumpDir:      "",
+			PreDumpDir:   "",
 		}
 
 		err := c.Migrate(&criuMigrationArgs)
@@ -2538,13 +2559,13 @@ func (c *LXC) Stop(stateful bool) error {
 		}
 
 		criuMigrationArgs := CriuMigrationArgs{
-			cmd:          lxc.MIGRATE_DUMP,
-			stateDir:     stateDir,
-			function:     "snapshot",
-			stop:         true,
-			actionScript: false,
-			dumpDir:      "",
-			preDumpDir:   "",
+			Cmd:          liblxc.MIGRATE_DUMP,
+			StateDir:     stateDir,
+			Function:     "snapshot",
+			Stop:         true,
+			ActionScript: false,
+			DumpDir:      "",
+			PreDumpDir:   "",
 		}
 
 		// Checkpoint
@@ -3302,13 +3323,13 @@ func (c *LXC) Restore(sourceContainer instance.Instance, stateful bool) error {
 		c.stateful = true
 
 		criuMigrationArgs := CriuMigrationArgs{
-			cmd:          lxc.MIGRATE_RESTORE,
-			stateDir:     c.StatePath(),
-			function:     "snapshot",
-			stop:         false,
-			actionScript: false,
-			dumpDir:      "",
-			preDumpDir:   "",
+			Cmd:          liblxc.MIGRATE_RESTORE,
+			StateDir:     c.StatePath(),
+			Function:     "snapshot",
+			Stop:         false,
+			ActionScript: false,
+			DumpDir:      "",
+			PreDumpDir:   "",
 		}
 
 		// Checkpoint.
@@ -4357,7 +4378,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
 			}
@@ -4371,7 +4392,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
 			}
@@ -4384,7 +4405,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
 			}
@@ -4397,7 +4418,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
 			}
@@ -4730,11 +4751,11 @@ func (c *LXC) Migrate(args *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 {
@@ -4744,18 +4765,18 @@ func (c *LXC) Migrate(args *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()
@@ -4772,14 +4793,14 @@ func (c *LXC) Migrate(args *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 {
@@ -4809,11 +4830,11 @@ func (c *LXC) Migrate(args *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()
@@ -4829,8 +4850,8 @@ func (c *LXC) Migrate(args *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(
@@ -4851,16 +4872,16 @@ func (c *LXC) Migrate(args *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
@@ -4873,12 +4894,12 @@ func (c *LXC) Migrate(args *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
@@ -4889,27 +4910,27 @@ func (c *LXC) Migrate(args *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})
 	}
@@ -4918,7 +4939,7 @@ func (c *LXC) Migrate(args *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 b25dc0108418f80d335147ba63ac4eb0d3b9b750 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 21/50] 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 46a6891196..61312b8b5f 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -1298,6 +1298,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 d232d9c50f72a9d8dd9709075ec26fdfd7e874e8 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 22/50] 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 61312b8b5f..46a036bd2e 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -1867,56 +1867,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
@@ -1976,9 +1926,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)
 			}
@@ -1992,9 +1942,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 155dbc2c2f167d4a8e1dee18fd30641d290b1766 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 23/50] 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 46a036bd2e..1c22228d5d 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -2261,7 +2261,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 7366db5a0cc31a5b65279797cc86af82e3a806b8 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 24/50] 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 1c22228d5d..7054d2cb92 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -6784,3 +6784,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 2c89a608304dd1b4e6733fbf79f2fa90960cd90b 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 25/50] 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 116eca7e38310187176a84567f1937d083f44dcf 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 26/50] 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 c6a8320241a52b08c7bc4cd9caa9cc822a0598c2 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 27/50] 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 1c9b9d0ef5f2a2e3456ec6f0bdc2016288f01958 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 28/50] 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 08456eb3c131d5257d2ed4c048758ca3ba5b3fc7 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 29/50] lxd/migrate/container:
 instanceDrivers.CriuMigrationArgs and instanceDrivers.LXC usage

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

diff --git a/lxd/migrate_container.go b/lxd/migrate_container.go
index 70751a70a7..dba04e7d9b 100644
--- a/lxd/migrate_container.go
+++ b/lxd/migrate_container.go
@@ -17,6 +17,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/db"
 	"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/migration"
 	"github.com/lxc/lxd/lxd/operations"
@@ -129,22 +130,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 := instanceDrivers.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.(*instanceDrivers.LXC)
 	err := c.Migrate(&criuMigrationArgs)
 
 	if err != nil {
@@ -241,14 +242,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 := instanceDrivers.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 +260,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.(*instanceDrivers.LXC)
 	err := c.Migrate(&criuMigrationArgs)
 	if err != nil {
 		return final, err
@@ -337,7 +338,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.(*instanceDrivers.LXC)
 
 	var offerHeader migration.MigrationHeader
 	var poolMigrationTypes []migration.Type
@@ -609,14 +610,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 := instanceDrivers.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 +637,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 := instanceDrivers.CriuMigrationArgs{
+				Cmd:          lxc.MIGRATE_DUMP,
+				StateDir:     checkpointDir,
+				Function:     "migration",
+				Stop:         true,
+				ActionScript: false,
+				DumpDir:      "final",
+				PreDumpDir:   "",
 			}
 
 			err = ct.Migrate(&criuMigrationArgs)
@@ -1044,7 +1045,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.(*instanceDrivers.LXC)
 				err = resetContainerDiskIdmap(ct, srcIdmap)
 				if err != nil {
 					fsTransfer <- err
@@ -1122,20 +1123,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 := instanceDrivers.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.(*instanceDrivers.LXC)
 				err = ct.Migrate(&criuMigrationArgs)
 				if err != nil {
 					restore <- err

From 97f6c1b99a561d8d6bca4df007eddf91bf23a436 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 30/50] lxd/patches: Updates patchContainerConfigRegen to use
 LXC.SaveConfigFile()

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

diff --git a/lxd/patches.go b/lxd/patches.go
index bd13a029eb..beb4c0c0a4 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"
+	instanceDrivers "github.com/lxc/lxd/lxd/instance/drivers"
 	"github.com/lxc/lxd/lxd/rsync"
 	driver "github.com/lxc/lxd/lxd/storage"
 	storagePools "github.com/lxc/lxd/lxd/storage"
@@ -2068,34 +2069,24 @@ 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() {
+		if !inst.IsRunning() {
 			continue
 		}
 
-		lxcCt, ok := c.(*containerLXC)
+		c, ok := inst.(*instanceDrivers.LXC)
 		if !ok {
 			continue
 		}
 
-		err = lxcCt.initLXC(true)
+		err = c.SaveConfigFile()
 		if err != nil {
-			logger.Errorf("Failed to generate LXC config for '%s': %v", ct, err)
-			continue
-		}
-
-		// Generate the LXC config
-		configPath := filepath.Join(lxcCt.LogPath(), "lxc.conf")
-		err = lxcCt.c.SaveConfigFile(configPath)
-		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", c.Name(), err)
 		}
 	}
 

From 40dad27633a2ae4299528fad90d55e0ff48c2fe1 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 31/50] 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 beb4c0c0a4..b4a7fbca5f 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -3321,17 +3321,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 2d7f17eba1aecaf42bafa828308077df44fb9d72 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 32/50] 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 468c7d6e56af0ee7b9bac2769d2ceb3760f37ffe 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 33/50] lxd/storage: instanceDrivers.LXC usage

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

diff --git a/lxd/storage.go b/lxd/storage.go
index e0c848e8ac..3bf0a5d3df 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -11,6 +11,7 @@ import (
 	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/device"
 	"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/state"
 	storagePools "github.com/lxc/lxd/lxd/storage"
@@ -46,7 +47,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 *instanceDrivers.LXC) error {
 	// Load the DB records
 	poolID, pool, err := s.Cluster.StoragePoolGet(poolName)
 	if err != nil {
@@ -121,7 +122,7 @@ func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName
 						continue
 					}
 
-					ct := instt.(*containerLXC)
+					ct := instt.(*instanceDrivers.LXC)
 
 					var ctNextIdmap *idmap.IdmapSet
 					if ct.IsRunning() {
@@ -206,7 +207,7 @@ func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName
 	return nil
 }
 
-func resetContainerDiskIdmap(container *containerLXC, srcIdmap *idmap.IdmapSet) error {
+func resetContainerDiskIdmap(container *instanceDrivers.LXC, srcIdmap *idmap.IdmapSet) error {
 	dstIdmap, err := container.DiskIdmap()
 	if err != nil {
 		return err
@@ -332,7 +333,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.(*instanceDrivers.LXC)
 	if !ok {
 		return fmt.Errorf("Received non-LXC container instance")
 	}

From 44b7fcbb26dce5b3bf1780f33b0a7804679a2d1e 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 34/50] 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 3bf0a5d3df..50ccee93ab 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -70,7 +70,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
@@ -153,7 +153,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)
 			}
@@ -171,7 +171,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 18db5b9da6aed737ede3bf153832a41ab3557b51 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 35/50] 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 df98227c3661cab94e53c2670ad827e3c2b3434d 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 36/50] 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 d1a11dce1a6084f29afad85015998cc0608bee85 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 37/50] 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 450eb972d802e3aa5e14653296be75728fcc743d 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 38/50] 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 41335c5d90..8804213f77 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 6335777e6dcf49a727c657ebd822ee035ba9b5fc 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 39/50] lxd/instance/drivers/driver/lxc: golint fixes

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

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 7054d2cb92..48175d9148 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -429,7 +429,7 @@ type CriuMigrationArgs struct {
 	Features     liblxc.CriuFeatures
 }
 
-// The LXC container driver
+// The LXC container driver.
 type LXC struct {
 	// Properties
 	architecture int
@@ -473,6 +473,7 @@ type LXC struct {
 	expiryDate time.Time
 }
 
+// Type returns the instance type.
 func (c *LXC) Type() instancetype.Type {
 	return c.dbType
 }
@@ -2251,6 +2252,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
 
@@ -2403,6 +2405,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
@@ -2634,6 +2637,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
 
@@ -2839,7 +2843,7 @@ func (c *LXC) cleanupDevices(netns string) {
 	}
 }
 
-// Freezer functions
+// Freeze functions.
 func (c *LXC) Freeze() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
@@ -2893,6 +2897,7 @@ func (c *LXC) Freeze() error {
 	return err
 }
 
+// Unfreeze unfreezes the instance.
 func (c *LXC) Unfreeze() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
@@ -2943,8 +2948,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) {
@@ -2968,10 +2971,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)
@@ -3031,6 +3035,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")
@@ -3089,6 +3094,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 {
@@ -3113,6 +3119,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
 
@@ -3148,6 +3155,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)
@@ -3358,6 +3366,7 @@ func (c *LXC) cleanup() {
 	os.RemoveAll(c.ShmountsPath())
 }
 
+// Delete deletes the instance.
 func (c *LXC) Delete() error {
 	ctxMap := log.Ctx{
 		"project":   c.project,
@@ -3472,6 +3481,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{
@@ -3618,6 +3628,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)
@@ -3634,6 +3645,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)
@@ -3654,6 +3666,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 {
@@ -3692,6 +3705,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 == "" {
@@ -4470,6 +4484,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,
@@ -4717,6 +4732,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 *CriuMigrationArgs) error {
 	ctxMap := log.Ctx{
 		"project":      c.project,
@@ -4954,18 +4970,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
@@ -5025,7 +5041,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)
@@ -5034,7 +5050,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()
@@ -5076,6 +5092,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
@@ -5124,6 +5141,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)
@@ -5164,7 +5182,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
 
@@ -5220,7 +5238,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
 		}
 
@@ -5250,18 +5268,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
@@ -5273,7 +5292,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)
 		}
 	}
 
@@ -5288,7 +5307,7 @@ func (c *LXC) FilePush(type_ string, srcpath string, dstpath string, uid int64,
 	}
 
 	defaultMode := 0640
-	if type_ == "directory" {
+	if fileType == "directory" {
 		defaultMode = 0750
 	}
 
@@ -5302,12 +5321,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,
 	)
@@ -5349,6 +5368,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
@@ -5410,6 +5430,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)
 
@@ -5463,6 +5484,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 {
@@ -5472,6 +5494,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{}
@@ -5985,6 +6008,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")
@@ -6300,36 +6324,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"])
 }
@@ -6347,43 +6374,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)
@@ -6394,14 +6431,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 {
@@ -6411,6 +6451,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 {
@@ -6420,6 +6461,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 {
@@ -6429,36 +6471,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 {
@@ -6467,42 +6505,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
@@ -6515,6 +6561,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 {
@@ -6524,11 +6571,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
@@ -6554,7 +6602,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 {
@@ -6797,7 +6845,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 609b2fedc0008ea45e7f16c2e0b19ddf61200fb4 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 40/50] 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 48175d9148..32cea2cba9 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -1007,7 +1007,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 {
@@ -1992,7 +1992,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
 	}
 
@@ -2417,7 +2417,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()
@@ -2431,7 +2431,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()
 			}
@@ -2441,7 +2441,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()
 			}
@@ -2451,7 +2451,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()
 		}
@@ -2794,7 +2794,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})
 		}
@@ -3356,7 +3356,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
@@ -3949,7 +3949,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")
 		}
@@ -4021,7 +4021,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 058ceaac405f4ebc33b53e6c54db42821e64a73c 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 41/50] 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 8b2eb8767cd296496f71e0d5d3f8867df7975992 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 42/50] 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 54f2159114876f8cf80a21136c8b2a70ed37b304 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 43/50] 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..1442ea2f2d 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 89dab3b76dc4eabc074be7caa909415be23d9c55 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 44/50] 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 f9808e19867afdc320ab89d5be7261d6baed1270 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 45/50] 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 d008524697fbca5339cccc5aefdefa3eddf6fa28 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 46/50] 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 dba04e7d9b..b54491d86f 100644
--- a/lxd/migrate_container.go
+++ b/lxd/migrate_container.go
@@ -240,7 +240,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 := instanceDrivers.CriuMigrationArgs{
 		Cmd:          lxc.MIGRATE_PRE_DUMP,
@@ -268,7 +268,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
@@ -591,7 +590,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)
@@ -901,7 +900,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 0e40cc7ca1070ad9982683a58452f50bccb6a0e2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 28 Feb 2020 11:11:33 +0000
Subject: [PATCH 47/50] lxd/patches: patchContainerConfigRegen cont

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

diff --git a/lxd/patches.go b/lxd/patches.go
index b4a7fbca5f..b657bdd859 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -19,7 +19,7 @@ import (
 	"github.com/lxc/lxd/lxd/db/query"
 	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/rsync"
 	driver "github.com/lxc/lxd/lxd/storage"
 	storagePools "github.com/lxc/lxd/lxd/storage"
@@ -2075,18 +2075,17 @@ func patchContainerConfigRegen(name string, d *Daemon) error {
 			continue
 		}
 
-		if !inst.IsRunning() {
+		if inst.Type() != instancetype.Container {
 			continue
 		}
 
-		c, ok := inst.(*instanceDrivers.LXC)
-		if !ok {
+		if !inst.IsRunning() {
 			continue
 		}
 
-		err = c.SaveConfigFile()
+		err = inst.SaveConfigFile()
 		if err != nil {
-			logger.Errorf("Failed to save LXC config for %q: %v", c.Name(), err)
+			logger.Errorf("Failed to save LXC config for %q: %v", inst.Name(), err)
 		}
 	}
 

From dd236c1567685f3e7614654ec5b74874ca5e0461 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 48/50] 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 79e330adfbce2fd90f7ddd730057805bf71306fd 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 49/50] 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 9eb3c69cf9352f7d7982700ae89fbb1c370628b4 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 50/50] 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 != "" {


More information about the lxc-devel mailing list