The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6415

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
- Some function renames to change "container" to "instance".
- Add support for instance type to some functions.
From bf38ffa62fc0014da3e03528e4dcfb7e5b5888ae Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 10:56:01 +0000
Subject: [PATCH 01/27] lxd/api/internal: Updates use of renamed functions

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

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index cdf6dbc1b9..392b30f81f 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -871,7 +871,7 @@ func internalImport(d *Daemon, r *http.Request) 
response.Response {
        if containerErr == nil {
                // Remove the storage volume db entry for the container since
                // force was specified.
-               err := d.cluster.ContainerRemove(projectName, req.Name)
+               err := d.cluster.InstanceRemove(projectName, req.Name)
                if err != nil {
                        return response.SmartError(err)
                }
@@ -916,7 +916,7 @@ func internalImport(d *Daemon, r *http.Request) 
response.Response {
        if err != nil {
                return response.SmartError(err)
        }
-       _, err = containerCreateInternal(d.State(), db.InstanceArgs{
+       _, err = instanceCreateInternal(d.State(), db.InstanceArgs{
                Project:      projectName,
                Architecture: arch,
                BaseImage:    baseImage,
@@ -982,7 +982,7 @@ func internalImport(d *Daemon, r *http.Request) 
response.Response {
                }
 
                if snapErr == nil {
-                       err := d.cluster.ContainerRemove(projectName, snap.Name)
+                       err := d.cluster.InstanceRemove(projectName, snap.Name)
                        if err != nil {
                                return response.SmartError(err)
                        }
@@ -1022,7 +1022,7 @@ func internalImport(d *Daemon, r *http.Request) 
response.Response {
                        snap.Devices[rootDevName] = rootDev
                }
 
-               _, err = containerCreateInternal(d.State(), db.InstanceArgs{
+               _, err = instanceCreateInternal(d.State(), db.InstanceArgs{
                        Project:      projectName,
                        Architecture: arch,
                        BaseImage:    baseImage,

From 14d712908d862a74bf64775d010869a532772fa2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 10:58:31 +0000
Subject: [PATCH 02/27] lxd/container: Updates return values of instance create
 and load functions

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

diff --git a/lxd/container.go b/lxd/container.go
index 0fcb2fdea6..d3ecf525ef 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -255,9 +255,9 @@ type container interface {
 }
 
 // containerCreateAsEmpty creates an empty instance.
-func containerCreateAsEmpty(d *Daemon, args db.InstanceArgs) (container, 
error) {
+func containerCreateAsEmpty(d *Daemon, args db.InstanceArgs) (Instance, error) 
{
        // Create the container.
-       c, err := containerCreateInternal(d.State(), args)
+       c, err := instanceCreateInternal(d.State(), args)
        if err != nil {
                return nil, err
        }
@@ -402,9 +402,9 @@ func containerCreateFromBackup(s *state.State, info 
backup.Info, data io.ReadSee
        return pool, nil
 }
 
-func containerCreateEmptySnapshot(s *state.State, args db.InstanceArgs) 
(container, error) {
+func containerCreateEmptySnapshot(s *state.State, args db.InstanceArgs) 
(Instance, error) {
        // Create the snapshot
-       c, err := containerCreateInternal(s, args)
+       c, err := instanceCreateInternal(s, args)
        if err != nil {
                return nil, err
        }
@@ -544,7 +544,7 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
 
        if !refresh {
                // Create the container.
-               ct, err = containerCreateInternal(s, args)
+               ct, err = instanceCreateInternal(s, args)
                if err != nil {
                        return nil, err
                }
@@ -564,7 +564,7 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                parentStoragePool = parentLocalRootDiskDevice["pool"]
        }
 
-       csList := []*container{}
+       csList := []*Instance{}
        var snapshots []Instance
 
        if !containerOnly {
@@ -632,7 +632,7 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                        }
 
                        // Create the snapshots.
-                       cs, err := containerCreateInternal(s, csArgs)
+                       cs, err := instanceCreateInternal(s, csArgs)
                        if err != nil {
                                if !refresh {
                                        ct.Delete()
@@ -750,7 +750,7 @@ func containerCreateAsSnapshot(s *state.State, args 
db.InstanceArgs, sourceInsta
        }
 
        // Create the snapshot
-       c, err := containerCreateInternal(s, args)
+       c, err := instanceCreateInternal(s, args)
        if err != nil {
                return nil, err
        }

From eeb7dccef05d70fdcbf54c66b0c0b123fbf8ddfd Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 10:59:11 +0000
Subject: [PATCH 03/27] lxc/container: Renames containerCreateFromImage to
 instanceCreateFromImage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container.go | 41 ++++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/lxd/container.go b/lxd/container.go
index d3ecf525ef..537d524186 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -419,8 +419,8 @@ func containerCreateEmptySnapshot(s *state.State, args 
db.InstanceArgs) (Instanc
        return c, nil
 }
 
-// containerCreateFromImage creates an instance from a rootfs image.
-func containerCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op 
*operations.Operation) (container, error) {
+// instanceCreateFromImage creates an instance from a rootfs image.
+func instanceCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op 
*operations.Operation) (Instance, error) {
        s := d.State()
 
        // Get the image properties.
@@ -475,59 +475,66 @@ func containerCreateFromImage(d *Daemon, args 
db.InstanceArgs, hash string, op *
        // Set the BaseImage field (regardless of previous value).
        args.BaseImage = hash
 
-       // Create the container
-       c, err := containerCreateInternal(s, args)
+       // Create the instance.
+       inst, err := instanceCreateInternal(s, args)
        if err != nil {
-               return nil, errors.Wrap(err, "Create container")
+               return nil, errors.Wrap(err, "Create instance")
        }
 
+       revert := true
+       defer func() {
+               if !revert {
+                       return
+               }
+
+               inst.Delete()
+       }()
+
        err = s.Cluster.ImageLastAccessUpdate(hash, time.Now().UTC())
        if err != nil {
-               c.Delete()
                return nil, fmt.Errorf("Error updating image last use date: 
%s", err)
        }
 
        // Check if we can load new storage layer for pool driver type.
-       pool, err := storagePools.GetPoolByInstance(d.State(), c)
+       pool, err := storagePools.GetPoolByInstance(d.State(), inst)
        if err != storageDrivers.ErrUnknownDriver && err != 
storageDrivers.ErrNotImplemented {
                if err != nil {
                        return nil, errors.Wrap(err, "Load instance storage 
pool")
                }
 
-               err = pool.CreateInstanceFromImage(c, hash, op)
+               err = pool.CreateInstanceFromImage(inst, hash, op)
                if err != nil {
-                       c.Delete()
                        return nil, errors.Wrap(err, "Create instance from 
image")
                }
-       } else if c.Type() == instancetype.Container {
+       } else if inst.Type() == instancetype.Container {
                metadata := make(map[string]interface{})
                var tracker *ioprogress.ProgressTracker
                if op != nil {
                        tracker = &ioprogress.ProgressTracker{
                                Handler: func(percent, speed int64) {
+                                       // tomp TODO should the container 
reference here be removed?
                                        shared.SetProgressMetadata(metadata, 
"create_container_from_image_unpack", "Unpack", percent, 0, speed)
                                        op.UpdateMetadata(metadata)
                                }}
                }
 
                // Now create the storage from an image.
-               err = c.Storage().ContainerCreateFromImage(c, hash, tracker)
+               err = inst.Storage().ContainerCreateFromImage(inst, hash, 
tracker)
                if err != nil {
-                       c.Delete()
-                       return nil, errors.Wrap(err, "Create container from 
image")
+                       return nil, errors.Wrap(err, "Create instance from 
image")
                }
        } else {
                return nil, fmt.Errorf("Instance type not supported")
        }
 
        // Apply any post-storage configuration.
-       err = containerConfigureInternal(d.State(), c)
+       err = containerConfigureInternal(d.State(), inst)
        if err != nil {
-               c.Delete()
-               return nil, errors.Wrap(err, "Configure container")
+               return nil, errors.Wrap(err, "Configure instance")
        }
 
-       return c, nil
+       revert = false
+       return inst, nil
 }
 
 func containerCreateAsCopy(s *state.State, args db.InstanceArgs, 
sourceContainer Instance, containerOnly bool, refresh bool) (Instance, error) {

From 3fc7315e8d4390a79765b9bb733de4c80d4dc237 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 10:59:50 +0000
Subject: [PATCH 04/27] lxd/container: Renames containerCreateInternal to
 instanceCreateInternal

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container.go | 71 +++++++++++++++++++++++++++++-------------------
 1 file changed, 43 insertions(+), 28 deletions(-)

diff --git a/lxd/container.go b/lxd/container.go
index 537d524186..bd7d848107 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -799,8 +799,8 @@ func containerCreateAsSnapshot(s *state.State, args 
db.InstanceArgs, sourceInsta
        return c, nil
 }
 
-func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, 
error) {
-       // Set default values
+func instanceCreateInternal(s *state.State, args db.InstanceArgs) (Instance, 
error) {
+       // Set default values.
        if args.Project == "" {
                args.Project = "default"
        }
@@ -832,11 +832,11 @@ func containerCreateInternal(s *state.State, args 
db.InstanceArgs) (container, e
                        return nil, err
                }
 
-               // Unset expiry date since containers don't expire
+               // Unset expiry date since containers don't expire.
                args.ExpiryDate = time.Time{}
        }
 
-       // Validate container config
+       // Validate container config.
        err := containerValidConfig(s.OS, args.Config, false, false)
        if err != nil {
                return nil, err
@@ -848,7 +848,7 @@ func containerCreateInternal(s *state.State, args 
db.InstanceArgs) (container, e
                return nil, errors.Wrap(err, "Invalid devices")
        }
 
-       // Validate architecture
+       // Validate architecture.
        _, err = osarch.ArchitectureName(args.Architecture)
        if err != nil {
                return nil, err
@@ -858,7 +858,7 @@ func containerCreateInternal(s *state.State, args 
db.InstanceArgs) (container, e
                return nil, fmt.Errorf("Requested architecture isn't supported 
by this host")
        }
 
-       // Validate profiles
+       // Validate profiles.
        profiles, err := s.Cluster.Profiles(args.Project)
        if err != nil {
                return nil, err
@@ -885,15 +885,15 @@ func containerCreateInternal(s *state.State, args 
db.InstanceArgs) (container, e
                args.LastUsedDate = time.Unix(0, 0).UTC()
        }
 
-       var container db.Instance
+       var dbInst db.Instance
+
        err = s.Cluster.Transaction(func(tx *db.ClusterTx) error {
                node, err := tx.NodeName()
                if err != nil {
                        return err
                }
 
-               // TODO: this check should probably be performed by the db
-               // package itself.
+               // TODO: this check should probably be performed by the db 
package itself.
                exists, err := tx.ProjectExists(args.Project)
                if err != nil {
                        return errors.Wrapf(err, "Check if project %q exists", 
args.Project)
@@ -932,13 +932,13 @@ func containerCreateInternal(s *state.State, args 
db.InstanceArgs) (container, e
                                return errors.Wrap(err, "Fetch created snapshot 
from the database")
                        }
 
-                       container = db.InstanceSnapshotToInstance(instance, s)
+                       dbInst = db.InstanceSnapshotToInstance(instance, s)
 
                        return nil
                }
 
-               // Create the container entry
-               container = db.Instance{
+               // Create the instance entry.
+               dbInst = db.Instance{
                        Project:      args.Project,
                        Name:         args.Name,
                        Node:         node,
@@ -956,28 +956,28 @@ func containerCreateInternal(s *state.State, args 
db.InstanceArgs) (container, e
                        ExpiryDate:   args.ExpiryDate,
                }
 
-               _, err = tx.InstanceCreate(container)
+               _, err = tx.InstanceCreate(dbInst)
                if err != nil {
-                       return errors.Wrap(err, "Add container info to the 
database")
+                       return errors.Wrap(err, "Add instance info to the 
database")
                }
 
-               // Read back the container, to get ID and creation time.
-               c, err := tx.InstanceGet(args.Project, args.Name)
+               // Read back the instance, to get ID and creation time.
+               dbRow, err := tx.InstanceGet(args.Project, args.Name)
                if err != nil {
-                       return errors.Wrap(err, "Fetch created container from 
the database")
+                       return errors.Wrap(err, "Fetch created instance from 
the database")
                }
 
-               container = *c
+               dbInst = *dbRow
 
-               if container.ID < 1 {
-                       return errors.Wrapf(err, "Unexpected container database 
ID %d", container.ID)
+               if dbInst.ID < 1 {
+                       return errors.Wrapf(err, "Unexpected instance database 
ID %d", dbInst.ID)
                }
 
                return nil
        })
        if err != nil {
                if err == db.ErrAlreadyDefined {
-                       thing := "Container"
+                       thing := "Instance"
                        if shared.IsSnapshot(args.Name) {
                                thing = "Snapshot"
                        }
@@ -986,19 +986,34 @@ func containerCreateInternal(s *state.State, args 
db.InstanceArgs) (container, e
                return nil, err
        }
 
-       // Wipe any existing log for this container name
+       revert := true
+       defer func() {
+               if !revert {
+                       return
+               }
+
+               s.Cluster.InstanceRemove(dbInst.Project, dbInst.Name)
+       }()
+
+       // Wipe any existing log for this instance name.
        os.RemoveAll(shared.LogPath(args.Name))
 
-       args = db.ContainerToArgs(&container)
+       args = db.ContainerToArgs(&dbInst)
+
+       var inst Instance
+
+       if args.Type == instancetype.Container {
+               inst, err = containerLXCCreate(s, args)
+       } else {
+               return nil, fmt.Errorf("Instance type invalid")
+       }
 
-       // Setup the container struct and finish creation (storage and idmap)
-       c, err := containerLXCCreate(s, args)
        if err != nil {
-               s.Cluster.ContainerRemove(args.Project, args.Name)
-               return nil, errors.Wrap(err, "Create LXC container")
+               return nil, errors.Wrap(err, "Create instance")
        }
 
-       return c, nil
+       revert = false
+       return inst, nil
 }
 
 func containerConfigureInternal(state *state.State, c Instance) error {

From be479c678960be804016843d6eb1f41d5eb4d7ad Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 11:00:39 +0000
Subject: [PATCH 05/27] lxd/container/lxc: Updates use of renamed
 c.state.Cluster.InstanceRemove

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

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index b52b732806..2071b242bb 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -3614,7 +3614,7 @@ func (c *containerLXC) Delete() error {
                }
 
                // Remove the database record of the instance or snapshot 
instance.
-               if err := c.state.Cluster.ContainerRemove(c.Project(), 
c.Name()); err != nil {
+               if err := c.state.Cluster.InstanceRemove(c.Project(), 
c.Name()); err != nil {
                        logger.Error("Failed deleting instance entry", 
log.Ctx{"project": c.Project(), "instance": c.Name(), "err": err})
                        return err
                }
@@ -3689,7 +3689,7 @@ func (c *containerLXC) Delete() error {
                }
 
                // Remove the database record
-               if err := c.state.Cluster.ContainerRemove(c.project, c.Name()); 
err != nil {
+               if err := c.state.Cluster.InstanceRemove(c.project, c.Name()); 
err != nil {
                        logger.Error("Failed deleting container entry", 
log.Ctx{"name": c.Name(), "err": err})
                        return err
                }

From 58ad929d5189b1fe0455220f23bf67c063158f33 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 11:01:04 +0000
Subject: [PATCH 06/27] lxd/containers/post: Adds VM support to createFromImage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/containers_post.go | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index e784bb3563..d501b67d9a 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -118,9 +118,16 @@ func createFromImage(d *Daemon, project string, req 
*api.InstancesPost) response
                        if err != nil {
                                return err
                        }
+
+                       // Detect image type based on instance type requested.
+                       imgType := "container"
+                       if req.Type == "virtual-machine" {
+                               imgType = "virtual-machine"
+                       }
+
                        info, err = d.ImageDownload(
                                op, req.Source.Server, req.Source.Protocol, 
req.Source.Certificate,
-                               req.Source.Secret, hash, "container", true, 
autoUpdate, "", true, project)
+                               req.Source.Secret, hash, imgType, true, 
autoUpdate, "", true, project)
                        if err != nil {
                                return err
                        }
@@ -136,11 +143,12 @@ func createFromImage(d *Daemon, project string, req 
*api.InstancesPost) response
                        return err
                }
 
-               _, err = containerCreateFromImage(d, args, info.Fingerprint, op)
+               _, err = instanceCreateFromImage(d, args, info.Fingerprint, op)
                return err
        }
 
        resources := map[string][]string{}
+       // tomp TODO should this be renamed/added to?
        resources["containers"] = []string{req.Name}
 
        op, err := operations.OperationCreate(d.State(), project, 
operations.OperationClassTask, db.OperationContainerCreate, resources, nil, 
run, nil, nil)
@@ -198,7 +206,7 @@ func createFromMigration(d *Daemon, project string, req 
*api.InstancesPost) resp
                return response.NotImplemented(fmt.Errorf("Mode '%s' not 
implemented", req.Source.Mode))
        }
 
-       var c container
+       var c Instance
 
        // Parse the architecture name
        architecture, err := osarch.ArchitectureId(req.Architecture)
@@ -293,7 +301,7 @@ func createFromMigration(d *Daemon, project string, req 
*api.InstancesPost) resp
                        return response.BadRequest(fmt.Errorf("Instance type 
not container"))
                }
 
-               c = inst.(container)
+               c = inst
        }
 
        if !req.Source.Refresh {
@@ -340,7 +348,7 @@ func createFromMigration(d *Daemon, project string, req 
*api.InstancesPost) resp
                        }
 
                        if ps.MigrationType() == 
migration.MigrationFSType_RSYNC {
-                               c, err = containerCreateFromImage(d, args, 
req.Source.BaseImage, nil)
+                               c, err = instanceCreateFromImage(d, args, 
req.Source.BaseImage, nil)
                                if err != nil {
                                        return response.InternalError(err)
                                }

From da249124590ba32ec28611124b8ca129442069ac Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 11:01:19 +0000
Subject: [PATCH 07/27] lxd/db/containers: Renames ContainerRemove to
 InstanceRemove

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

diff --git a/lxd/db/containers.go b/lxd/db/containers.go
index b2b4cf9d3d..58ff234f32 100644
--- a/lxd/db/containers.go
+++ b/lxd/db/containers.go
@@ -620,8 +620,8 @@ func (c *ClusterTx) configUpdate(id int, values 
map[string]string, insertSQL, de
        return nil
 }
 
-// ContainerRemove removes the container with the given name from the database.
-func (c *Cluster) ContainerRemove(project, name string) error {
+// InstanceRemove removes the instance with the given name from the database.
+func (c *Cluster) InstanceRemove(project, name string) error {
        if strings.Contains(name, shared.SnapshotDelimiter) {
                parts := strings.SplitN(name, shared.SnapshotDelimiter, 2)
                return c.Transaction(func(tx *ClusterTx) error {

From a6882c6c579b3d431af91b4ff6a45c18e0c3b59e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 11:04:06 +0000
Subject: [PATCH 08/27] lxd/container: Renames containerCreateAsEmpty to
 containerCreateAsEmpty

- Adds revert for safety

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container.go | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/lxd/container.go b/lxd/container.go
index bd7d848107..f25f232e12 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -254,31 +254,38 @@ type container interface {
        NextIdmap() (*idmap.IdmapSet, error)
 }
 
-// containerCreateAsEmpty creates an empty instance.
-func containerCreateAsEmpty(d *Daemon, args db.InstanceArgs) (Instance, error) 
{
-       // Create the container.
-       c, err := instanceCreateInternal(d.State(), args)
+// instanceCreateAsEmpty creates an empty instance.
+func instanceCreateAsEmpty(d *Daemon, args db.InstanceArgs) (Instance, error) {
+       // Create the instance record.
+       inst, err := instanceCreateInternal(d.State(), args)
        if err != nil {
                return nil, err
        }
 
+       revert := true
+       defer func() {
+               if !revert {
+                       return
+               }
+
+               inst.Delete()
+       }()
+
        // Check if we can load new storage layer for pool driver type.
-       pool, err := storagePools.GetPoolByInstance(d.State(), c)
+       pool, err := storagePools.GetPoolByInstance(d.State(), inst)
        if err != storageDrivers.ErrUnknownDriver && err != 
storageDrivers.ErrNotImplemented {
                if err != nil {
                        return nil, errors.Wrap(err, "Load instance storage 
pool")
                }
 
-               err = pool.CreateInstance(c, nil)
+               err = pool.CreateInstance(inst, nil)
                if err != nil {
-                       c.Delete()
                        return nil, errors.Wrap(err, "Create instance")
                }
-       } else if c.Type() == instancetype.Container {
+       } else if inst.Type() == instancetype.Container {
                // Now create the empty storage.
-               err = c.Storage().ContainerCreate(c)
+               err = inst.Storage().ContainerCreate(inst)
                if err != nil {
-                       c.Delete()
                        return nil, err
                }
        } else {
@@ -286,13 +293,13 @@ func containerCreateAsEmpty(d *Daemon, args 
db.InstanceArgs) (Instance, error) {
        }
 
        // Apply any post-storage configuration.
-       err = containerConfigureInternal(d.State(), c)
+       err = containerConfigureInternal(d.State(), inst)
        if err != nil {
-               c.Delete()
                return nil, err
        }
 
-       return c, nil
+       revert = false
+       return inst, nil
 }
 
 func containerCreateFromBackup(s *state.State, info backup.Info, data 
io.ReadSeeker,

From 2ad54c4f2bbd19253027be680eabd0f20be4b5ca Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 11:09:46 +0000
Subject: [PATCH 09/27] lxd/containers/post: Updates use of
 instanceCreateAsEmpty

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

diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index d501b67d9a..eced2a1c89 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -185,7 +185,7 @@ func createFromNone(d *Daemon, project string, req 
*api.InstancesPost) response.
        }
 
        run := func(op *operations.Operation) error {
-               _, err := containerCreateAsEmpty(d, args)
+               _, err := instanceCreateAsEmpty(d, args)
                return err
        }
 
@@ -320,7 +320,7 @@ func createFromMigration(d *Daemon, project string, req 
*api.InstancesPost) resp
                 */
                _, _, err = d.cluster.ImageGet(args.Project, 
req.Source.BaseImage, false, true)
                if err != nil {
-                       c, err = containerCreateAsEmpty(d, args)
+                       c, err = instanceCreateAsEmpty(d, args)
                        if err != nil {
                                return response.InternalError(err)
                        }
@@ -353,7 +353,7 @@ func createFromMigration(d *Daemon, project string, req 
*api.InstancesPost) resp
                                        return response.InternalError(err)
                                }
                        } else {
-                               c, err = containerCreateAsEmpty(d, args)
+                               c, err = instanceCreateAsEmpty(d, args)
                                if err != nil {
                                        return response.InternalError(err)
                                }

From 1901d15737fbb80e9a122f77451120fee05716dc Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 11:36:17 +0000
Subject: [PATCH 10/27] lxd/storage/backend/lxd: Pass correct content type to
 storage drivers for VMs

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/backend_lxd.go | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index f246a6352a..f05cc06bb6 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -299,7 +299,12 @@ func (b *lxdBackend) CreateInstance(inst Instance, op 
*operations.Operation) err
                b.DeleteInstance(inst, op)
        }()
 
-       vol := b.newVolume(volType, drivers.ContentTypeFS, 
project.Prefix(inst.Project(), inst.Name()), nil)
+       contentType := drivers.ContentTypeFS
+       if inst.Type() == instancetype.VM {
+               contentType = drivers.ContentTypeBlock
+       }
+
+       vol := b.newVolume(volType, contentType, project.Prefix(inst.Project(), 
inst.Name()), nil)
        err = b.driver.CreateVolume(vol, nil, op)
        if err != nil {
                return err
@@ -366,7 +371,12 @@ func (b *lxdBackend) CreateInstanceFromImage(inst 
Instance, fingerprint string,
                b.DeleteInstance(inst, op)
        }()
 
-       vol := b.newVolume(volType, drivers.ContentTypeFS, 
project.Prefix(inst.Project(), inst.Name()), nil)
+       contentType := drivers.ContentTypeFS
+       if inst.Type() == instancetype.VM {
+               contentType = drivers.ContentTypeBlock
+       }
+
+       vol := b.newVolume(volType, contentType, project.Prefix(inst.Project(), 
inst.Name()), nil)
 
        // If the driver doesn't support optimized image volumes then create a 
new empty volume and
        // populate it with the contents of the image archive.
@@ -384,7 +394,7 @@ func (b *lxdBackend) CreateInstanceFromImage(inst Instance, 
fingerprint string,
                        return err
                }
 
-               imgVol := b.newVolume(drivers.VolumeTypeImage, 
drivers.ContentTypeFS, fingerprint, nil)
+               imgVol := b.newVolume(drivers.VolumeTypeImage, contentType, 
fingerprint, nil)
                err = b.driver.CreateVolumeFromCopy(vol, imgVol, false, op)
                if err != nil {
                        return err
@@ -839,9 +849,20 @@ func (b *lxdBackend) EnsureImage(fingerprint string, op 
*operations.Operation) e
                return nil
        }
 
+       // Load image info from database.
+       _, image, err := b.state.Cluster.ImageGetFromAnyProject(fingerprint)
+       if err != nil {
+               return err
+       }
+
+       contentType := drivers.ContentTypeFS
+       if api.InstanceType(image.Type) == api.InstanceTypeVM {
+               contentType = drivers.ContentTypeBlock
+       }
+
        // Create the new image volume.
-       vol := b.newVolume(drivers.VolumeTypeImage, drivers.ContentTypeFS, 
fingerprint, nil)
-       err := b.driver.CreateVolume(vol, b.imageFiller(fingerprint, op), op)
+       vol := b.newVolume(drivers.VolumeTypeImage, contentType, fingerprint, 
nil)
+       err = b.driver.CreateVolume(vol, b.imageFiller(fingerprint, op), op)
        if err != nil {
                return err
        }

From ebfc5f673d3abcd1dcfb6ae6acd9d541937f4af9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 11:57:18 +0000
Subject: [PATCH 11/27] lxd/storage/drivers/utils: Unexports
 deleteParentSnapshotDirIfEmpty

As not used outside of package.

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

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index ffc09539ed..655c2ac58a 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -192,9 +192,9 @@ func GetSnapshotVolumeName(parentName, snapshotName string) 
string {
        return fmt.Sprintf("%s%s%s", parentName, shared.SnapshotDelimiter, 
snapshotName)
 }
 
-// DeleteParentSnapshotDirIfEmpty removes the parent snapshot directory if it 
is empty.
+// deleteParentSnapshotDirIfEmpty removes the parent snapshot directory if it 
is empty.
 // It accepts the pool name, volume type and parent volume name.
-func DeleteParentSnapshotDirIfEmpty(poolName string, volType VolumeType, 
volName string) error {
+func deleteParentSnapshotDirIfEmpty(poolName string, volType VolumeType, 
volName string) error {
        snapshotsPath, err := GetVolumeSnapshotDir(poolName, volType, volName)
        if err != nil {
                return err

From 5d70b6b162775ef4e1a9de2ab58231e0380d0add Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 11:57:50 +0000
Subject: [PATCH 12/27] lxd/storage/drivers/driver/dir: Updates use of
 deleteParentSnapshotDirIfEmpty

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_dir.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/storage/drivers/driver_dir.go 
b/lxd/storage/drivers/driver_dir.go
index 58592d8b36..fdb9507217 100644
--- a/lxd/storage/drivers/driver_dir.go
+++ b/lxd/storage/drivers/driver_dir.go
@@ -639,7 +639,7 @@ func (d *dir) DeleteVolume(volType VolumeType, volName 
string, op *operations.Op
 
        // Although the volume snapshot directory should already be removed, 
lets remove it here
        // to just in case the top-level directory is left.
-       err = DeleteParentSnapshotDirIfEmpty(d.name, volType, volName)
+       err = deleteParentSnapshotDirIfEmpty(d.name, volType, volName)
        if err != nil {
                return err
        }
@@ -834,7 +834,7 @@ func (d *dir) DeleteVolumeSnapshot(volType VolumeType, 
volName string, snapshotN
        }
 
        // Remove the parent snapshot directory if this is the last snapshot 
being removed.
-       err = DeleteParentSnapshotDirIfEmpty(d.name, volType, volName)
+       err = deleteParentSnapshotDirIfEmpty(d.name, volType, volName)
        if err != nil {
                return err
        }

From 5f3ecea76bc2a302087ac973edd5b2e86cb3b060 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 16:54:27 +0000
Subject: [PATCH 13/27] lxd/container/lxc: Updating DB usage to be instance
 type agnostic

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container_lxc.go | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 2071b242bb..a6e5a13c96 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -3544,7 +3544,7 @@ func (c *containerLXC) Delete() error {
        }
 
        // Get the storage pool name of the instance.
-       poolName, err := c.state.Cluster.ContainerPool(c.Project(), c.Name())
+       poolName, err := c.state.Cluster.InstancePool(c.Project(), c.Name())
        if err != nil {
                return err
        }
@@ -4055,7 +4055,12 @@ func writeBackupFile(c Instance) error {
                return err
        }
 
-       _, volume, err := 
s.Cluster.StoragePoolNodeVolumeGetTypeByProject(c.Project(), c.Name(), 
storagePoolVolumeTypeContainer, poolID)
+       dbType := db.StoragePoolVolumeTypeContainer
+       if c.Type() == instancetype.VM {
+               dbType = db.StoragePoolVolumeTypeVM
+       }
+
+       _, volume, err := 
s.Cluster.StoragePoolNodeVolumeGetTypeByProject(c.Project(), c.Name(), dbType, 
poolID)
        if err != nil {
                return err
        }
@@ -6897,7 +6902,7 @@ func (c *containerLXC) StatePath() string {
 }
 
 func (c *containerLXC) StoragePool() (string, error) {
-       poolName, err := c.state.Cluster.ContainerPool(c.Project(), c.Name())
+       poolName, err := c.state.Cluster.InstancePool(c.Project(), c.Name())
        if err != nil {
                return "", err
        }

From 1c8ad86c88eb129ac5796561d4563e61c10faf7e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 16:54:59 +0000
Subject: [PATCH 14/27] lxd/container/post: Updates usage of InstancePool

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

diff --git a/lxd/container_post.go b/lxd/container_post.go
index d9027961ce..3371b332b9 100644
--- a/lxd/container_post.go
+++ b/lxd/container_post.go
@@ -178,7 +178,7 @@ func containerPost(d *Daemon, r *http.Request) 
response.Response {
                        }
 
                        // Check if we are migrating a ceph-based container.
-                       poolName, err := d.cluster.ContainerPool(project, name)
+                       poolName, err := d.cluster.InstancePool(project, name)
                        if err != nil {
                                err = errors.Wrap(err, "Failed to fetch 
container's pool name")
                                return response.SmartError(err)
@@ -449,7 +449,7 @@ func containerPostClusteringMigrateWithCeph(d *Daemon, c 
Instance, project, oldN
                                return errors.Wrapf(
                                        err, "Move container %s to %s with new 
name %s", oldName, newNode, newName)
                        }
-                       poolName, err = tx.ContainerPool(project, newName)
+                       poolName, err = tx.InstancePool(project, newName)
                        if err != nil {
                                return errors.Wrapf(err, "Get the container's 
storage pool name for %s", newName)
                        }

From 4f1254a4b996e4543939852487c383116e81b1fc Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 17:19:55 +0000
Subject: [PATCH 15/27] lxd/container/test: Updates instanceCreateInternal
 usage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container_test.go | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/lxd/container_test.go b/lxd/container_test.go
index 4d49318e56..92b7711e9b 100644
--- a/lxd/container_test.go
+++ b/lxd/container_test.go
@@ -26,7 +26,7 @@ func (suite *containerTestSuite) 
TestContainer_ProfilesDefault() {
                Name:      "testFoo",
        }
 
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
        defer c.Delete()
 
@@ -34,7 +34,7 @@ func (suite *containerTestSuite) 
TestContainer_ProfilesDefault() {
        suite.Len(
                profiles,
                1,
-               "No default profile created on containerCreateInternal.")
+               "No default profile created on instanceCreateInternal.")
 
        suite.Equal(
                "default",
@@ -69,7 +69,7 @@ func (suite *containerTestSuite) 
TestContainer_ProfilesMulti() {
                Name:      "testFoo",
        }
 
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
        defer c.Delete()
 
@@ -77,7 +77,7 @@ func (suite *containerTestSuite) 
TestContainer_ProfilesMulti() {
        suite.Len(
                profiles,
                2,
-               "Didn't get both profiles in containerCreateInternal.")
+               "Didn't get both profiles in instanceCreateInternal.")
 
        suite.True(
                c.IsPrivileged(),
@@ -97,7 +97,7 @@ func (suite *containerTestSuite) 
TestContainer_ProfilesOverwriteDefaultNic() {
                Name: "testFoo",
        }
 
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
 
        suite.True(c.IsPrivileged(), "This container should be privileged.")
@@ -128,7 +128,7 @@ func (suite *containerTestSuite) TestContainer_LoadFromDB() 
{
        }
 
        // Create the container
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
        defer c.Delete()
 
@@ -159,7 +159,7 @@ func (suite *containerTestSuite) 
TestContainer_Path_Regular() {
                Name:      "testFoo",
        }
 
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
        defer c.Delete()
 
@@ -175,7 +175,7 @@ func (suite *containerTestSuite) TestContainer_LogPath() {
                Name:      "testFoo",
        }
 
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
        defer c.Delete()
 
@@ -190,7 +190,7 @@ func (suite *containerTestSuite) 
TestContainer_IsPrivileged_Privileged() {
                Name:      "testFoo",
        }
 
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
 
        suite.Req.True(c.IsPrivileged(), "This container should be privileged.")
@@ -205,7 +205,7 @@ func (suite *containerTestSuite) 
TestContainer_IsPrivileged_Unprivileged() {
                Name:      "testFoo",
        }
 
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
 
        suite.Req.False(c.IsPrivileged(), "This container should be 
unprivileged.")
@@ -219,7 +219,7 @@ func (suite *containerTestSuite) TestContainer_Rename() {
                Name:      "testFoo",
        }
 
-       c, err := containerCreateInternal(suite.d.State(), args)
+       c, err := instanceCreateInternal(suite.d.State(), args)
        suite.Req.Nil(err)
        defer c.Delete()
 
@@ -228,7 +228,7 @@ func (suite *containerTestSuite) TestContainer_Rename() {
 }
 
 func (suite *containerTestSuite) TestContainer_findIdmap_isolated() {
-       c1, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{
+       c1, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{
                Type: instancetype.Container,
                Name: "isol-1",
                Config: map[string]string{
@@ -238,7 +238,7 @@ func (suite *containerTestSuite) 
TestContainer_findIdmap_isolated() {
        suite.Req.Nil(err)
        defer c1.Delete()
 
-       c2, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{
+       c2, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{
                Type: instancetype.Container,
                Name: "isol-2",
                Config: map[string]string{
@@ -269,7 +269,7 @@ func (suite *containerTestSuite) 
TestContainer_findIdmap_isolated() {
 }
 
 func (suite *containerTestSuite) TestContainer_findIdmap_mixed() {
-       c1, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{
+       c1, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{
                Type: instancetype.Container,
                Name: "isol-1",
                Config: map[string]string{
@@ -279,7 +279,7 @@ func (suite *containerTestSuite) 
TestContainer_findIdmap_mixed() {
        suite.Req.Nil(err)
        defer c1.Delete()
 
-       c2, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{
+       c2, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{
                Type: instancetype.Container,
                Name: "isol-2",
                Config: map[string]string{
@@ -310,7 +310,7 @@ func (suite *containerTestSuite) 
TestContainer_findIdmap_mixed() {
 }
 
 func (suite *containerTestSuite) TestContainer_findIdmap_raw() {
-       c1, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{
+       c1, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{
                Type: instancetype.Container,
                Name: "isol-1",
                Config: map[string]string{
@@ -349,7 +349,7 @@ func (suite *containerTestSuite) 
TestContainer_findIdmap_maxed() {
        maps := []*idmap.IdmapSet{}
 
        for i := 0; i < 7; i++ {
-               c, err := containerCreateInternal(suite.d.State(), 
db.InstanceArgs{
+               c, err := instanceCreateInternal(suite.d.State(), 
db.InstanceArgs{
                        Type: instancetype.Container,
                        Name: fmt.Sprintf("isol-%d", i),
                        Config: map[string]string{

From dbead628dead023e34b038b1d0d8a755dbcd6623 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 18:32:22 +0000
Subject: [PATCH 16/27] lxd/api/internal: InstancePath usage

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

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 392b30f81f..ff0392ac18 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -698,7 +698,7 @@ func internalImport(d *Daemon, r *http.Request) 
response.Response {
                                onDiskPoolName = poolName
                        }
                        snapName := fmt.Sprintf("%s/%s", req.Name, od)
-                       snapPath := driver.ContainerPath(snapName, true)
+                       snapPath := driver.InstancePath(instancetype.Container, 
projectName, snapName, true)
                        err = lvmContainerDeleteInternal(projectName, poolName, 
req.Name,
                                true, onDiskPoolName, snapPath)
                case "ceph":
@@ -936,7 +936,7 @@ func internalImport(d *Daemon, r *http.Request) 
response.Response {
                return response.SmartError(err)
        }
 
-       containerPath := driver.ContainerPath(project.Prefix(projectName, 
req.Name), false)
+       containerPath := driver.InstancePath(instancetype.Container, 
projectName, req.Name, false)
        isPrivileged := false
        if backup.Container.Config["security.privileged"] == "" {
                isPrivileged = true

From 86ed197b6158db87975fa555efc754202759ab66 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 18:33:02 +0000
Subject: [PATCH 17/27] lxd/container/lxc: InstancePath usage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container_lxc.go | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index a6e5a13c96..193fc6f4e5 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -6854,8 +6854,7 @@ func (c *containerLXC) State() string {
 
 // Various container paths
 func (c *containerLXC) Path() string {
-       name := project.Prefix(c.Project(), c.Name())
-       return storagePools.ContainerPath(name, c.IsSnapshot())
+       return storagePools.InstancePath(c.Type(), c.Project(), c.Name(), 
c.IsSnapshot())
 }
 
 func (c *containerLXC) DevicesPath() string {

From d82f602da78d3a5aec4a8e8e9e4cd3c723a4502b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 18:33:22 +0000
Subject: [PATCH 18/27] lxd/storage/backend/lxd: InstancePath usage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/backend_lxd.go | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index f05cc06bb6..12212d8211 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -178,8 +178,7 @@ func (b *lxdBackend) Unmount() (bool, error) {
 // ensureInstanceSymlink creates a symlink in the instance directory to the 
instance's mount path
 // if doesn't exist already.
 func (b *lxdBackend) ensureInstanceSymlink(instanceType instancetype.Type, 
projectName, instanceName, mountPath string) error {
-       volStorageName := project.Prefix(projectName, instanceName)
-       symlinkPath := ContainerPath(volStorageName, false)
+       symlinkPath := InstancePath(instanceType, projectName, instanceName, 
false)
 
        // Remove any old symlinks left over by previous bugs that may point to 
a different pool.
        if shared.PathExists(symlinkPath) {
@@ -200,8 +199,7 @@ func (b *lxdBackend) ensureInstanceSymlink(instanceType 
instancetype.Type, proje
 
 // removeInstanceSymlink removes a symlink in the instance directory to the 
instance's mount path.
 func (b *lxdBackend) removeInstanceSymlink(instanceType instancetype.Type, 
projectName, instanceName string) error {
-       volStorageName := project.Prefix(projectName, instanceName)
-       symlinkPath := ContainerPath(volStorageName, false)
+       symlinkPath := InstancePath(instanceType, projectName, instanceName, 
false)
 
        if shared.PathExists(symlinkPath) {
                err := os.Remove(symlinkPath)
@@ -223,7 +221,7 @@ func (b *lxdBackend) 
ensureInstanceSnapshotSymlink(instanceType instancetype.Typ
        }
 
        parentName, _, _ := 
shared.ContainerGetParentAndSnapshotName(instanceName)
-       snapshotSymlink := shared.VarPath("snapshots", 
project.Prefix(projectName, parentName))
+       snapshotSymlink := InstancePath(instanceType, projectName, parentName, 
true)
        volStorageName := project.Prefix(projectName, parentName)
 
        snapshotTargetPath, err := drivers.GetVolumeSnapshotDir(b.name, 
volType, volStorageName)
@@ -259,7 +257,7 @@ func (b *lxdBackend) 
removeInstanceSnapshotSymlinkIfUnused(instanceType instance
        }
 
        parentName, _, _ := 
shared.ContainerGetParentAndSnapshotName(instanceName)
-       snapshotSymlink := shared.VarPath("snapshots", 
project.Prefix(projectName, parentName))
+       snapshotSymlink := InstancePath(instanceType, projectName, parentName, 
true)
        volStorageName := project.Prefix(projectName, parentName)
 
        snapshotTargetPath, err := drivers.GetVolumeSnapshotDir(b.name, 
volType, volStorageName)

From d9d9df7a3334378849467201e06af6d0278c7cdf Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 18:33:58 +0000
Subject: [PATCH 19/27] lxd/storage/storage: Renames ContainerPath to
 InstancePath

- Ads VM support

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

diff --git a/lxd/storage/storage.go b/lxd/storage/storage.go
index 4ec18a70e3..a30471982b 100644
--- a/lxd/storage/storage.go
+++ b/lxd/storage/storage.go
@@ -3,17 +3,27 @@ package storage
 import (
        "os"
 
+       "github.com/lxc/lxd/lxd/instance/instancetype"
        "github.com/lxc/lxd/lxd/project"
        "github.com/lxc/lxd/shared"
 )
 
-// ContainerPath returns the directory of a container or snapshot.
-func ContainerPath(name string, isSnapshot bool) string {
+// InstancePath returns the directory of an instance or snapshot.
+func InstancePath(instanceType instancetype.Type, projectName, instanceName 
string, isSnapshot bool) string {
+       fullName := project.Prefix(projectName, instanceName)
+       if instanceType == instancetype.VM {
+               if isSnapshot {
+                       return shared.VarPath("virtual-machines-snapshots", 
fullName)
+               }
+
+               return shared.VarPath("virtual-machines", fullName)
+       }
+
        if isSnapshot {
-               return shared.VarPath("snapshots", name)
+               return shared.VarPath("snapshots", fullName)
        }
 
-       return shared.VarPath("containers", name)
+       return shared.VarPath("containers", fullName)
 }
 
 // GetStoragePoolMountPoint returns the mountpoint of the given pool.

From 3d9903cf3732847ca46f83e38682481d313c9615 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 18:34:19 +0000
Subject: [PATCH 20/27] lxd/storage/dir: InstancePath usage

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

diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go
index 15044043d2..846077dda5 100644
--- a/lxd/storage_dir.go
+++ b/lxd/storage_dir.go
@@ -12,6 +12,7 @@ import (
        "golang.org/x/sys/unix"
 
        "github.com/lxc/lxd/lxd/backup"
+       "github.com/lxc/lxd/lxd/instance/instancetype"
        "github.com/lxc/lxd/lxd/migration"
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/lxd/project"
@@ -1198,7 +1199,7 @@ func (s *storageDir) ContainerBackupLoad(info 
backup.Info, data io.ReadSeeker, t
 
        // Create mountpoints
        containerMntPoint := driver.GetContainerMountPoint(info.Project, 
s.pool.Name, info.Name)
-       err = driver.CreateContainerMountpoint(containerMntPoint, 
driver.ContainerPath(project.Prefix(info.Project, info.Name), false), 
info.Privileged)
+       err = driver.CreateContainerMountpoint(containerMntPoint, 
driver.InstancePath(instancetype.Container, info.Project, info.Name, false), 
info.Privileged)
        if err != nil {
                return errors.Wrap(err, "Create container mount point")
        }

From 9a57538232f3d0ab1cd8c0a01b2d7771da815e1d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 18:34:42 +0000
Subject: [PATCH 21/27] lxd/storage/zfs: InstancePath usage

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

diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index ca7cc6cbc2..da3350bde5 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -15,6 +15,7 @@ import (
        "golang.org/x/sys/unix"
 
        "github.com/lxc/lxd/lxd/backup"
+       "github.com/lxc/lxd/lxd/instance/instancetype"
        "github.com/lxc/lxd/lxd/migration"
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/lxd/project"
@@ -2113,7 +2114,7 @@ func (s *storageZfs) ContainerBackupCreate(path string, 
backup backup.Backup, so
 func (s *storageZfs) doContainerBackupLoadOptimized(info backup.Info, data 
io.ReadSeeker, tarArgs []string) error {
        containerName, _, _ := 
shared.ContainerGetParentAndSnapshotName(info.Name)
        containerMntPoint := driver.GetContainerMountPoint(info.Project, 
s.pool.Name, containerName)
-       err := driver.CreateContainerMountpoint(containerMntPoint, 
driver.ContainerPath(project.Prefix(info.Project, info.Name), false), 
info.Privileged)
+       err := driver.CreateContainerMountpoint(containerMntPoint, 
driver.InstancePath(instancetype.Container, info.Project, info.Name, false), 
info.Privileged)
        if err != nil {
                return err
        }

From b919f8c90161cdbbd63c7032516096e112866dab Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 18:36:49 +0000
Subject: [PATCH 22/27] lxd/container/test: InstancePath usage

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

diff --git a/lxd/container_test.go b/lxd/container_test.go
index 92b7711e9b..40bb744df6 100644
--- a/lxd/container_test.go
+++ b/lxd/container_test.go
@@ -165,7 +165,7 @@ func (suite *containerTestSuite) 
TestContainer_Path_Regular() {
 
        suite.Req.False(c.IsSnapshot(), "Shouldn't be a snapshot.")
        suite.Req.Equal(shared.VarPath("containers", "testFoo"), c.Path())
-       suite.Req.Equal(shared.VarPath("containers", "testFoo2"), 
driver.ContainerPath("testFoo2", false))
+       suite.Req.Equal(shared.VarPath("containers", "testFoo2"), 
driver.InstancePath(instancetype.Container, "default", "testFoo2", false))
 }
 
 func (suite *containerTestSuite) TestContainer_LogPath() {

From 86db8038bd0e8f2e554f0d1420e477ac1213afc5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 16:56:21 +0000
Subject: [PATCH 23/27] lxd/db/storage/pools: Adds VM instance type constant
 and conversion codes

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/db/storage_pools.go | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go
index b2995b23e0..1f9f30c8f4 100644
--- a/lxd/db/storage_pools.go
+++ b/lxd/db/storage_pools.go
@@ -1053,6 +1053,7 @@ const (
        StoragePoolVolumeTypeContainer = iota
        StoragePoolVolumeTypeImage
        StoragePoolVolumeTypeCustom
+       StoragePoolVolumeTypeVM
 )
 
 // Leave the string type in here! This guarantees that go treats this is as a
@@ -1060,6 +1061,7 @@ const (
 // constants which is not what we want.
 const (
        StoragePoolVolumeTypeNameContainer string = "container"
+       StoragePoolVolumeTypeNameVM        string = "virtual-machine"
        StoragePoolVolumeTypeNameImage     string = "image"
        StoragePoolVolumeTypeNameCustom    string = "custom"
 )
@@ -1081,6 +1083,8 @@ func StoragePoolVolumeTypeToName(volumeType int) (string, 
error) {
        switch volumeType {
        case StoragePoolVolumeTypeContainer:
                return StoragePoolVolumeTypeNameContainer, nil
+       case StoragePoolVolumeTypeVM:
+               return StoragePoolVolumeTypeNameVM, nil
        case StoragePoolVolumeTypeImage:
                return StoragePoolVolumeTypeNameImage, nil
        case StoragePoolVolumeTypeCustom:

From a56797fbd3a52281445d7ba69beca06355f8241c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 16:55:27 +0000
Subject: [PATCH 24/27] lxd/db/containers: Updates pool lookup functions to be
 instance type agnostic

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/db/containers.go      | 28 ++++++++++++++--------------
 lxd/db/containers_test.go |  2 +-
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/lxd/db/containers.go b/lxd/db/containers.go
index 58ff234f32..bb18ebf66c 100644
--- a/lxd/db/containers.go
+++ b/lxd/db/containers.go
@@ -444,7 +444,7 @@ func (c *ClusterTx) snapshotIDsAndNames(project, name 
string) (map[int]string, e
 func (c *ClusterTx) ContainerNodeMove(project, oldName, newName, newNode 
string) error {
        // First check that the container to be moved is backed by a ceph
        // volume.
-       poolName, err := c.ContainerPool(project, oldName)
+       poolName, err := c.InstancePool(project, oldName)
        if err != nil {
                return errors.Wrap(err, "failed to get container's storage pool 
name")
        }
@@ -1085,23 +1085,23 @@ WHERE projects.name=? AND instances.name=?`
        return max
 }
 
-// ContainerPool returns the storage pool of a given container.
+// InstancePool returns the storage pool of a given instance.
 //
-// This is a non-transactional variant of ClusterTx.ContainerPool().
-func (c *Cluster) ContainerPool(project, containerName string) (string, error) 
{
+// This is a non-transactional variant of ClusterTx.InstancePool().
+func (c *Cluster) InstancePool(project, instanceName string) (string, error) {
        var poolName string
        err := c.Transaction(func(tx *ClusterTx) error {
                var err error
-               poolName, err = tx.ContainerPool(project, containerName)
+               poolName, err = tx.InstancePool(project, instanceName)
                return err
        })
        return poolName, err
 }
 
-// ContainerPool returns the storage pool of a given container.
-func (c *ClusterTx) ContainerPool(project, containerName string) (string, 
error) {
-       if strings.Contains(containerName, shared.SnapshotDelimiter) {
-               return c.containerPoolSnapshot(project, containerName)
+// InstancePool returns the storage pool of a given instance.
+func (c *ClusterTx) InstancePool(project, instanceName string) (string, error) 
{
+       if strings.Contains(instanceName, shared.SnapshotDelimiter) {
+               return c.instancePoolSnapshot(project, instanceName)
        }
 
        // Get container storage volume. Since container names are globally
@@ -1113,9 +1113,9 @@ SELECT storage_pools.name FROM storage_pools
   JOIN storage_volumes ON storage_pools.id=storage_volumes.storage_pool_id
   JOIN instances ON instances.name=storage_volumes.name
   JOIN projects ON projects.id=instances.project_id
- WHERE projects.name=? AND storage_volumes.node_id=? AND 
storage_volumes.name=? AND storage_volumes.type=?
+ WHERE projects.name=? AND storage_volumes.node_id=? AND 
storage_volumes.name=? AND storage_volumes.type IN(?,?)
 `
-       inargs := []interface{}{project, c.nodeID, containerName, 
StoragePoolVolumeTypeContainer}
+       inargs := []interface{}{project, c.nodeID, instanceName, 
StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeVM}
        outargs := []interface{}{&poolName}
 
        err := c.tx.QueryRow(query, inargs...).Scan(outargs...)
@@ -1130,15 +1130,15 @@ SELECT storage_pools.name FROM storage_pools
        return poolName, nil
 }
 
-func (c *ClusterTx) containerPoolSnapshot(project, fullName string) (string, 
error) {
+func (c *ClusterTx) instancePoolSnapshot(project, fullName string) (string, 
error) {
        poolName := ""
        query := `
 SELECT storage_pools.name FROM storage_pools
   JOIN storage_volumes ON storage_pools.id=storage_volumes.storage_pool_id
   JOIN projects ON projects.id=storage_volumes.project_id
- WHERE projects.name=? AND storage_volumes.node_id=? AND 
storage_volumes.name=? AND storage_volumes.type=?
+ WHERE projects.name=? AND storage_volumes.node_id=? AND 
storage_volumes.name=? AND storage_volumes.type IN(?,?)
 `
-       inargs := []interface{}{project, c.nodeID, fullName, 
StoragePoolVolumeTypeContainer}
+       inargs := []interface{}{project, c.nodeID, fullName, 
StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeVM}
        outargs := []interface{}{&poolName}
 
        err := c.tx.QueryRow(query, inargs...).Scan(outargs...)
diff --git a/lxd/db/containers_test.go b/lxd/db/containers_test.go
index be914912bb..4c399a935b 100644
--- a/lxd/db/containers_test.go
+++ b/lxd/db/containers_test.go
@@ -374,7 +374,7 @@ func TestContainerPool(t *testing.T) {
        })
        require.NoError(t, err)
 
-       poolName, err := cluster.ContainerPool("default", "c1")
+       poolName, err := cluster.InstancePool("default", "c1")
        require.NoError(t, err)
        assert.Equal(t, "default", poolName)
 }

From d05b31613e4704f0153b9e184edfe59f25bf8a28 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Wed, 6 Nov 2019 17:06:24 +0000
Subject: [PATCH 25/27] lxd/storage/load: InstancePool usage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/load.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/storage/load.go b/lxd/storage/load.go
index ee3df9df32..bdad09351b 100644
--- a/lxd/storage/load.go
+++ b/lxd/storage/load.go
@@ -152,7 +152,7 @@ func GetPoolByName(state *state.State, name string) (Pool, 
error) {
 // If the pool's driver is not recognised then drivers.ErrUnknownDriver is 
returned. If the pool's
 // driver does not support the instance's type then drivers.ErrNotImplemented 
is returned.
 func GetPoolByInstance(s *state.State, inst Instance) (Pool, error) {
-       poolName, err := s.Cluster.ContainerPool(inst.Project(), inst.Name())
+       poolName, err := s.Cluster.InstancePool(inst.Project(), inst.Name())
        if err != nil {
                return nil, err
        }

From df08df4ca72fee1db9e6593aae8eb70bf1a23738 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 7 Nov 2019 09:20:20 +0000
Subject: [PATCH 26/27] lxd/db/containers/test: InstancePool usage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/db/containers_test.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/db/containers_test.go b/lxd/db/containers_test.go
index 4c399a935b..2b2f96c65c 100644
--- a/lxd/db/containers_test.go
+++ b/lxd/db/containers_test.go
@@ -347,7 +347,7 @@ func TestContainersByNodeName(t *testing.T) {
                }, result)
 }
 
-func TestContainerPool(t *testing.T) {
+func TestInstancePool(t *testing.T) {
        cluster, cleanup := db.NewTestCluster(t)
        defer cleanup()
 

From 8d62d915358260345e1fab2a20ff7ac1fd33512b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 7 Nov 2019 09:20:34 +0000
Subject: [PATCH 27/27] lxd/storage: InstancePool usage

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

diff --git a/lxd/storage.go b/lxd/storage.go
index 7b50d49119..163bff5435 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -620,7 +620,7 @@ func storagePoolVolumeContainerCreateInit(s *state.State, 
project string, poolNa
 
 func storagePoolVolumeContainerLoadInit(s *state.State, project, containerName 
string) (storage, error) {
        // Get the storage pool of a given container.
-       poolName, err := s.Cluster.ContainerPool(project, containerName)
+       poolName, err := s.Cluster.InstancePool(project, containerName)
        if err != nil {
                return nil, errors.Wrapf(err, "Load storage pool for container 
%q in project %q", containerName, project)
        }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to