Skip to content

Commit

Permalink
refactor the lvm pool implementation
Browse files Browse the repository at this point in the history
- add proper source and target so we can add more pool implementations later
- handle deprecation of top level path properly
- less checks, lets libvirt handle it
- add acceptance tests
- refactor the test helper block device creation out of domain
- add docs
  • Loading branch information
dmacvicar committed Sep 28, 2024
1 parent 74d3cac commit fd7ac21
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 131 deletions.
10 changes: 9 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ require (
github.com/coreos/go-systemd/v22 v22.0.0 // indirect
github.com/coreos/ignition/v2 v2.14.0 // indirect
github.com/coreos/vcontext v0.0.0-20211021162308-f1dbbca7bef4 // indirect
github.com/diskfs/go-diskfs v1.4.2 // indirect
github.com/djherbis/times v1.6.0 // indirect
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
Expand All @@ -52,6 +55,7 @@ require (
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/hooklift/assert v0.0.0-20170704181755-9d1defd6d214 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
Expand All @@ -60,8 +64,12 @@ require (
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/xattr v0.4.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/vincent-petithory/dataurl v1.0.0 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
Expand All @@ -88,7 +96,7 @@ replace git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110

replace golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce => github.com/dmacvicar/golang-x-crypto v0.0.0-20220126233154-a96af8f07497

go 1.22.0
go 1.23

toolchain go1.23.1

Expand Down
21 changes: 21 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,14 @@ github.com/digitalocean/go-libvirt v0.0.0-20221205150000-2939327a8519 h1:OpkN/n4
github.com/digitalocean/go-libvirt v0.0.0-20221205150000-2939327a8519/go.mod h1:WyJJyfmJ0gWJvjV+ZH4DOgtOYZc1KOvYyBXWCLKxsUU=
github.com/digitalocean/go-libvirt v0.0.0-20240916165608-bff44a349d9d h1:3lleylIw0Dvrlff8+3c+xp0MboNcRz9tMinZNeiGFpc=
github.com/digitalocean/go-libvirt v0.0.0-20240916165608-bff44a349d9d/go.mod h1:+tYha+y/luhAZImNm1TtQjBE2NWEtP5HDLyE5XG+RNA=
github.com/diskfs/go-diskfs v1.4.2 h1:khBr9RTkqAZFaMYK7PP8NooL30hqj3bSgRmj3Ouguls=
github.com/diskfs/go-diskfs v1.4.2/go.mod h1:ss1uAUBhgDdEOewZFDWWpYqJFjNPbK7hYSjRoQE+D94=
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
github.com/dmacvicar/terraform-provider-ignition/v2 v2.1.3-0.20210701165004-13acf61ca184 h1:z9nAMxjTxJXAOmGWMvW5SS0xUwCEJNVjfTesp+07ynE=
github.com/dmacvicar/terraform-provider-ignition/v2 v2.1.3-0.20210701165004-13acf61ca184/go.mod h1:pToe90z63vSP7LIYtZ85Q+g88WvRmdNsg73YZYJZg64=
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY=
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down Expand Up @@ -144,6 +150,7 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
Expand Down Expand Up @@ -345,6 +352,8 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF
github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
Expand Down Expand Up @@ -412,11 +421,16 @@ github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pin/tftp v2.1.0+incompatible/go.mod h1:xVpZOMCXTy+A5QMjEVN0Glwa1sUvaJhFXbr/aAxuxGY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE=
github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
Expand All @@ -427,6 +441,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af h1:Sp5TG9f7K39yfB+If0vjp97vuT74F72r8hfRpP8jLU0=
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
Expand All @@ -450,6 +466,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/vincent-petithory/dataurl v0.0.0-20160330182126-9a301d65acbb/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI=
Expand Down Expand Up @@ -650,8 +668,11 @@ golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
163 changes: 163 additions & 0 deletions libvirt/helper/test/temp_loop_dev.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package test

import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)

type TempBlockDevice struct {
TempFile string
LoopDevice string
}

// returns the temporary file, the device path and the error.
func CreateTempFormattedLoopDevice(t *testing.T, name string) (*TempBlockDevice, error) {
blockDev, err := CreateTempLoopDevice(t, name)
if err != nil {
return nil, err
}

//nolint:gosec
cmd := exec.Command("/sbin/mkfs.ext4", "-F", "-q", blockDev.LoopDevice)
log.Printf("[DEBUG] executing command: %s", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
if err := cleanupLoop(blockDev.LoopDevice); err != nil {
return nil, err
}

if err := cleanupFile(blockDev.TempFile); err != nil {
return nil, err
}

return nil, fmt.Errorf("error formatting file system: %w", err)
}

return blockDev, nil
}

// returns the temporary file, the device and the error.
func CreateTempLVMLoopDevice(t *testing.T, name string) (*TempBlockDevice, error) {
blockDev, err := CreateTempLoopDevice(t, name)
if err != nil {
return nil, err
}

//nolint:gosec
cmd := exec.Command("sudo", "pvcreate", blockDev.LoopDevice)
log.Printf("[DEBUG] executing command: %s", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
if err := cleanupLoop(blockDev.LoopDevice); err != nil {
return nil, err
}

if err := cleanupFile(blockDev.TempFile); err != nil {
return nil, err
}

return nil, fmt.Errorf("error creating LVM partition on %s: %w", blockDev.LoopDevice, err)
}

return blockDev, nil
}

// returns the temporary file, the device and the error.
func CreateTempLoopDevice(t *testing.T, name string) (*TempBlockDevice, error) {
log.Print("[DEBUG] creating a temporary file for loop device")

// Create a 1MB temp file
filename := filepath.Join(t.TempDir(), name)

//nolint:gosec
cmd := exec.Command("dd", "if=/dev/zero", fmt.Sprintf("of=%s", filename), "bs=1024", "count=2048")
log.Printf("[DEBUG] executing command: %s\n", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
if err := cleanupFile(filename); err != nil {
return nil, err
}

return nil, fmt.Errorf("Error creating file %s: %w", filename, err)
}

// Find an available loop device.
cmd = exec.Command("sudo", "/sbin/losetup", "--find")
loopdevStr, err := cmd.Output()
log.Printf("[DEBUG] executing command: %s", strings.Join(cmd.Args, " "))
if err != nil {
if err := cleanupFile(filename); err != nil {
return nil, err
}

return nil, fmt.Errorf("Error searching for available loop device: %w", err)
}
loopdev := filepath.Clean(strings.TrimRight(string(loopdevStr), "\n"))

// give the same permissions to the loop device as the backing file.
cmd = exec.Command("sudo", "chown", "--reference", filename, loopdev)
log.Printf("[DEBUG] executing command: %s", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
if err := cleanupFile(filename); err != nil {
return nil, err
}

return nil, fmt.Errorf("Error copying permissions from %s: %w", filename, err)
}

// attach the file to a loop device.
cmd = exec.Command("sudo", "/sbin/losetup", loopdev, filename)
log.Printf("[DEBUG] executing command: %s", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
if err := cleanupFile(filename); err != nil {
return nil, err
}

return nil, fmt.Errorf("Error setting up loop device: %w", err)
}

log.Printf("[DEBUG] temporary file %s attached to loop device %s", filename, loopdev)

return &TempBlockDevice{TempFile: filename, LoopDevice: loopdev}, nil
}

func (b *TempBlockDevice) Cleanup() error {
err := cleanupLoop(b.LoopDevice)
if err != nil {
return err
}

err = cleanupFile(b.TempFile)
if err != nil {
return err
}

return nil
}

func cleanupLoop(loopDevice string) error {
cmd := exec.Command("sudo", "losetup", "-d", loopDevice)
if err := cmd.Run(); err != nil {
log.Printf("[DEBUG] error detaching loop device %s: %s", loopDevice, err)
return err
}
log.Printf("[DEBUG] detaching loop device %s", loopDevice)

return nil
}

func cleanupFile(tempFile string) error {
if err := os.Remove(tempFile); err != nil {
log.Printf("[DEBUG] error removing temporary file %s: %s", tempFile, err)
return err
}
log.Printf("[DEBUG] removing temporary file %s", tempFile)

return nil
}

func (b *TempBlockDevice) String() string {
return fmt.Sprintf("TempFile: %s, LoopDevice: %s", b.TempFile, b.LoopDevice)
}
6 changes: 3 additions & 3 deletions libvirt/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func poolExistsStateRefreshFunc(virConn *libvirt.Libvirt, uuid libvirt.UUID) ret
_, err := virConn.StoragePoolLookupByUUID(uuid)
if err != nil {
if isError(err, libvirt.ErrNoStoragePool) {
log.Printf("pool %s does not exist", uuid)
log.Printf("pool %v does not exist", uuidString(uuid))
return virConn, poolStateConfNotExists, nil
}
return virConn, poolStateConfNotExists, err
Expand All @@ -28,7 +28,7 @@ func poolExistsStateRefreshFunc(virConn *libvirt.Libvirt, uuid libvirt.UUID) ret
}

func waitForStatePoolExists(ctx context.Context, virConn *libvirt.Libvirt, uuid libvirt.UUID) error {
log.Printf("Waiting for pool %s to appear...", uuid)
log.Printf("Waiting for pool %v to appear...", uuidString(uuid))
stateConf := &retry.StateChangeConf{
Pending: []string{poolStateConfNotExists},
Target: []string{poolStateConfExists},
Expand All @@ -46,7 +46,7 @@ func waitForStatePoolExists(ctx context.Context, virConn *libvirt.Libvirt, uuid

// waitForStatePoolDeleted waits for a storage pool to be removed.
func waitForStatePoolDeleted(ctx context.Context, virConn *libvirt.Libvirt, uuid libvirt.UUID) error {
log.Printf("waiting for pool %s to be deleted...", uuid)
log.Printf("waiting for pool %v to be deleted...", uuidString(uuid))
stateConf := &retry.StateChangeConf{
Pending: []string{poolStateConfExists},
Target: []string{poolStateConfNotExists},
Expand Down
Loading

0 comments on commit fd7ac21

Please sign in to comment.