The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3396
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) === Signed-off-by: Christian Brauner <[email protected]>
From b1eb7453d3911644a9b6d894de7e6dedd241b17d Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Thu, 8 Jun 2017 22:01:24 +0200 Subject: [PATCH 1/3] zfs: fix container copy Closes #3395. Signed-off-by: Christian Brauner <[email protected]> --- lxd/storage_zfs.go | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go index 37697fe63..dbe421525 100644 --- a/lxd/storage_zfs.go +++ b/lxd/storage_zfs.go @@ -958,7 +958,7 @@ func (s *storageZfs) copyWithSnapshots(target container, source container, paren zfsSendCmd := exec.Command("zfs", args...) targetSnapshotDataset := fmt.Sprintf("%s/containers/%s@snapshot-%s", poolName, targetParentName, targetSnapOnlyName) - zfsRecvCmd := exec.Command("zfs", "receive", targetSnapshotDataset) + zfsRecvCmd := exec.Command("zfs", "receive", "-F", targetSnapshotDataset) zfsRecvCmd.Stdin, _ = zfsSendCmd.StdoutPipe() zfsRecvCmd.Stdout = os.Stdout @@ -1019,8 +1019,9 @@ func (s *storageZfs) ContainerCopy(target container, source container, container return err } + prev := "" + prevSnapOnlyName := "" for i, snap := range snapshots { - prev := "" if i > 0 { prev = snapshots[i-1].Name() } @@ -1031,6 +1032,7 @@ func (s *storageZfs) ContainerCopy(target container, source container, container } _, snapOnlyName, _ := containerGetParentAndSnapshotName(snap.Name()) + prevSnapOnlyName = snapOnlyName newSnapName := fmt.Sprintf("%s/%s", target.Name(), snapOnlyName) targetSnapshot, err := containerLoadByName(s.d, newSnapName) if err != nil { @@ -1043,6 +1045,47 @@ func (s *storageZfs) ContainerCopy(target container, source container, container } } + // send actual container + tmpSnapshotName := fmt.Sprintf("copy-send-%s", uuid.NewRandom().String()) + err = s.zfsPoolVolumeSnapshotCreate(fmt.Sprintf("containers/%s", source.Name()), tmpSnapshotName) + if err != nil { + return err + } + + poolName := s.getOnDiskPoolName() + currentSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, source.Name(), tmpSnapshotName) + args := []string{"send", currentSnapshotDataset} + if prevSnapOnlyName != "" { + parentSnapshotDataset := fmt.Sprintf("%s/containers/%s@snapshot-%s", poolName, source.Name(), prevSnapOnlyName) + args = append(args, "-i", parentSnapshotDataset) + } + + zfsSendCmd := exec.Command("zfs", args...) + targetSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, target.Name(), tmpSnapshotName) + zfsRecvCmd := exec.Command("zfs", "receive", "-F", targetSnapshotDataset) + + zfsRecvCmd.Stdin, _ = zfsSendCmd.StdoutPipe() + zfsRecvCmd.Stdout = os.Stdout + zfsRecvCmd.Stderr = os.Stderr + + err = zfsRecvCmd.Start() + if err != nil { + return err + } + + err = zfsSendCmd.Run() + if err != nil { + return err + } + + err = zfsRecvCmd.Wait() + if err != nil { + return err + } + + s.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", source.Name()), tmpSnapshotName) + s.zfsPoolVolumeSnapshotDestroy(fmt.Sprintf("containers/%s", target.Name()), tmpSnapshotName) + fs := fmt.Sprintf("containers/%s", target.Name()) err = s.zfsPoolVolumeSet(fs, "mountpoint", targetContainerMountPoint) if err != nil { From 17de1869158f22d7a77e6e33f46fa51100af9d1d Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Thu, 8 Jun 2017 22:21:55 +0200 Subject: [PATCH 2/3] storage: {copy,move} bugfixes Signed-off-by: Christian Brauner <[email protected]> --- lxd/migrate.go | 2 +- lxd/storage_btrfs.go | 22 ++++++++++++---------- lxd/storage_migration.go | 33 ++++++++++++++++++--------------- lxd/storage_zfs.go | 27 ++++++++++++++++----------- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/lxd/migrate.go b/lxd/migrate.go index 5fa7d1db2..244ee1d73 100644 --- a/lxd/migrate.go +++ b/lxd/migrate.go @@ -401,7 +401,7 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error { return err } - err = driver.SendWhileRunning(s.fsConn, migrateOp, bwlimit) + err = driver.SendWhileRunning(s.fsConn, migrateOp, bwlimit, s.containerOnly) if err != nil { return abort(err) } diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go index 89f49ff4f..a403b5e8e 100644 --- a/lxd/storage_btrfs.go +++ b/lxd/storage_btrfs.go @@ -1770,7 +1770,7 @@ func (s *btrfsMigrationSourceDriver) send(conn *websocket.Conn, btrfsPath string return err } -func (s *btrfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string) error { +func (s *btrfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string, containerOnly bool) error { _, containerPool := s.container.Storage().GetContainerPoolInfo() containerName := s.container.Name() containersPath := getContainerMountPoint(containerPool, "") @@ -1806,16 +1806,18 @@ func (s *btrfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op * return s.send(conn, migrationSendSnapshot, "", wrapper) } - for i, snap := range s.snapshots { - prev := "" - if i > 0 { - prev = getSnapshotMountPoint(containerPool, s.snapshots[i-1].Name()) - } + if !containerOnly { + for i, snap := range s.snapshots { + prev := "" + if i > 0 { + prev = getSnapshotMountPoint(containerPool, s.snapshots[i-1].Name()) + } - snapMntPoint := getSnapshotMountPoint(containerPool, snap.Name()) - wrapper := StorageProgressReader(op, "fs_progress", snap.Name()) - if err := s.send(conn, snapMntPoint, prev, wrapper); err != nil { - return err + snapMntPoint := getSnapshotMountPoint(containerPool, snap.Name()) + wrapper := StorageProgressReader(op, "fs_progress", snap.Name()) + if err := s.send(conn, snapMntPoint, prev, wrapper); err != nil { + return err + } } } diff --git a/lxd/storage_migration.go b/lxd/storage_migration.go index 4f1e095c5..c49f2b373 100644 --- a/lxd/storage_migration.go +++ b/lxd/storage_migration.go @@ -18,7 +18,7 @@ type MigrationStorageSourceDriver interface { /* send any bits of the container/snapshots that are possible while the * container is still running. */ - SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string) error + SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string, containerOnly bool) error /* send the final bits (e.g. a final delta snapshot for zfs, btrfs, or * do a final rsync) of the fs after the container has been @@ -42,22 +42,25 @@ func (s rsyncStorageSourceDriver) Snapshots() []container { return s.snapshots } -func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string) error { +func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string, containerOnly bool) error { ctName, _, _ := containerGetParentAndSnapshotName(s.container.Name()) - for _, send := range s.snapshots { - ourStart, err := send.StorageStart() - if err != nil { - return err - } - if ourStart { - defer send.StorageStop() - } - path := send.Path() - wrapper := StorageProgressReader(op, "fs_progress", send.Name()) - err = RsyncSend(ctName, shared.AddSlash(path), conn, wrapper, bwlimit) - if err != nil { - return err + if !containerOnly { + for _, send := range s.snapshots { + ourStart, err := send.StorageStart() + if err != nil { + return err + } + if ourStart { + defer send.StorageStop() + } + + path := send.Path() + wrapper := StorageProgressReader(op, "fs_progress", send.Name()) + err = RsyncSend(ctName, shared.AddSlash(path), conn, wrapper, bwlimit) + if err != nil { + return err + } } } diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go index dbe421525..dea7044f5 100644 --- a/lxd/storage_zfs.go +++ b/lxd/storage_zfs.go @@ -2510,7 +2510,7 @@ func (s *zfsMigrationSourceDriver) send(conn *websocket.Conn, zfsName string, zf return err } -func (s *zfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string) error { +func (s *zfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string, containerOnly bool) error { if s.container.IsSnapshot() { _, snapOnlyName, _ := containerGetParentAndSnapshotName(s.container.Name()) snapshotName := fmt.Sprintf("snapshot-%s", snapOnlyName) @@ -2519,18 +2519,19 @@ func (s *zfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *op } lastSnap := "" + if !containerOnly { + for i, snap := range s.zfsSnapshotNames { + prev := "" + if i > 0 { + prev = s.zfsSnapshotNames[i-1] + } - for i, snap := range s.zfsSnapshotNames { - prev := "" - if i > 0 { - prev = s.zfsSnapshotNames[i-1] - } - - lastSnap = snap + lastSnap = snap - wrapper := StorageProgressReader(op, "fs_progress", snap) - if err := s.send(conn, snap, prev, wrapper); err != nil { - return err + wrapper := StorageProgressReader(op, "fs_progress", snap) + if err := s.send(conn, snap, prev, wrapper); err != nil { + return err + } } } @@ -2593,6 +2594,10 @@ func (s *storageZfs) MigrationSource(ct container, containerOnly bool) (Migratio zfs: s, } + if containerOnly { + return &driver, nil + } + /* List all the snapshots in order of reverse creation. The idea here * is that we send the oldest to newest snapshot, hopefully saving on * xfer costs. Then, after all that, we send the container itself. From 4263ec402833cd45b0705e5448a560f610756691 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Thu, 8 Jun 2017 22:32:28 +0200 Subject: [PATCH 3/3] test: add more {copy,migration} tests Signed-off-by: Christian Brauner <[email protected]> --- test/suites/migration.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/suites/migration.sh b/test/suites/migration.sh index 20b75addb..6a75cf4ec 100644 --- a/test/suites/migration.sh +++ b/test/suites/migration.sh @@ -128,27 +128,33 @@ migration() { # Test container only copies lxc init testimage cccp + echo "before" | lxc file push - cccp/blah lxc snapshot cccp lxc snapshot cccp + echo "after" | lxc file push - cccp/blah # Local container only copy. lxc copy cccp udssr --container-only [ "$(lxc info udssr | grep -c snap)" -eq 0 ] + [ "$(lxc file pull udssr/blah -)" = "after" ] lxc delete udssr # Local container with snapshots copy. lxc copy cccp udssr [ "$(lxc info udssr | grep -c snap)" -eq 2 ] + [ "$(lxc file pull udssr/blah -)" = "after" ] lxc delete udssr # Remote container only copy. lxc_remote copy l1:cccp l2:udssr --container-only [ "$(lxc_remote info l2:udssr | grep -c snap)" -eq 0 ] + [ "$(lxc_remote file pull l2:udssr/blah -)" = "after" ] lxc_remote delete l2:udssr # Remote container with snapshots copy. lxc_remote copy l1:cccp l2:udssr [ "$(lxc_remote info l2:udssr | grep -c snap)" -eq 2 ] + [ "$(lxc_remote file pull l2:udssr/blah -)" = "after" ] lxc_remote delete l2:udssr # Remote container only move.
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
