[lxc-devel] [lxd/master] lxd/patches: Handle btrfs snapshots properly
stgraber on Github
lxc-bot at linuxcontainers.org
Wed Jun 19 00:57:51 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 370 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190618/02c5bbd1/attachment.bin>
-------------- next part --------------
From 8861340d4ffe59218b328e4d50ff0f2d38a52593 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 18 Jun 2019 20:57:05 -0400
Subject: [PATCH] lxd/patches: Handle btrfs snapshots properly
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #5855
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/patches.go | 113 ++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 106 insertions(+), 7 deletions(-)
diff --git a/lxd/patches.go b/lxd/patches.go
index 8b7cf993a8..8ddc9f1449 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
stdlog "log"
"os"
+ "os/exec"
"path/filepath"
"strings"
"syscall"
@@ -72,6 +73,7 @@ var patches = []patch{
{name: "fix_lvm_pool_volume_names", run: patchRenameCustomVolumeLVs},
{name: "storage_api_rename_container_snapshots_dir_again", run: patchStorageApiRenameContainerSnapshotsDir},
{name: "storage_api_rename_container_snapshots_links_again", run: patchStorageApiUpdateContainerSnapshots},
+ {name: "storage_api_rename_container_snapshots_dir_again_again", run: patchStorageApiRenameContainerSnapshotsDir},
}
type patch struct {
@@ -3260,8 +3262,7 @@ func patchMoveBackups(name string, d *Daemon) error {
func patchStorageApiRenameContainerSnapshotsDir(name string, d *Daemon) error {
pools, err := d.cluster.StoragePools()
if err != nil && err == db.ErrNoSuchObject {
- // No pool was configured in the previous update. So we're on a
- // pristine LXD instance.
+ // No pool was configured so we're on a pristine LXD instance.
return nil
} else if err != nil {
// Database is screwed.
@@ -3269,7 +3270,9 @@ func patchStorageApiRenameContainerSnapshotsDir(name string, d *Daemon) error {
return err
}
+ // Iterate through all configured pools
for _, poolName := range pools {
+ // Make sure the pool is mounted
pool, err := storagePoolInit(d.State(), poolName)
if err != nil {
return err
@@ -3284,15 +3287,111 @@ func patchStorageApiRenameContainerSnapshotsDir(name string, d *Daemon) error {
defer pool.StoragePoolUmount()
}
+ // Figure out source/target path
containerSnapshotDirOld := shared.VarPath("storage-pools", poolName, "snapshots")
containerSnapshotDirNew := shared.VarPath("storage-pools", poolName, "containers-snapshots")
- err = shared.FileMove(containerSnapshotDirOld, containerSnapshotDirNew)
- if err != nil {
- if os.IsNotExist(err) {
- continue
+ if !shared.PathExists(containerSnapshotDirOld) {
+ continue
+ }
+
+ if !shared.PathExists(containerSnapshotDirNew) {
+ // Simple and easy rename (common path)
+ err = os.Rename(containerSnapshotDirOld, containerSnapshotDirNew)
+ if err != nil {
+ return err
+ }
+ } else {
+ // Check if btrfs might have been used
+ hasBtrfs := false
+ _, err = exec.LookPath("btrfs")
+ if err == nil {
+ hasBtrfs = true
}
- return err
+ // Get all containers
+ containersDir, err := os.Open(shared.VarPath("storage-pools", poolName, "snapshots"))
+ if err != nil {
+ return err
+ }
+ defer containersDir.Close()
+
+ entries, err := containersDir.Readdirnames(-1)
+ if err != nil {
+ return err
+ }
+
+ for _, entry := range entries {
+ // Create the target (straight rename won't work with btrfs)
+ if !shared.PathExists(filepath.Join(containerSnapshotDirNew, entry)) {
+ err = os.Mkdir(filepath.Join(containerSnapshotDirNew, entry), 0700)
+ if err != nil {
+ return err
+ }
+ }
+
+ // Get all snapshots
+ snapshotsDir, err := os.Open(shared.VarPath("storage-pools", poolName, "snapshots", entry))
+ if err != nil {
+ return err
+ }
+ defer snapshotsDir.Close()
+
+ snaps, err := snapshotsDir.Readdirnames(-1)
+ if err != nil {
+ return err
+ }
+
+ // Disable the read-only properties
+ if hasBtrfs {
+ path := snapshotsDir.Name()
+ subvols, _ := btrfsSubVolumesGet(path)
+ for _, subvol := range subvols {
+ subvol = filepath.Join(path, subvol)
+ newSubvol := filepath.Join(shared.VarPath("storage-pools", poolName, "containers-snapshots", entry), subvol)
+
+ if !btrfsSubVolumeIsRo(subvol) {
+ continue
+ }
+
+ btrfsSubVolumeMakeRw(subvol)
+ defer btrfsSubVolumeMakeRo(newSubvol)
+ }
+ }
+
+ // Rename the snapshots
+ for _, snap := range snaps {
+ err = os.Rename(filepath.Join(containerSnapshotDirOld, entry, snap), filepath.Join(containerSnapshotDirNew, entry, snap))
+ if err != nil {
+ return err
+ }
+ }
+
+ // Cleanup
+ err = os.Remove(snapshotsDir.Name())
+ if err != nil {
+ if hasBtrfs {
+ err1 := btrfsSubVolumeDelete(snapshotsDir.Name())
+ if err1 != nil {
+ return err
+ }
+ } else {
+ return err
+ }
+ }
+ }
+
+ // Cleanup
+ err = os.Remove(containersDir.Name())
+ if err != nil {
+ if hasBtrfs {
+ err1 := btrfsSubVolumeDelete(containersDir.Name())
+ if err1 != nil {
+ return err
+ }
+ } else {
+ return err
+ }
+ }
}
}
More information about the lxc-devel
mailing list