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