From d8274b1682583763c4f2597c6d82ed06bde9df69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sat, 26 Mar 2022 15:25:09 +0100 Subject: [PATCH] Add option to add a data disk to an instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The data disk will show up after the base disk Typically as /dev/vdb, when running with virtio Signed-off-by: Anders F Björklund --- docs/internal.md | 1 + examples/default.yaml | 4 ++++ pkg/limayaml/defaults.go | 10 ++++++++++ pkg/limayaml/defaults_test.go | 3 +++ pkg/limayaml/limayaml.go | 1 + pkg/limayaml/validate.go | 6 ++++++ pkg/qemu/qemu.go | 17 +++++++++++++++++ pkg/store/filenames/filenames.go | 1 + pkg/store/instance.go | 5 +++++ 9 files changed, 48 insertions(+) diff --git a/docs/internal.md b/docs/internal.md index 8287aabe4b0..d96d5d0cc4d 100644 --- a/docs/internal.md +++ b/docs/internal.md @@ -35,6 +35,7 @@ cloud-init: disk: - `basedisk`: the base image - `diffdisk`: the diff image (QCOW2) +- `datadisk`: the data image (QCOW2), optional QEMU: - `qemu.pid`: QEMU PID diff --git a/examples/default.yaml b/examples/default.yaml index d2d7de06664..f6ffe46ce1d 100644 --- a/examples/default.yaml +++ b/examples/default.yaml @@ -39,6 +39,10 @@ memory: null # 🟢 Builtin default: "100GiB" disk: null +# Data size +# 🟢 Builtin default: "0" +data: null + # Expose host directories to the guest, the mount point might be accessible from all UIDs in the guest # 🟢 Builtin default: null (Mount nothing) # 🔵 This file: Mount the home as read-only, /tmp/lima as writable diff --git a/pkg/limayaml/defaults.go b/pkg/limayaml/defaults.go index a3840cc2dc3..6607ff5024c 100644 --- a/pkg/limayaml/defaults.go +++ b/pkg/limayaml/defaults.go @@ -139,6 +139,16 @@ func FillDefault(y, d, o *LimaYAML, filePath string) { y.Disk = pointer.String("100GiB") } + if y.Data == nil { + y.Data = d.Data + } + if o.Data != nil { + y.Data = o.Data + } + if y.Data == nil || *y.Data == "" { + y.Data = pointer.String("0") + } + if y.Video.Display == nil { y.Video.Display = d.Video.Display } diff --git a/pkg/limayaml/defaults_test.go b/pkg/limayaml/defaults_test.go index 17cbfb0ba96..a177e57d4e1 100644 --- a/pkg/limayaml/defaults_test.go +++ b/pkg/limayaml/defaults_test.go @@ -55,6 +55,7 @@ func TestFillDefault(t *testing.T) { CPUs: pointer.Int(4), Memory: pointer.String("4GiB"), Disk: pointer.String("100GiB"), + Data: pointer.String("0"), Containerd: Containerd{ System: pointer.Bool(false), User: pointer.Bool(true), @@ -190,6 +191,7 @@ func TestFillDefault(t *testing.T) { CPUs: pointer.Int(7), Memory: pointer.String("5GiB"), Disk: pointer.String("105GiB"), + Data: pointer.String("10GiB"), Containerd: Containerd{ System: pointer.Bool(true), User: pointer.Bool(false), @@ -314,6 +316,7 @@ func TestFillDefault(t *testing.T) { CPUs: pointer.Int(12), Memory: pointer.String("7GiB"), Disk: pointer.String("117GiB"), + Data: pointer.String("17GiB"), Containerd: Containerd{ System: pointer.Bool(true), User: pointer.Bool(false), diff --git a/pkg/limayaml/limayaml.go b/pkg/limayaml/limayaml.go index 47ac646ca46..818a732f486 100644 --- a/pkg/limayaml/limayaml.go +++ b/pkg/limayaml/limayaml.go @@ -13,6 +13,7 @@ type LimaYAML struct { CPUs *int `yaml:"cpus,omitempty" json:"cpus,omitempty"` Memory *string `yaml:"memory,omitempty" json:"memory,omitempty"` // go-units.RAMInBytes Disk *string `yaml:"disk,omitempty" json:"disk,omitempty"` // go-units.RAMInBytes + Data *string `yaml:"data,omitempty" json:"data,omitempty"` // go-units.RAMInBytes Mounts []Mount `yaml:"mounts,omitempty" json:"mounts,omitempty"` SSH SSH `yaml:"ssh,omitempty" json:"ssh,omitempty"` // REQUIRED (FIXME) Firmware Firmware `yaml:"firmware,omitempty" json:"firmware,omitempty"` diff --git a/pkg/limayaml/validate.go b/pkg/limayaml/validate.go index 167bb9f85cf..da62ef951ea 100644 --- a/pkg/limayaml/validate.go +++ b/pkg/limayaml/validate.go @@ -71,6 +71,12 @@ func Validate(y LimaYAML, warn bool) error { return fmt.Errorf("field `memory` has an invalid value: %w", err) } + if y.Data != nil { + if _, err := units.RAMInBytes(*y.Data); err != nil { + return fmt.Errorf("field `data` has an invalid value: %w", err) + } + } + u, err := osutil.LimaUser(false) if err != nil { return fmt.Errorf("internal error (not an error of YAML): %w", err) diff --git a/pkg/qemu/qemu.go b/pkg/qemu/qemu.go index a35c7af6dfc..054e1751304 100644 --- a/pkg/qemu/qemu.go +++ b/pkg/qemu/qemu.go @@ -94,6 +94,19 @@ func EnsureDisk(cfg Config) error { if out, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to run %v: %q: %w", cmd.Args, string(out), err) } + diskSize, _ = units.RAMInBytes(*cfg.LimaYAML.Data) + if diskSize == 0 { + return nil + } + dataDisk := filepath.Join(cfg.InstanceDir, filenames.DataDisk) + if _, err := os.Stat(dataDisk); errors.Is(err, os.ErrNotExist) { + args = []string{"create", "-f", "qcow2"} + args = append(args, dataDisk, strconv.Itoa(int(diskSize))) + cmd := exec.Command("qemu-img", args...) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to run %v: %q: %w", cmd.Args, string(out), err) + } + } return nil } @@ -317,6 +330,7 @@ func Cmdline(cfg Config) (string, []string, error) { baseDisk := filepath.Join(cfg.InstanceDir, filenames.BaseDisk) diffDisk := filepath.Join(cfg.InstanceDir, filenames.DiffDisk) + dataDisk := filepath.Join(cfg.InstanceDir, filenames.DataDisk) isBaseDiskCDROM, err := iso9660util.IsISO9660(baseDisk) if err != nil { return "", nil, err @@ -332,6 +346,9 @@ func Cmdline(cfg Config) (string, []string, error) { } else if !isBaseDiskCDROM { args = append(args, "-drive", fmt.Sprintf("file=%s,if=virtio", baseDisk)) } + if _, err := os.Stat(dataDisk); err == nil { + args = append(args, "-drive", fmt.Sprintf("file=%s,if=virtio", dataDisk)) + } // cloud-init args = append(args, "-cdrom", filepath.Join(cfg.InstanceDir, filenames.CIDataISO)) diff --git a/pkg/store/filenames/filenames.go b/pkg/store/filenames/filenames.go index 68e7f99ec6f..29d2adaf7df 100644 --- a/pkg/store/filenames/filenames.go +++ b/pkg/store/filenames/filenames.go @@ -29,6 +29,7 @@ const ( CIDataISO = "cidata.iso" BaseDisk = "basedisk" DiffDisk = "diffdisk" + DataDisk = "datadisk" QemuPID = "qemu.pid" QMPSock = "qmp.sock" SerialLog = "serial.log" diff --git a/pkg/store/instance.go b/pkg/store/instance.go index 1126ea22123..bd25ec0dad6 100644 --- a/pkg/store/instance.go +++ b/pkg/store/instance.go @@ -37,6 +37,7 @@ type Instance struct { CPUs int `json:"cpus,omitempty"` Memory int64 `json:"memory,omitempty"` // bytes Disk int64 `json:"disk,omitempty"` // bytes + Data int64 `json:"data,omitempty"` // bytes Message string `json:"message,omitempty"` Networks []limayaml.Network `json:"network,omitempty"` SSHLocalPort int `json:"sshLocalPort,omitempty"` @@ -87,6 +88,10 @@ func Inspect(instName string) (*Instance, error) { if err == nil { inst.Disk = disk } + data, err := units.RAMInBytes(*y.Data) + if err == nil { + inst.Data = data + } inst.Message = y.Message inst.Networks = y.Networks inst.SSHLocalPort = *y.SSH.LocalPort // maybe 0