From 6b872802518e85542fd89c111be494383deb666d Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Thu, 3 Oct 2024 15:18:34 +0200 Subject: [PATCH] Implement CrcImagePuller This will replace the default podman-machine code to get the disk image for the VM. --- pkg/machinedriver/crcimageprovider.go | 137 ++++++++++++++++++++++++++ pkg/machinedriver/driver.go | 18 ++-- 2 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 pkg/machinedriver/crcimageprovider.go diff --git a/pkg/machinedriver/crcimageprovider.go b/pkg/machinedriver/crcimageprovider.go new file mode 100644 index 00000000..8ed22894 --- /dev/null +++ b/pkg/machinedriver/crcimageprovider.go @@ -0,0 +1,137 @@ +package macadam + +import ( + "fmt" + "log/slog" + "os" + "path/filepath" + + "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/vmconfigs" + crcos "github.com/crc-org/crc/v2/pkg/os" +) + +type CrcImagePuller struct { + localPath *define.VMFile + sourcePath string + vmType define.VMType + machineConfig *vmconfigs.MachineConfig + machineDirs *define.MachineDirs +} + +func GetHomeDir() string { + homeDir, err := os.UserHomeDir() + if err != nil { + panic("Failed to get homeDir: " + err.Error()) + } + return homeDir +} + +var ( + CrcBaseDir = filepath.Join(GetHomeDir(), ".crc") + MachineBaseDir = CrcBaseDir + MachineCacheDir = filepath.Join(MachineBaseDir, "cache") + MachineInstanceDir = filepath.Join(MachineBaseDir, "machines") +) + +func NewCrcImagePuller(vmType define.VMType) (*CrcImagePuller, error) { + crcImage := CrcImagePuller{ + vmType: vmType, + } + + return &crcImage, nil +} + +/* TODO: Might be better to pass an actual URI and to strip the "file://" part from it */ +func (puller *CrcImagePuller) SetSourceURI(path string) { + puller.sourcePath = path +} + +/* + type MachineDirs struct { + ConfigDir *VMFile + DataDir *VMFile + ImageCacheDir *VMFile + RuntimeDir *VMFile + } + +var crcMachineDirs = MachineDirs { +ConfigDir: CrcBaseDir, +DataDir: filepath.Join(MachineInstanceDir, , "crc"), +ImageCacheDir: MachineCacheDir, +RuntimeDir: filepath.Join(MachineInstanceDir, , "crc"), +} +*/ + +func imageExtension(vmType define.VMType) string { + switch vmType { + case define.QemuVirt: + return ".qcow2" + case define.AppleHvVirt, define.LibKrun: + return ".raw" + case define.HyperVVirt: + return ".vhdx" + case define.WSLVirt: + return "" + default: + return "" + } +} + +func (puller *CrcImagePuller) LocalPath() (*define.VMFile, error) { + // filename is bundle specific + return define.NewMachineFile(filepath.Join(MachineInstanceDir, "crc", fmt.Sprintf("crc%s", imageExtension(puller.vmType))), nil) +} + +func (puller *CrcImagePuller) Download() error { + //_ = bundle.Get() + // no download yet, reuse crc code + imagePath, err := puller.LocalPath() + if err != nil { + return err + } + + slog.Info(fmt.Sprintf("%+v", puller)) + slog.Info("file copy", "source", puller.sourcePath, "dest", imagePath.GetPath()) + if err := crcos.CopyFile(puller.sourcePath, imagePath.GetPath()); err != nil { + return err + } + /* + if err := unix.Access(imagePath.GetPath(), unix.R_OK|unix.W_OK); err != nil { + return fmt.Errorf("cannot access %s: %w", imagePath.GetPath(), err) + } + */ + fi, err := os.Stat(imagePath.GetPath()) + if err != nil { + return fmt.Errorf("cannot get file information for %s: %w", imagePath.GetPath(), err) + } + perms := fi.Mode().Perm() + if !perms.IsRegular() { + return fmt.Errorf("%s must be a regular file", imagePath.GetPath()) + } + if (perms & 0600) != 0600 { + return fmt.Errorf("%s is not readable/writable by the user", imagePath.GetPath()) + } + slog.Info("all is fine", "imagePath", imagePath.GetPath()) + + return nil +} + +/* + bundleInfo, err := bundle.Use(bundleName) + if err == nil { + logging.Infof("Loading bundle: %s...", bundleName) + return bundleInfo, nil + } + logging.Debugf("Failed to load bundle %s: %v", bundleName, err) + logging.Infof("Downloading bundle: %s...", bundleName) + bundlePath, err = bundle.Download(preset, bundlePath, enableBundleQuayFallback) + if err != nil { + return nil, err + } + logging.Infof("Extracting bundle: %s...", bundleName) + if _, err := bundle.Extract(bundlePath); err != nil { + return nil, err + } + return bundle.Use(bundleName) +*/ diff --git a/pkg/machinedriver/driver.go b/pkg/machinedriver/driver.go index 9d58ce30..f31e8027 100644 --- a/pkg/machinedriver/driver.go +++ b/pkg/machinedriver/driver.go @@ -28,7 +28,6 @@ import ( provider2 "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" - crcos "github.com/crc-org/crc/v2/pkg/os" "github.com/crc-org/machine/libmachine/drivers" "github.com/crc-org/machine/libmachine/state" ) @@ -166,16 +165,6 @@ func (d *Driver) Create() error { return err } - switch d.ImageFormat { - case "qcow2": - // FIXME: the libvirt machine driver uses qemu-img - if err := crcos.CopyFile(d.ImageSourcePath, d.getDiskPath()); err != nil { - return err - } - default: - return fmt.Errorf("%s is an unsupported disk image format", d.ImageFormat) - } - // Check if machine already exists vmConfig, exists, err := shim.VMExists(d.MachineName, []vmconfigs.VMProvider{d.vmProvider}) if err != nil { @@ -206,6 +195,13 @@ func (d *Driver) Create() error { */ initOpts := d.initOpts() + crcPuller, err := NewCrcImagePuller(d.vmProvider.VMType()) + if err != nil { + return nil + } + crcPuller.SetSourceURI(d.ImageSourcePath) + initOpts.ImagePuller = crcPuller + for idx, vol := range initOpts.Volumes { initOpts.Volumes[idx] = os.ExpandEnv(vol) }