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

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) ===

From 6e54f64ca62105e1a344d7e2a11d58ae81595164 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 10:21:43 +0000
Subject: [PATCH 01/13] lxd/storage/load: Adds GetPoolByInstanceName

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

diff --git a/lxd/storage/load.go b/lxd/storage/load.go
index 1c134d75d6..eb7fa6e1a2 100644
--- a/lxd/storage/load.go
+++ b/lxd/storage/load.go
@@ -128,3 +128,13 @@ func GetPoolByName(state *state.State, name string) (Pool, 
error) {
 
        return &pool, nil
 }
+
+// GetPoolByInstanceName retrieves the pool from the database using the 
instance's project and name.
+func GetPoolByInstanceName(s *state.State, projectName, instanceName string) 
(Pool, error) {
+       poolName, err := s.Cluster.ContainerPool(projectName, instanceName)
+       if err != nil {
+               return nil, err
+       }
+
+       return GetPoolByName(s, poolName)
+}

From a98656fd1a12dbfc6c2be5b7b40eed10ae35808b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:36:18 +0000
Subject: [PATCH 02/13] lxd/container: Links containerCreateFromImage to new
 storage layer

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

diff --git a/lxd/container.go b/lxd/container.go
index f4cfe3fe44..589525ce5e 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -24,6 +24,8 @@ import (
        "github.com/lxc/lxd/lxd/instance/instancetype"
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/lxd/state"
+       storagePools "github.com/lxc/lxd/lxd/storage"
+       storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
        "github.com/lxc/lxd/lxd/sys"
        "github.com/lxc/lxd/lxd/task"
        "github.com/lxc/lxd/shared"
@@ -356,7 +358,7 @@ func containerCreateEmptySnapshot(s *state.State, args 
db.InstanceArgs) (contain
        return c, nil
 }
 
-func containerCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, 
tracker *ioprogress.ProgressTracker) (container, error) {
+func containerCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op 
*operations.Operation) (container, error) {
        s := d.State()
 
        // Get the image properties
@@ -424,11 +426,34 @@ func containerCreateFromImage(d *Daemon, args 
db.InstanceArgs, hash string, trac
                return nil, fmt.Errorf("Error updating image last use date: 
%s", err)
        }
 
-       // Now create the storage from an image
-       err = c.Storage().ContainerCreateFromImage(c, hash, tracker)
-       if err != nil {
-               c.Delete()
-               return nil, errors.Wrap(err, "Create container from image")
+       // Check if we can load new storage layer for pool driver type.
+       pool, err := storagePools.GetPoolByInstanceName(d.State(), c.Project(), 
c.Name())
+       if err != storageDrivers.ErrUnknownDriver {
+               if err != nil {
+                       return nil, errors.Wrap(err, "Load instance storage 
pool")
+               }
+
+               err = pool.CreateInstanceFromImage(c, hash, op)
+               if err != nil {
+                       return nil, errors.Wrap(err, "Create instance from 
image")
+               }
+       } else {
+               metadata := make(map[string]interface{})
+               var tracker *ioprogress.ProgressTracker
+               if op != nil {
+                       tracker = &ioprogress.ProgressTracker{
+                               Handler: func(percent, speed int64) {
+                                       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)
+               if err != nil {
+                       c.Delete()
+                       return nil, errors.Wrap(err, "Create container from 
image")
+               }
        }
 
        // Apply any post-storage configuration

From 7ca2b7f4121ffe10a09a1a1a92deb57f222f1bde Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:36:48 +0000
Subject: [PATCH 03/13] lxd/containers/post: Moves progress tracker into
 containerCreateFromImage

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

diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index 02f05b6c79..0fd29b04b1 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -27,7 +27,6 @@ import (
        "github.com/lxc/lxd/lxd/response"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
-       "github.com/lxc/lxd/shared/ioprogress"
        log "github.com/lxc/lxd/shared/log15"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/osarch"
@@ -137,12 +136,7 @@ func createFromImage(d *Daemon, project string, req 
*api.InstancesPost) response
                        return err
                }
 
-               metadata := make(map[string]interface{})
-               _, err = containerCreateFromImage(d, args, info.Fingerprint, 
&ioprogress.ProgressTracker{
-                       Handler: func(percent, speed int64) {
-                               shared.SetProgressMetadata(metadata, 
"create_container_from_image_unpack", "Unpack", percent, 0, speed)
-                               op.UpdateMetadata(metadata)
-                       }})
+               _, err = containerCreateFromImage(d, args, info.Fingerprint, op)
                return err
        }
 

From c3be23b19bc70bbe5709d6ab00d0b28b83e8eff6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:37:09 +0000
Subject: [PATCH 04/13] lxd/images: Removes old unpackImage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/images.go | 32 --------------------------------
 1 file changed, 32 deletions(-)

diff --git a/lxd/images.go b/lxd/images.go
index 77b543cd06..c43e2c4345 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -107,38 +107,6 @@ var imageAliasCmd = APIEndpoint{
    end for whichever finishes last. */
 var imagePublishLock sync.Mutex
 
-func unpackImage(imagefname string, destpath string, sType storageType, 
runningInUserns bool, tracker *ioprogress.ProgressTracker) error {
-       blockBackend := false
-
-       if sType == storageTypeLvm || sType == storageTypeCeph {
-               blockBackend = true
-       }
-
-       err := shared.Unpack(imagefname, destpath, blockBackend, 
runningInUserns, tracker)
-       if err != nil {
-               return err
-       }
-
-       rootfsPath := fmt.Sprintf("%s/rootfs", destpath)
-       if shared.PathExists(imagefname + ".rootfs") {
-               err = os.MkdirAll(rootfsPath, 0755)
-               if err != nil {
-                       return fmt.Errorf("Error creating rootfs directory")
-               }
-
-               err = shared.Unpack(imagefname+".rootfs", rootfsPath, 
blockBackend, runningInUserns, tracker)
-               if err != nil {
-                       return err
-               }
-       }
-
-       if !shared.PathExists(rootfsPath) {
-               return fmt.Errorf("Image is missing a rootfs: %s", imagefname)
-       }
-
-       return nil
-}
-
 func compressFile(compress string, infile io.Reader, outfile io.Writer) error {
        reproducible := []string{"gzip"}
 

From fe2b8ec35ae8410bfcf6c2458699221162b3a52c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:37:38 +0000
Subject: [PATCH 05/13] lxd/storage/backend/lxd: Implements
 CreateInstanceFromImage

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 3a51642a92..3ac4a05a11 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -11,11 +11,13 @@ import (
        "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"
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/lxd/storage/drivers"
        "github.com/lxc/lxd/lxd/storage/memorypipe"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/ioprogress"
        log "github.com/lxc/lxd/shared/log15"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/logging"
@@ -171,8 +173,75 @@ func (b *lxdBackend) CreateInstanceFromCopy(inst Instance, 
src Instance, snapsho
        return ErrNotImplemented
 }
 
+// createInstanceSymlink creates a symlink in the instance directory to the 
instance's mount path.
+func (b *lxdBackend) createInstanceSymlink(inst Instance, mountPath string) 
error {
+       symlinkPath := inst.Path()
+       if !shared.PathExists(symlinkPath) {
+               err := os.Symlink(mountPath, symlinkPath)
+               if err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
+
+// CreateInstanceFromImage creates a new volume for an instance populated with 
the image requested.
 func (b *lxdBackend) CreateInstanceFromImage(inst Instance, fingerprint 
string, op *operations.Operation) error {
-       return ErrNotImplemented
+       logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
+       logger.Debug("CreateInstanceFromImage started")
+       defer logger.Debug("CreateInstanceFromImage finished")
+
+       volType, err := InstanceTypeToVolumeType(inst.Type())
+       if err != nil {
+               return err
+       }
+
+       revert := true
+       defer func() {
+               if !revert {
+                       return
+               }
+               b.DeleteInstance(inst, op)
+       }()
+
+       filler := func(instanceMountPath string) error {
+               var tracker *ioprogress.ProgressTracker
+               if op != nil { // Not passed when being done as part of 
pre-migration setup.
+                       metadata := make(map[string]interface{})
+                       tracker = &ioprogress.ProgressTracker{
+                               Handler: func(percent, speed int64) {
+                                       shared.SetProgressMetadata(metadata, 
"create_instance_from_image_unpack", "Unpack", percent, 0, speed)
+                                       op.UpdateMetadata(metadata)
+                               }}
+               }
+
+               imagePath := shared.VarPath("images", fingerprint)
+
+               // tomp TODO currently passing false to isBlockBackend 
argument, which only affects
+               // user hint on how to increase disk space if not enough to 
unpack image. Ask about
+               // removing this argument entirely.
+               return ImageUnpack(imagePath, instanceMountPath, false, 
b.state.OS.RunningInUserNS, tracker)
+       }
+
+       vol := b.newVolume(volType, drivers.ContentTypeFS, 
project.Prefix(inst.Project(), inst.Name()), nil)
+       err = b.driver.CreateVolume(vol, filler, op)
+       if err != nil {
+               return err
+       }
+
+       err = b.createInstanceSymlink(inst, vol.MountPath())
+       if err != nil {
+               return err
+       }
+
+       err = inst.TemplateApply("create")
+       if err != nil {
+               return err
+       }
+
+       revert = false
+       return nil
 }
 
 func (b *lxdBackend) CreateInstanceFromMigration(inst Instance, conn 
io.ReadWriteCloser, args migration.SinkArgs, op *operations.Operation) error {
@@ -184,6 +253,10 @@ func (b *lxdBackend) RenameInstance(inst Instance, newName 
string, op *operation
 }
 
 func (b *lxdBackend) DeleteInstance(inst Instance, op *operations.Operation) 
error {
+       logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
+       logger.Debug("DeleteInstance started")
+       defer logger.Debug("DeleteInstance finished")
+
        return ErrNotImplemented
 }
 
@@ -201,7 +274,7 @@ func (b *lxdBackend) BackupInstance(inst Instance, 
targetPath string, optimized
 
 // GetInstanceUsage returns the disk usage of the Instance's root device.
 func (b *lxdBackend) GetInstanceUsage(inst Instance) (int64, error) {
-       logger := logging.AddContext(b.logger, log.Ctx{"instance": inst.Name()})
+       logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("GetInstanceUsage started")
        defer logger.Debug("GetInstanceUsage finished")
 

From 5b00064598537b4f791f16312542f9bbfed6416e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:38:18 +0000
Subject: [PATCH 06/13] lxd/storage/drivers/driver/dir: Switches to using
 volume.CreateMounthPath()

To ensure perms are applied consistently and correctly across all drivers.

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

diff --git a/lxd/storage/drivers/driver_dir.go 
b/lxd/storage/drivers/driver_dir.go
index f50ee8ceef..816664c420 100644
--- a/lxd/storage/drivers/driver_dir.go
+++ b/lxd/storage/drivers/driver_dir.go
@@ -172,9 +172,10 @@ func (d *dir) CreateVolume(vol Volume, filler func(path 
string) error, op *opera
        volID, err := d.getVolID(vol.volType, vol.name)
        if err != nil {
                return err
+
        }
 
-       err = os.MkdirAll(volPath, 0711)
+       err = vol.CreateMountPath()
        if err != nil {
                return err
        }
@@ -286,7 +287,7 @@ func (d *dir) CreateVolumeFromMigration(vol Volume, conn 
io.ReadWriteCloser, vol
                }
 
                snapPath := snapshot.MountPath()
-               err = os.MkdirAll(snapPath, 0711)
+               err = snapshot.CreateMountPath()
                if err != nil {
                        return err
                }
@@ -317,7 +318,7 @@ func (d *dir) CreateVolumeFromMigration(vol Volume, conn 
io.ReadWriteCloser, vol
        volPath := vol.MountPath()
 
        // Finally the actual volume is sent by sender, so create that last.
-       err = os.MkdirAll(volPath, 0711)
+       err = vol.CreateMountPath()
        if err != nil {
                return err
        }
@@ -393,7 +394,7 @@ func (d *dir) CreateVolumeFromCopy(vol Volume, srcVol 
Volume, copySnapshots bool
                        }
 
                        dstSnapPath := dstSnapshot.MountPath()
-                       err = os.MkdirAll(dstSnapPath, 0711)
+                       err = dstSnapshot.CreateMountPath()
                        if err != nil {
                                return err
                        }
@@ -416,7 +417,7 @@ func (d *dir) CreateVolumeFromCopy(vol Volume, srcVol 
Volume, copySnapshots bool
        }
 
        volPath := vol.MountPath()
-       err = os.MkdirAll(volPath, 0711)
+       err = vol.CreateMountPath()
        if err != nil {
                return err
        }
@@ -513,6 +514,7 @@ func (d *dir) RenameVolume(volType VolumeType, volName 
string, newVolName string
                return err
        }
 
+       // tomp TODO check old snapshots dir is removed.
        err = os.MkdirAll(snapshotDir, 0711)
        if err != nil {
                return err
@@ -761,10 +763,12 @@ func (d *dir) CreateVolumeSnapshot(volType VolumeType, 
volName string, newSnapsh
        }
 
        srcPath := GetVolumeMountPath(d.name, volType, volName)
-       snapPath := GetVolumeMountPath(d.name, volType, 
GetSnapshotVolumeName(volName, newSnapshotName))
+       fullSnapName := GetSnapshotVolumeName(volName, newSnapshotName)
+       snapVol := NewVolume(d, d.name, volType, ContentTypeFS, fullSnapName, 
nil)
+       snapPath := snapVol.MountPath()
 
        // Create snapshot directory.
-       err = os.MkdirAll(snapPath, 0711)
+       err = snapVol.CreateMountPath()
        if err != nil {
                return err
        }

From 4e69206d98ac48286cd241bfed55526f039b7d02 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:39:02 +0000
Subject: [PATCH 07/13] lxd/storage/drivers/volume: Adds CreateMountPath

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

diff --git a/lxd/storage/drivers/volume.go b/lxd/storage/drivers/volume.go
index 5dd78a91fa..a9dacb955c 100644
--- a/lxd/storage/drivers/volume.go
+++ b/lxd/storage/drivers/volume.go
@@ -2,6 +2,7 @@ package drivers
 
 import (
        "fmt"
+       "os"
 
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/shared"
@@ -74,6 +75,28 @@ func (v Volume) MountPath() string {
        return GetVolumeMountPath(v.pool, v.volType, v.name)
 }
 
+// CreateMountPath creates the volume's mount path and sets the correct 
permission for the type.
+func (v Volume) CreateMountPath() error {
+       volPath := v.MountPath()
+
+       // Create volume's mount path, with any created directories set to 0711.
+       err := os.MkdirAll(volPath, 0711)
+       if err != nil {
+               return err
+       }
+
+       // Set very restrictive mode 0100 for non-custom and non-image volumes.
+       if v.volType != VolumeTypeCustom && v.volType != VolumeTypeImage {
+               // Set mode of actual volume's mount path.
+               err = os.Chmod(volPath, 0100)
+               if err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
+
 // MountTask runs the supplied task after mounting the volume if needed. If 
the volume was mounted
 // for this then it is unmounted when the task finishes.
 func (v Volume) MountTask(task func(mountPath string, op 
*operations.Operation) error, op *operations.Operation) error {

From b3f97536789205579bee4320b18ecec75b0e9cc5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:39:24 +0000
Subject: [PATCH 08/13] lxd/storage/load: Improves getVolID error when volume
 not found

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 eb7fa6e1a2..6db6f2834a 100644
--- a/lxd/storage/load.go
+++ b/lxd/storage/load.go
@@ -32,7 +32,7 @@ func volIDFuncMake(state *state.State, poolID int64) 
func(volType drivers.Volume
                volID, _, err := 
state.Cluster.StoragePoolNodeVolumeGetTypeByProject("default", volName, 
volTypeID, poolID)
                if err != nil {
                        if err == db.ErrNoSuchObject {
-                               return -1, fmt.Errorf("Volume doesn't exist")
+                               return -1, fmt.Errorf("Failed to get volume ID, 
volume '%s' of type '%s' doesn't exist", volName, volType)
                        }
 
                        return -1, err

From a4cf41b9f00bb7b08bafe0fa735f553bb8b3ff85 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:40:11 +0000
Subject: [PATCH 09/13] lxd/storage/utils: Adds InstanceTypeToVolumeType

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

diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go
index b22e8c1ada..14a40f3e32 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -10,6 +10,7 @@ import (
        "golang.org/x/sys/unix"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/instance/instancetype"
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/lxd/storage/drivers"
        "github.com/lxc/lxd/shared"
@@ -417,6 +418,18 @@ func VolumeTypeToDBType(volType drivers.VolumeType) (int, 
error) {
        return -1, fmt.Errorf("Invalid storage volume type")
 }
 
+// InstanceTypeToVolumeType converts instance type to volume type.
+func InstanceTypeToVolumeType(instType instancetype.Type) (drivers.VolumeType, 
error) {
+       switch instType {
+       case instancetype.Container:
+               return drivers.VolumeTypeContainer, nil
+       case instancetype.VM:
+               return drivers.VolumeTypeVM, nil
+       }
+
+       return "", fmt.Errorf("Invalid instance type")
+}
+
 // VolumeDBCreate creates a volume in the database.
 func VolumeDBCreate(s *state.State, poolName string, volumeName, 
volumeDescription string, volumeTypeName string, snapshot bool, volumeConfig 
map[string]string) error {
        // Convert the volume type name to our internal integer representation.

From b98393ed76969622849b564db154480893cc2387 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:40:22 +0000
Subject: [PATCH 10/13] lxd/storage/utils: Adds ImageUnpack

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

diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go
index 14a40f3e32..c71f69f980 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -15,6 +15,7 @@ import (
        "github.com/lxc/lxd/lxd/storage/drivers"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/ioprogress"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/units"
 )
@@ -696,3 +697,30 @@ func validateVolumeCommonRules() map[string]func(string) 
error {
                },
        }
 }
+
+// ImageUnpack unpacks a filesystem image into the destination path.
+func ImageUnpack(imageFile string, destPath string, blockBackend bool, 
runningInUserns bool, tracker *ioprogress.ProgressTracker) error {
+       err := shared.Unpack(imageFile, destPath, blockBackend, 
runningInUserns, tracker)
+       if err != nil {
+               return err
+       }
+
+       rootfsPath := fmt.Sprintf("%s/rootfs", destPath)
+       if shared.PathExists(imageFile + ".rootfs") {
+               err = os.MkdirAll(rootfsPath, 0755)
+               if err != nil {
+                       return fmt.Errorf("Error creating rootfs directory")
+               }
+
+               err = shared.Unpack(imageFile+".rootfs", rootfsPath, 
blockBackend, runningInUserns, tracker)
+               if err != nil {
+                       return err
+               }
+       }
+
+       if !shared.PathExists(rootfsPath) {
+               return fmt.Errorf("Image is missing a rootfs: %s", imageFile)
+       }
+
+       return nil
+}

From 0432f3521ec39ca3d47386ddced3172ee6dbbf82 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:40:39 +0000
Subject: [PATCH 11/13] test/suites/basic: Updates tests to take into account
 more secure volume perms

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 test/suites/basic.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/suites/basic.sh b/test/suites/basic.sh
index 29dfe6d64b..a3f7334f9e 100644
--- a/test/suites/basic.sh
+++ b/test/suites/basic.sh
@@ -423,7 +423,7 @@ test_basic_usage() {
   lxc profile create unconfined
   lxc profile set unconfined security.privileged true
   lxc init testimage foo2 -p unconfined -s "lxdtest-$(basename "${LXD_DIR}")"
-  [ "$(stat -L -c "%a" "${LXD_DIR}/containers/foo2")" = "700" ]
+  [ "$(stat -L -c "%a" "${LXD_DIR}/containers/foo2")" = "100" ]
   lxc delete foo2
   lxc profile delete unconfined
 

From e93175747e743d0dcbf7adfe7a06e9d66ffa64ee Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 14:41:11 +0000
Subject: [PATCH 12/13] lxd: Updates use of driver.ImageUnpack

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage_btrfs.go     | 2 +-
 lxd/storage_ceph.go      | 2 +-
 lxd/storage_dir.go       | 2 +-
 lxd/storage_lvm.go       | 2 +-
 lxd/storage_lvm_utils.go | 2 +-
 lxd/storage_zfs.go       | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index 85a73b8f7c..ff1eb628f6 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -2008,7 +2008,7 @@ func (s *storageBtrfs) ImageCreate(fingerprint string, 
tracker *ioprogress.Progr
 
        // Unpack the image in imageMntPoint.
        imagePath := shared.VarPath("images", fingerprint)
-       err = unpackImage(imagePath, tmpImageSubvolumeName, storageTypeBtrfs, 
s.s.OS.RunningInUserNS, tracker)
+       err = driver.ImageUnpack(imagePath, tmpImageSubvolumeName, false, 
s.s.OS.RunningInUserNS, tracker)
        if err != nil {
                return err
        }
diff --git a/lxd/storage_ceph.go b/lxd/storage_ceph.go
index 526a02f1a6..846cc91155 100644
--- a/lxd/storage_ceph.go
+++ b/lxd/storage_ceph.go
@@ -2102,7 +2102,7 @@ func (s *storageCeph) ImageCreate(fingerprint string, 
tracker *ioprogress.Progre
 
                // rsync contents into image
                imagePath := shared.VarPath("images", fingerprint)
-               err = unpackImage(imagePath, imageMntPoint, storageTypeCeph, 
s.s.OS.RunningInUserNS, nil)
+               err = driver.ImageUnpack(imagePath, imageMntPoint, true, 
s.s.OS.RunningInUserNS, nil)
                if err != nil {
                        logger.Errorf(`Failed to unpack image for RBD storage 
volume for image "%s" on storage pool "%s": %s`, fingerprint, s.pool.Name, err)
 
diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go
index e005c880d6..844849ae0f 100644
--- a/lxd/storage_dir.go
+++ b/lxd/storage_dir.go
@@ -572,7 +572,7 @@ func (s *storageDir) ContainerCreateFromImage(container 
Instance, imageFingerpri
        }
 
        imagePath := shared.VarPath("images", imageFingerprint)
-       err = unpackImage(imagePath, containerMntPoint, storageTypeDir, 
s.s.OS.RunningInUserNS, nil)
+       err = driver.ImageUnpack(imagePath, containerMntPoint, false, 
s.s.OS.RunningInUserNS, nil)
        if err != nil {
                return errors.Wrap(err, "Unpack image")
        }
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 763c0c5de1..4a05f07206 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -1939,7 +1939,7 @@ func (s *storageLvm) ImageCreate(fingerprint string, 
tracker *ioprogress.Progres
                }
 
                imagePath := shared.VarPath("images", fingerprint)
-               err = unpackImage(imagePath, imageMntPoint, storageTypeLvm, 
s.s.OS.RunningInUserNS, nil)
+               err = driver.ImageUnpack(imagePath, imageMntPoint, true, 
s.s.OS.RunningInUserNS, nil)
                if err != nil {
                        return err
                }
diff --git a/lxd/storage_lvm_utils.go b/lxd/storage_lvm_utils.go
index f782366ad2..56a60c8d11 100644
--- a/lxd/storage_lvm_utils.go
+++ b/lxd/storage_lvm_utils.go
@@ -504,7 +504,7 @@ func (s *storageLvm) containerCreateFromImageLv(c Instance, 
fp string) error {
 
        imagePath := shared.VarPath("images", fp)
        containerMntPoint := driver.GetContainerMountPoint(c.Project(), 
s.pool.Name, containerName)
-       err = unpackImage(imagePath, containerMntPoint, storageTypeLvm, 
s.s.OS.RunningInUserNS, nil)
+       err = driver.ImageUnpack(imagePath, containerMntPoint, true, 
s.s.OS.RunningInUserNS, nil)
        if err != nil {
                logger.Errorf(`Failed to unpack image "%s" into non-thinpool 
LVM storage volume "%s" for container "%s" on storage pool "%s": %s`, 
imagePath, containerMntPoint, containerName, s.pool.Name, err)
                return err
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 0e5d7d3cc9..139fbba671 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -2406,7 +2406,7 @@ func (s *storageZfs) ImageCreate(fingerprint string, 
tracker *ioprogress.Progres
        }
 
        // Unpack the image into the temporary mountpoint.
-       err = unpackImage(imagePath, tmpImageDir, storageTypeZfs, 
s.s.OS.RunningInUserNS, nil)
+       err = driver.ImageUnpack(imagePath, tmpImageDir, false, 
s.s.OS.RunningInUserNS, nil)
        if err != nil {
                return err
        }

From db021c9bfc1761babaed53919fc92b2d43a430ba Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 Nov 2019 16:06:03 +0000
Subject: [PATCH 13/13] lxd/storage/load: Makes volIDFuncMake project aware

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

diff --git a/lxd/storage/load.go b/lxd/storage/load.go
index 6db6f2834a..725a0bf2b7 100644
--- a/lxd/storage/load.go
+++ b/lxd/storage/load.go
@@ -2,6 +2,7 @@ package storage
 
 import (
        "fmt"
+       "strings"
 
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/lxd/operations"
@@ -28,11 +29,21 @@ func volIDFuncMake(state *state.State, poolID int64) 
func(volType drivers.Volume
                        return -1, err
                }
 
-               // TODO add project support in the future by splitting the 
volName by "_".
-               volID, _, err := 
state.Cluster.StoragePoolNodeVolumeGetTypeByProject("default", volName, 
volTypeID, poolID)
+               // It is possible for the project name to be encoded into the 
volume name in the
+               // format <project>_<volume>. However not all volume types 
currently use this
+               // encoding format, so if there is no underscore in the volume 
name then we assume
+               // the project is default.
+               project := "default"
+               volParts := strings.SplitN(volName, "_", 2)
+               if len(volParts) > 1 {
+                       project = volParts[0]
+                       volName = volParts[1]
+               }
+
+               volID, _, err := 
state.Cluster.StoragePoolNodeVolumeGetTypeByProject(project, volName, 
volTypeID, poolID)
                if err != nil {
                        if err == db.ErrNoSuchObject {
-                               return -1, fmt.Errorf("Failed to get volume ID, 
volume '%s' of type '%s' doesn't exist", volName, volType)
+                               return -1, fmt.Errorf("Failed to get volume ID 
for project '%s', volume '%s', type '%s': Volume doesn't exist", project, 
volName, volType)
                        }
 
                        return -1, err
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to