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

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) ===
This lays the ground work for linking createFromCopy to the new storage layer's CreateInstanceFromCopy function.
From 74baafdb9d7cd6bdf5fc9f45889af2ad7eed5c84 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 19 Nov 2019 10:46:59 +0000
Subject: [PATCH 1/5] lxd/container: container to instance renames, comment
 improvements

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

diff --git a/lxd/container.go b/lxd/container.go
index fde7831bac..626245a8ac 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -320,7 +320,7 @@ func instanceCreateAsEmpty(d *Daemon, args db.InstanceArgs) 
(Instance, error) {
        }
 
        // Apply any post-storage configuration.
-       err = containerConfigureInternal(d.State(), inst)
+       err = instanceConfigureInternal(d.State(), inst)
        if err != nil {
                return nil, err
        }
@@ -561,7 +561,7 @@ func instanceCreateFromImage(d *Daemon, args 
db.InstanceArgs, hash string, op *o
        }
 
        // Apply any post-storage configuration.
-       err = containerConfigureInternal(d.State(), inst)
+       err = instanceConfigureInternal(d.State(), inst)
        if err != nil {
                return nil, errors.Wrap(err, "Configure instance")
        }
@@ -575,7 +575,7 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
        var err error
 
        if refresh {
-               // Load the target container
+               // Load the target instance.
                ct, err = instanceLoadByProjectAndName(s, args.Project, 
args.Name)
                if err != nil {
                        refresh = false
@@ -583,7 +583,7 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
        }
 
        if !refresh {
-               // Create the container.
+               // Create the instance.
                ct, err = instanceCreateInternal(s, args)
                if err != nil {
                        return nil, err
@@ -591,12 +591,11 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
        }
 
        if refresh && ct.IsRunning() {
-               return nil, fmt.Errorf("Cannot refresh a running container")
+               return nil, fmt.Errorf("Cannot refresh a running instance")
        }
 
-       // At this point we have already figured out the parent
-       // container's root disk device so we can simply
-       // retrieve it from the expanded devices.
+       // At this point we have already figured out the parent container's 
root disk device so we
+       // can simply retrieve it from the expanded devices.
        parentStoragePool := ""
        parentExpandedDevices := ct.ExpandedDevices()
        parentLocalRootDiskDeviceKey, parentLocalRootDiskDevice, _ := 
shared.GetRootDiskDevice(parentExpandedDevices.CloneNative())
@@ -604,18 +603,18 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                parentStoragePool = parentLocalRootDiskDevice["pool"]
        }
 
-       csList := []*Instance{}
+       snapList := []*Instance{}
        var snapshots []Instance
 
        if !containerOnly {
                if refresh {
-                       // Compare snapshots
-                       syncSnapshots, deleteSnapshots, err := 
containerCompareSnapshots(sourceContainer, ct)
+                       // Compare snapshots.
+                       syncSnapshots, deleteSnapshots, err := 
instanceCompareSnapshots(sourceContainer, ct)
                        if err != nil {
                                return nil, err
                        }
 
-                       // Delete extra snapshots
+                       // Delete extra snapshots first.
                        for _, snap := range deleteSnapshots {
                                err := snap.Delete()
                                if err != nil {
@@ -623,10 +622,10 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                                }
                        }
 
-                       // Only care about the snapshots that need updating
+                       // Only care about the snapshots that need updating.
                        snapshots = syncSnapshots
                } else {
-                       // Get snapshots of source container
+                       // Get snapshots of source instance.
                        snapshots, err = sourceContainer.Snapshots()
                        if err != nil {
                                ct.Delete()
@@ -638,7 +637,7 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                for _, snap := range snapshots {
                        fields := strings.SplitN(snap.Name(), 
shared.SnapshotDelimiter, 2)
 
-                       // Ensure that snapshot and parent container have the
+                       // Ensure that snapshot and parent instance have the
                        // same storage pool in their local root disk device.
                        // If the root disk device for the snapshot comes from a
                        // profile on the new instance as well we don't need to
@@ -681,7 +680,7 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                                return nil, err
                        }
 
-                       // Restore snapshot creation date
+                       // Restore snapshot creation date.
                        err = s.Cluster.ContainerCreationUpdate(cs.ID(), 
snap.CreationDate())
                        if err != nil {
                                if !refresh {
@@ -691,11 +690,11 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                                return nil, err
                        }
 
-                       csList = append(csList, &cs)
+                       snapList = append(snapList, &cs)
                }
        }
 
-       // Now clone or refresh the storage
+       // Now clone or refresh the storage.
        if refresh {
                err = ct.Storage().ContainerRefresh(ct, sourceContainer, 
snapshots)
                if err != nil {
@@ -713,7 +712,7 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
        }
 
        // Apply any post-storage configuration.
-       err = containerConfigureInternal(s, ct)
+       err = instanceConfigureInternal(s, ct)
        if err != nil {
                if !refresh {
                        ct.Delete()
@@ -723,9 +722,9 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
        }
 
        if !containerOnly {
-               for _, cs := range csList {
+               for _, snap := range snapList {
                        // Apply any post-storage configuration.
-                       err = containerConfigureInternal(s, *cs)
+                       err = instanceConfigureInternal(s, *snap)
                        if err != nil {
                                if !refresh {
                                        ct.Delete()
@@ -1051,7 +1050,8 @@ func instanceCreateInternal(s *state.State, args 
db.InstanceArgs) (Instance, err
        return inst, nil
 }
 
-func containerConfigureInternal(state *state.State, c Instance) error {
+// instanceConfigureInternal applies quota set in volatile "apply_quota" and 
writes a backup file.
+func instanceConfigureInternal(state *state.State, c Instance) error {
        // Find the root device
        rootDiskDeviceKey, rootDiskDevice, err := 
shared.GetRootDiskDevice(c.ExpandedDevices().CloneNative())
        if err != nil {
@@ -1339,44 +1339,57 @@ func instanceLoad(s *state.State, args db.InstanceArgs, 
profiles []api.Profile)
        return inst, nil
 }
 
-func containerCompareSnapshots(source Instance, target Instance) ([]Instance, 
[]Instance, error) {
-       // Get the source snapshots
+// instanceCompareSnapshots returns a list of snapshots to sync to the target 
and a list of
+// snapshots to remove from the target. A snapshot will be marked as "to sync" 
if it either doesn't
+// exist in the target or its creation date is different to the source. A 
snapshot will be marked
+// as "to delete" if it doesn't exist in the source or creation date is 
different to the source.
+func instanceCompareSnapshots(source Instance, target Instance) ([]Instance, 
[]Instance, error) {
+       // Get the source snapshots.
        sourceSnapshots, err := source.Snapshots()
        if err != nil {
                return nil, nil, err
        }
 
-       // Get the target snapshots
+       // Get the target snapshots.
        targetSnapshots, err := target.Snapshots()
        if err != nil {
                return nil, nil, err
        }
 
-       // Compare source and target
+       // Compare source and target.
        sourceSnapshotsTime := map[string]time.Time{}
        targetSnapshotsTime := map[string]time.Time{}
 
        toDelete := []Instance{}
        toSync := []Instance{}
 
+       // Generate a list of source snapshot creation dates.
        for _, snap := range sourceSnapshots {
                _, snapName, _ := 
shared.ContainerGetParentAndSnapshotName(snap.Name())
 
                sourceSnapshotsTime[snapName] = snap.CreationDate()
        }
 
+       // Generate a list of target snapshot creation times, if the source 
doesn't contain the
+       // the snapshot or the creation time is different on the source then 
add the target snapshot
+       // to the "to delete" list.
        for _, snap := range targetSnapshots {
                _, snapName, _ := 
shared.ContainerGetParentAndSnapshotName(snap.Name())
 
                targetSnapshotsTime[snapName] = snap.CreationDate()
                existDate, exists := sourceSnapshotsTime[snapName]
                if !exists {
+                       // Snapshot doesn't exist in source, mark it for 
deletion on target.
                        toDelete = append(toDelete, snap)
                } else if existDate != snap.CreationDate() {
+                       // Snapshot creation date is different in source, mark 
it for deletion on
+                       // target.
                        toDelete = append(toDelete, snap)
                }
        }
 
+       // For each of the source snapshots, decide whether it needs to be 
synced or not based on
+       // whether it already exists in the target and whether the creation 
dates match.
        for _, snap := range sourceSnapshots {
                _, snapName, _ := 
shared.ContainerGetParentAndSnapshotName(snap.Name())
 

From 76a5ef29c3b46f441e56595eb29b418f1d0da528 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 19 Nov 2019 10:47:21 +0000
Subject: [PATCH 2/5] lxd/containers/post: Adds instances field to response
 from createFromCopy

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

diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index 976be3a618..9abf1a4727 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -612,7 +612,8 @@ func createFromCopy(d *Daemon, project string, req 
*api.InstancesPost) response.
        }
 
        resources := map[string][]string{}
-       resources["containers"] = []string{req.Name, req.Source.Source}
+       resources["instances"] = []string{req.Name, req.Source.Source}
+       resources["containers"] = resources["instances"] // Populate old field 
name.
 
        op, err := operations.OperationCreate(d.State(), targetProject, 
operations.OperationClassTask, db.OperationContainerCreate, resources, nil, 
run, nil, nil)
        if err != nil {

From e5b8f8fde8a05644d7e099255d18e49f2668b2be Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 19 Nov 2019 12:04:37 +0000
Subject: [PATCH 3/5] lxd/container: instanceCreateAsCopy rename and revertion
 logic

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

diff --git a/lxd/container.go b/lxd/container.go
index 626245a8ac..37ca7929e4 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -570,34 +570,44 @@ func instanceCreateFromImage(d *Daemon, args 
db.InstanceArgs, hash string, op *o
        return inst, nil
 }
 
-func containerCreateAsCopy(s *state.State, args db.InstanceArgs, 
sourceContainer Instance, containerOnly bool, refresh bool) (Instance, error) {
-       var ct Instance
+func instanceCreateAsCopy(s *state.State, args db.InstanceArgs, sourceInst 
Instance, instanceOnly bool, refresh bool) (Instance, error) {
+       var inst, revertInst Instance
        var err error
 
+       defer func() {
+               if revertInst == nil {
+                       return
+               }
+
+               revertInst.Delete()
+       }()
+
        if refresh {
                // Load the target instance.
-               ct, err = instanceLoadByProjectAndName(s, args.Project, 
args.Name)
+               inst, err = instanceLoadByProjectAndName(s, args.Project, 
args.Name)
                if err != nil {
-                       refresh = false
+                       refresh = false // Instance doesn't exist, so switch to 
copy mode.
+               }
+
+               if inst.IsRunning() {
+                       return nil, fmt.Errorf("Cannot refresh a running 
instance")
                }
        }
 
+       // If we are not in refresh mode, then create a new instance as we are 
in copy mode.
        if !refresh {
                // Create the instance.
-               ct, err = instanceCreateInternal(s, args)
+               inst, err = instanceCreateInternal(s, args)
                if err != nil {
                        return nil, err
                }
-       }
-
-       if refresh && ct.IsRunning() {
-               return nil, fmt.Errorf("Cannot refresh a running instance")
+               revertInst = inst
        }
 
        // At this point we have already figured out the parent container's 
root disk device so we
        // can simply retrieve it from the expanded devices.
        parentStoragePool := ""
-       parentExpandedDevices := ct.ExpandedDevices()
+       parentExpandedDevices := inst.ExpandedDevices()
        parentLocalRootDiskDeviceKey, parentLocalRootDiskDevice, _ := 
shared.GetRootDiskDevice(parentExpandedDevices.CloneNative())
        if parentLocalRootDiskDeviceKey != "" {
                parentStoragePool = parentLocalRootDiskDevice["pool"]
@@ -606,10 +616,10 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
        snapList := []*Instance{}
        var snapshots []Instance
 
-       if !containerOnly {
+       if !instanceOnly {
                if refresh {
                        // Compare snapshots.
-                       syncSnapshots, deleteSnapshots, err := 
instanceCompareSnapshots(sourceContainer, ct)
+                       syncSnapshots, deleteSnapshots, err := 
instanceCompareSnapshots(sourceInst, inst)
                        if err != nil {
                                return nil, err
                        }
@@ -626,10 +636,8 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                        snapshots = syncSnapshots
                } else {
                        // Get snapshots of source instance.
-                       snapshots, err = sourceContainer.Snapshots()
+                       snapshots, err = sourceInst.Snapshots()
                        if err != nil {
-                               ct.Delete()
-
                                return nil, err
                        }
                }
@@ -656,11 +664,11 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                                }
                        }
 
-                       newSnapName := fmt.Sprintf("%s/%s", ct.Name(), 
fields[1])
-                       csArgs := db.InstanceArgs{
+                       newSnapName := fmt.Sprintf("%s/%s", inst.Name(), 
fields[1])
+                       snapInstArgs := db.InstanceArgs{
                                Architecture: snap.Architecture(),
                                Config:       snap.LocalConfig(),
-                               Type:         sourceContainer.Type(),
+                               Type:         sourceInst.Type(),
                                Snapshot:     true,
                                Devices:      snapDevices,
                                Description:  snap.Description(),
@@ -671,71 +679,52 @@ func containerCreateAsCopy(s *state.State, args 
db.InstanceArgs, sourceContainer
                        }
 
                        // Create the snapshots.
-                       cs, err := instanceCreateInternal(s, csArgs)
+                       snapInst, err := instanceCreateInternal(s, snapInstArgs)
                        if err != nil {
-                               if !refresh {
-                                       ct.Delete()
-                               }
-
                                return nil, err
                        }
 
                        // Restore snapshot creation date.
-                       err = s.Cluster.ContainerCreationUpdate(cs.ID(), 
snap.CreationDate())
+                       err = s.Cluster.ContainerCreationUpdate(snapInst.ID(), 
snap.CreationDate())
                        if err != nil {
-                               if !refresh {
-                                       ct.Delete()
-                               }
-
                                return nil, err
                        }
 
-                       snapList = append(snapList, &cs)
+                       snapList = append(snapList, &snapInst)
                }
        }
 
        // Now clone or refresh the storage.
        if refresh {
-               err = ct.Storage().ContainerRefresh(ct, sourceContainer, 
snapshots)
+               err = inst.Storage().ContainerRefresh(inst, sourceInst, 
snapshots)
                if err != nil {
                        return nil, err
                }
        } else {
-               err = ct.Storage().ContainerCopy(ct, sourceContainer, 
containerOnly)
+               err = inst.Storage().ContainerCopy(inst, sourceInst, 
instanceOnly)
                if err != nil {
-                       if !refresh {
-                               ct.Delete()
-                       }
-
                        return nil, err
                }
        }
 
        // Apply any post-storage configuration.
-       err = instanceConfigureInternal(s, ct)
+       err = instanceConfigureInternal(s, inst)
        if err != nil {
-               if !refresh {
-                       ct.Delete()
-               }
-
                return nil, err
        }
 
-       if !containerOnly {
+       if !instanceOnly {
                for _, snap := range snapList {
                        // Apply any post-storage configuration.
                        err = instanceConfigureInternal(s, *snap)
                        if err != nil {
-                               if !refresh {
-                                       ct.Delete()
-                               }
-
                                return nil, err
                        }
                }
        }
 
-       return ct, nil
+       revertInst = nil
+       return inst, nil
 }
 
 func containerCreateAsSnapshot(s *state.State, args db.InstanceArgs, 
sourceInstance Instance) (Instance, error) {

From 5eb355c0ace37a8a502061876f8175d680b943e6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 19 Nov 2019 12:05:23 +0000
Subject: [PATCH 4/5] lxd/container: instanceCreateInternal comment

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

diff --git a/lxd/container.go b/lxd/container.go
index 37ca7929e4..55aaed404c 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -820,6 +820,7 @@ func containerCreateAsSnapshot(s *state.State, args 
db.InstanceArgs, sourceInsta
        return c, nil
 }
 
+// instanceCreateInternal creates an instance record and storage volume record 
in the database.
 func instanceCreateInternal(s *state.State, args db.InstanceArgs) (Instance, 
error) {
        // Set default values.
        if args.Project == "" {

From 97cda101269d6892bda8fd3f2615a69c4c4494b0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 19 Nov 2019 12:05:39 +0000
Subject: [PATCH 5/5] lxd/containers/post: instanceCreateAsCopy usage

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

diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index 9abf1a4727..dacc135db2 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -604,7 +604,7 @@ func createFromCopy(d *Daemon, project string, req 
*api.InstancesPost) response.
 
        run := func(op *operations.Operation) error {
                instanceOnly := req.Source.InstanceOnly || 
req.Source.ContainerOnly
-               _, err := containerCreateAsCopy(d.State(), args, source, 
instanceOnly, req.Source.Refresh)
+               _, err := instanceCreateAsCopy(d.State(), args, source, 
instanceOnly, req.Source.Refresh)
                if err != nil {
                        return err
                }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to