-
Notifications
You must be signed in to change notification settings - Fork 458
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: lvm storage pool impl This feature also adds support for target and source blocks in pool. Deprecating the old top-level path, and opening the door for supporting more pool backends, following libvirt description closer. - refactor the lvm pool implementation - 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 - skip the tests if the host does not support logical pools - skip early if acceptance tests are disabled * fix: dir path is actually on target, not source * add name attribute to pool source * cleanup support for existing vg * move code to configure provider to common function --------- Co-authored-by: dpap <daniel.pap@qualysoft.com> Co-authored-by: Duncan Mac-Vicar P. <duncan@mac-vicar.eu> Co-authored-by: Boris Momčilović <boris.momcilovic@sb22.com>
- Loading branch information
1 parent
72a3214
commit b56a61c
Showing
10 changed files
with
590 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
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 CreateTempLVMGroupDevice(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) | ||
} | ||
|
||
//nolint:gosec | ||
cmd = exec.Command("sudo", "vgcreate", name, 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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package libvirt | ||
|
||
import ( | ||
"encoding/xml" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
|
||
"github.com/digitalocean/go-libvirt" | ||
"libvirt.org/go/libvirtxml" | ||
) | ||
|
||
func newDefPoolFromLibvirt(virConn *libvirt.Libvirt, pool libvirt.StoragePool) (libvirtxml.StoragePool, diag.Diagnostics) { | ||
poolDefXML, err := virConn.StoragePoolGetXMLDesc(pool, 0) | ||
if err != nil { | ||
return libvirtxml.StoragePool{}, diag.Errorf("could not get XML description for pool %s: %s", pool.Name, err) | ||
} | ||
poolDef, err := newDefPoolFromXML(poolDefXML) | ||
if err != nil { | ||
return libvirtxml.StoragePool{}, diag.Errorf("could not get a pool definition from XML for %s: %s", pool.Name, err) | ||
} | ||
return poolDef, nil | ||
} | ||
|
||
func newDefPoolFromXML(s string) (libvirtxml.StoragePool, error) { | ||
var poolDef libvirtxml.StoragePool | ||
err := xml.Unmarshal([]byte(s), &poolDef) | ||
if err != nil { | ||
return libvirtxml.StoragePool{}, err | ||
} | ||
return poolDef, nil | ||
} |
Oops, something went wrong.