diff --git a/internal/vm/create.go b/internal/vm/create.go index f3e9d34..529c73c 100644 --- a/internal/vm/create.go +++ b/internal/vm/create.go @@ -2,6 +2,9 @@ package vm import ( "fmt" + "io" + "os" + "path/filepath" configuration "git.g3e.fr/syonad/two/internal/config/agent" "git.g3e.fr/syonad/two/internal/iptables" @@ -49,18 +52,54 @@ func StartVM(db *badger.DB, name string, cfg *configuration.Config) error { return fmt.Errorf("start metadata: %w", err) } + qcfg := qemu.Config{ + Name: name, + TapID: d.tapID, + Mac: d.mac, + VolumePath: d.volumePath, + Memory: d.memory, + CPUs: d.cpus, + SerialDir: cfg.QEMU.SerialDir, + MonitorDir: cfg.QEMU.MonitorDir, + QMPDir: cfg.QEMU.QMPDir, + } + + if d.uefi { + varsPath := filepath.Join(cfg.QEMU.UEFIVarsDir, name+"-uefi-vars.fd") + if err := copyFile(cfg.QEMU.OVMFVarsTemplate, varsPath); err != nil { + return fmt.Errorf("copy uefi vars: %w", err) + } + qcfg.UEFICodePath = cfg.QEMU.OVMFCodePath + qcfg.UEFIVarsPath = varsPath + } + if err := netns.Call(d.vpcName, func() error { - return qemu.Start(qemu.Config{ - Name: name, - TapID: d.tapID, - Mac: d.mac, - VolumePath: d.volumePath, - Memory: d.memory, - CPUs: d.cpus, - }) + return qemu.Start(qcfg) }); err != nil { return fmt.Errorf("start qemu: %w", err) } return kv.AddInDB(db, "vm/"+name+"/state", "started") } + +func copyFile(src, dst string) error { + if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + return err + } + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + + if _, err := io.Copy(out, in); err != nil { + return err + } + return out.Sync() +} diff --git a/internal/vm/data.go b/internal/vm/data.go index df5c051..1e2644e 100644 --- a/internal/vm/data.go +++ b/internal/vm/data.go @@ -14,7 +14,7 @@ import ( type vmData struct { subnetName string vpcName string - interfaceIP string + interfaceIP string bridge string tapID int ip string @@ -23,6 +23,7 @@ type vmData struct { volumePath string memory int cpus int + uefi bool password string sshkey string } @@ -105,6 +106,9 @@ func loadVM(db *badger.DB, name string) (vmData, error) { return d, fmt.Errorf("parse cpus: %w", err) } + if v, _ := kv.GetFromDB(db, "vm/"+name+"/uefi"); v == "true" { + d.uefi = true + } d.password, _ = kv.GetFromDB(db, "vm/"+name+"/password") d.sshkey, _ = kv.GetFromDB(db, "vm/"+name+"/sshkey") diff --git a/internal/vm/delete.go b/internal/vm/delete.go index 79a4c72..7e47f3f 100644 --- a/internal/vm/delete.go +++ b/internal/vm/delete.go @@ -2,6 +2,8 @@ package vm import ( "fmt" + "os" + "path/filepath" "time" configuration "git.g3e.fr/syonad/two/internal/config/agent" @@ -29,7 +31,7 @@ func StopVM(db *badger.DB, name string, cfg *configuration.Config) error { return err } - socketPath := fmt.Sprintf("/tmp/%s.qmp-sock", name) + socketPath := filepath.Join(cfg.QEMU.QMPDir, name+".sock") if _, err := qmp.Send(socketPath, []string{`{"execute":"system_powerdown"}`}); err != nil { return fmt.Errorf("qmp system_powerdown: %w", err) @@ -65,5 +67,10 @@ func StopVM(db *badger.DB, name string, cfg *configuration.Config) error { return fmt.Errorf("delete tap: %w", err) } + if d.uefi { + varsPath := filepath.Join(cfg.QEMU.UEFIVarsDir, name+"-uefi-vars.fd") + os.Remove(varsPath) + } + return kv.AddInDB(db, "vm/"+name+"/state", "stopped") }