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

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 a2e4eb739269695835fc1db817628a7e95a4b209 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Mon, 27 Jan 2020 20:50:01 +0200
Subject: [PATCH 1/6] lxd/instance: Add NetworkUpdateStatic
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/instance/instance_utils.go | 4 ++++
 lxd/networks.go                | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/lxd/instance/instance_utils.go b/lxd/instance/instance_utils.go
index 4ad0300638..4fa6984ef6 100644
--- a/lxd/instance/instance_utils.go
+++ b/lxd/instance/instance_utils.go
@@ -48,6 +48,10 @@ var Create func(s *state.State, args db.InstanceArgs) 
(Instance, error)
 // network related functions into their own package at this time.
 var NetworkGetLeaseAddresses func(s *state.State, network string, hwaddr 
string) ([]api.InstanceStateNetworkAddress, error)
 
+// NetworkUpdateStatic is linked to main.networkUpdateStatic to limit scope of 
moving
+// network related functions into their own package at this time.
+var NetworkUpdateStatic func(s *state.State, network string) error
+
 // CompareSnapshots 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
diff --git a/lxd/networks.go b/lxd/networks.go
index 8b2458870e..d05fb81214 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -38,6 +38,9 @@ import (
 func init() {
        // Link networkGetLeaseAddresses into instance package.
        instance.NetworkGetLeaseAddresses = networkGetLeaseAddresses
+
+       // Link networkUpdateStatic into instance package.
+       instance.NetworkUpdateStatic = networkUpdateStatic
 }
 
 // Lock to prevent concurent networks creation

From cbd75974b0bfab32e4b4e5f6b3970807e9e4bc6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Mon, 27 Jan 2020 20:50:37 +0200
Subject: [PATCH 2/6] Add maasRename to VM
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/instance/drivers/driver_qemu.go | 35 +++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/lxd/instance/drivers/driver_qemu.go 
b/lxd/instance/drivers/driver_qemu.go
index ef0f5dc99b..e8658aee27 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -3432,6 +3432,41 @@ func (vm *qemu) maasInterfaces(devices 
map[string]map[string]string) ([]maas.Con
        return interfaces, nil
 }
 
+func (vm *qemu) maasRename(newName string) error {
+       maasURL, err := cluster.ConfigGetString(vm.state.Cluster, 
"maas.api.url")
+       if err != nil {
+               return err
+       }
+
+       if maasURL == "" {
+               return nil
+       }
+
+       interfaces, err := vm.maasInterfaces(vm.expandedDevices.CloneNative())
+       if err != nil {
+               return err
+       }
+
+       if len(interfaces) == 0 {
+               return nil
+       }
+
+       if vm.state.MAAS == nil {
+               return fmt.Errorf("Can't perform the operation because MAAS is 
currently unavailable")
+       }
+
+       exists, err := 
vm.state.MAAS.DefinedContainer(project.Prefix(vm.project, vm.name))
+       if err != nil {
+               return err
+       }
+
+       if !exists {
+               return vm.maasUpdate(nil)
+       }
+
+       return vm.state.MAAS.RenameContainer(project.Prefix(vm.project, 
vm.name), project.Prefix(vm.project, newName))
+}
+
 func (vm *qemu) maasDelete() error {
        maasURL, err := cluster.ConfigGetString(vm.state.Cluster, 
"maas.api.url")
        if err != nil {

From 32f264dcca562cec8329edbf067ffd44eddce958 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Mon, 27 Jan 2020 20:50:55 +0200
Subject: [PATCH 3/6] lxd/storage/generic: Don't fail rename on missing path
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/storage/drivers/generic_vfs.go | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/lxd/storage/drivers/generic_vfs.go 
b/lxd/storage/drivers/generic_vfs.go
index 64aea3f035..1c3cdabf2c 100644
--- a/lxd/storage/drivers/generic_vfs.go
+++ b/lxd/storage/drivers/generic_vfs.go
@@ -51,26 +51,28 @@ func genericVFSRenameVolume(d Driver, vol Volume, 
newVolName string, op *operati
        srcVolumePath := GetVolumeMountPath(d.Name(), vol.volType, vol.name)
        dstVolumePath := GetVolumeMountPath(d.Name(), vol.volType, newVolName)
 
-       err := os.Rename(srcVolumePath, dstVolumePath)
-       if err != nil {
-               return errors.Wrapf(err, "Failed to rename '%s' to '%s'", 
srcVolumePath, dstVolumePath)
-       }
-
        revertRename := true
-       defer func() {
-               if !revertRename {
-                       return
+       if shared.PathExists(srcVolumePath) {
+               err := os.Rename(srcVolumePath, dstVolumePath)
+               if err != nil {
+                       return errors.Wrapf(err, "Failed to rename '%s' to 
'%s'", srcVolumePath, dstVolumePath)
                }
 
-               os.Rename(dstVolumePath, srcVolumePath)
-       }()
+               defer func() {
+                       if !revertRename {
+                               return
+                       }
+
+                       os.Rename(dstVolumePath, srcVolumePath)
+               }()
+       }
 
        // And if present, the snapshots too.
        srcSnapshotDir := GetVolumeSnapshotDir(d.Name(), vol.volType, vol.name)
        dstSnapshotDir := GetVolumeSnapshotDir(d.Name(), vol.volType, 
newVolName)
 
        if shared.PathExists(srcSnapshotDir) {
-               err = os.Rename(srcSnapshotDir, dstSnapshotDir)
+               err := os.Rename(srcSnapshotDir, dstSnapshotDir)
                if err != nil {
                        return errors.Wrapf(err, "Failed to rename '%s' to 
'%s'", srcSnapshotDir, dstSnapshotDir)
                }

From 8227dc155bc05948fa85ee6a2057ee11ed264739 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Mon, 27 Jan 2020 20:51:22 +0200
Subject: [PATCH 4/6] lxd/storage/zfs: Fix block mounts
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/storage/drivers/driver_zfs_volumes.go | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/lxd/storage/drivers/driver_zfs_volumes.go 
b/lxd/storage/drivers/driver_zfs_volumes.go
index 0ab3bd9771..7d26064e3c 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -849,7 +849,18 @@ func (d *zfs) MountVolume(vol Volume, op 
*operations.Operation) (bool, error) {
 
        // For block devices, we make them appear.
        if vol.contentType == ContentTypeBlock {
-               err := d.setDatasetProperties(d.dataset(vol, false), 
"volmode=dev")
+               current, err := d.getDatasetProperty(d.dataset(vol, false), 
"volmode")
+               if err != nil {
+                       return false, err
+               }
+
+               // Check if already active.
+               if current == "dev" {
+                       return false, nil
+               }
+
+               // Activate.
+               err = d.setDatasetProperties(d.dataset(vol, false), 
"volmode=dev")
                if err != nil {
                        return false, err
                }
@@ -857,7 +868,7 @@ func (d *zfs) MountVolume(vol Volume, op 
*operations.Operation) (bool, error) {
                // Wait half a second to give udev a chance to kick in.
                time.Sleep(500 * time.Millisecond)
 
-               return false, nil
+               return true, nil
        }
 
        // Check if not already mounted.

From e4bf6710b6e0bf3b687425a2cb92250b728a1488 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Mon, 27 Jan 2020 20:51:27 +0200
Subject: [PATCH 5/6] lxd/storage/zfs: Fix renames
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/storage/drivers/driver_zfs_volumes.go | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/lxd/storage/drivers/driver_zfs_volumes.go 
b/lxd/storage/drivers/driver_zfs_volumes.go
index 7d26064e3c..c8c710c80e 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -949,9 +949,11 @@ func (d *zfs) RenameVolume(vol Volume, newVolName string, 
op *operations.Operati
        })
 
        // Update the mountpoints.
-       err = d.setDatasetProperties(d.dataset(newVol, false), 
fmt.Sprintf("mountpoint=%s", newVol.MountPath()))
-       if err != nil {
-               return err
+       if vol.contentType == ContentTypeFS {
+               err = d.setDatasetProperties(d.dataset(newVol, false), 
fmt.Sprintf("mountpoint=%s", newVol.MountPath()))
+               if err != nil {
+                       return err
+               }
        }
 
        // For VM images, create a filesystem volume too.

From 46d4b25b60c7ec1074361ba97e155eb3653e7fcf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Mon, 27 Jan 2020 20:51:36 +0200
Subject: [PATCH 6/6] lxd/vm: Implement Rename
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/instance/drivers/driver_qemu.go | 136 +++++++++++++++++++++++++++-
 1 file changed, 135 insertions(+), 1 deletion(-)

diff --git a/lxd/instance/drivers/driver_qemu.go 
b/lxd/instance/drivers/driver_qemu.go
index e8658aee27..af48094b85 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -1776,7 +1776,141 @@ func (vm *qemu) Backups() ([]backup.Backup, error) {
 
 // Rename the instance.
 func (vm *qemu) Rename(newName string) error {
-       return fmt.Errorf("Rename Not implemented")
+       oldName := vm.Name()
+       ctxMap := log.Ctx{
+               "project":   vm.project,
+               "name":      vm.name,
+               "created":   vm.creationDate,
+               "ephemeral": vm.ephemeral,
+               "used":      vm.lastUsedDate,
+               "newname":   newName}
+
+       logger.Info("Renaming instance", ctxMap)
+
+       // Sanity checks.
+       if !vm.IsSnapshot() && !shared.ValidHostname(newName) {
+               return fmt.Errorf("Invalid instance name")
+       }
+
+       if vm.IsRunning() {
+               return fmt.Errorf("Renaming of running instance not allowed")
+       }
+
+       // Clean things up.
+       vm.cleanup()
+
+       // Check if we can load new storage layer for pool driver type.
+       pool, err := storagePools.GetPoolByInstance(vm.state, vm)
+       if err != nil {
+               return errors.Wrap(err, "Load instance storage pool")
+       }
+
+       if vm.IsSnapshot() {
+               _, newSnapName, _ := 
shared.InstanceGetParentAndSnapshotName(newName)
+               err = pool.RenameInstanceSnapshot(vm, newSnapName, nil)
+               if err != nil {
+                       return errors.Wrap(err, "Rename instance snapshot")
+               }
+       } else {
+               err = pool.RenameInstance(vm, newName, nil)
+               if err != nil {
+                       return errors.Wrap(err, "Rename instance")
+               }
+       }
+
+       if !vm.IsSnapshot() {
+               // Rename all the instance snapshot database entries.
+               results, err := 
vm.state.Cluster.ContainerGetSnapshots(vm.project, oldName)
+               if err != nil {
+                       logger.Error("Failed to get instance snapshots", ctxMap)
+                       return err
+               }
+
+               for _, sname := range results {
+                       // Rename the snapshot.
+                       oldSnapName := strings.SplitN(sname, 
shared.SnapshotDelimiter, 2)[1]
+                       baseSnapName := filepath.Base(sname)
+                       err := vm.state.Cluster.Transaction(func(tx 
*db.ClusterTx) error {
+                               return tx.InstanceSnapshotRename(vm.project, 
oldName, oldSnapName, baseSnapName)
+                       })
+                       if err != nil {
+                               logger.Error("Failed renaming snapshot", ctxMap)
+                               return err
+                       }
+               }
+       }
+
+       // Rename the instance database entry.
+       err = vm.state.Cluster.Transaction(func(tx *db.ClusterTx) error {
+               if vm.IsSnapshot() {
+                       oldParts := strings.SplitN(oldName, 
shared.SnapshotDelimiter, 2)
+                       newParts := strings.SplitN(newName, 
shared.SnapshotDelimiter, 2)
+                       return tx.InstanceSnapshotRename(vm.project, 
oldParts[0], oldParts[1], newParts[1])
+               }
+
+               return tx.InstanceRename(vm.project, oldName, newName)
+       })
+       if err != nil {
+               logger.Error("Failed renaming instance", ctxMap)
+               return err
+       }
+
+       // Rename the logging path.
+       os.RemoveAll(shared.LogPath(newName))
+       if shared.PathExists(vm.LogPath()) {
+               err := os.Rename(vm.LogPath(), shared.LogPath(newName))
+               if err != nil {
+                       logger.Error("Failed renaming instance", ctxMap)
+                       return err
+               }
+       }
+
+       // Rename the MAAS entry.
+       if !vm.IsSnapshot() {
+               err = vm.maasRename(newName)
+               if err != nil {
+                       return err
+               }
+       }
+
+       // Rename the backups.
+       backups, err := vm.Backups()
+       if err != nil {
+               return err
+       }
+
+       for _, backup := range backups {
+               backupName := strings.Split(backup.Name(), "/")[1]
+               newName := fmt.Sprintf("%s/%s", newName, backupName)
+
+               err = backup.Rename(newName)
+               if err != nil {
+                       return err
+               }
+       }
+
+       // Set the new name in the struct.
+       vm.name = newName
+
+       // Update lease files.
+       instance.NetworkUpdateStatic(vm.state, "")
+
+       logger.Info("Renamed instance", ctxMap)
+
+       if vm.IsSnapshot() {
+               vm.state.Events.SendLifecycle(vm.project, 
"virtual-machine-snapshot-renamed",
+                       fmt.Sprintf("/1.0/virtual-machines/%s", oldName), 
map[string]interface{}{
+                               "new_name":      newName,
+                               "snapshot_name": oldName,
+                       })
+       } else {
+               vm.state.Events.SendLifecycle(vm.project, 
"virtual-machine-renamed",
+                       fmt.Sprintf("/1.0/virtual-machines/%s", oldName), 
map[string]interface{}{
+                               "new_name": newName,
+                       })
+       }
+
+       return nil
 }
 
 // Update the instance config.
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to