From 662f387446df121c5cbf2b150e42a9dc487134d8 Mon Sep 17 00:00:00 2001 From: "Julie B." Date: Tue, 16 Aug 2022 14:41:43 +0200 Subject: [PATCH] tool/create: take guest config into account --- core/internal/build.nix | 1 + tool/common.hpp | 23 +++++++++++++++++++++++ tool/create.cpp | 36 ++++++++++++++++++++++++++---------- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/core/internal/build.nix b/core/internal/build.nix index 0b3b100..277bc72 100644 --- a/core/internal/build.nix +++ b/core/internal/build.nix @@ -26,6 +26,7 @@ mkIf cfg.enable { mkdir -p $out/boot ln -sT ${config.system.build.toplevel}/init $out/boot/init cp ${closureInfo}/registration $out/boot/nix-path-registration + ln -s ${pkgs.writeText "miniguest-config.json" (builtins.toJSON cfg)} $out/miniguest-config.json ${lib.optionalString (cfg.guestType == "qemu") "cp -P ${config.system.build.toplevel}/{kernel,initrd} -t $out" } diff --git a/tool/common.hpp b/tool/common.hpp index d83db6b..a963eba 100644 --- a/tool/common.hpp +++ b/tool/common.hpp @@ -17,6 +17,7 @@ */ #include +#include #include namespace miniguest { @@ -48,4 +49,26 @@ private: void completeGuestName(size_t, std::string_view prefix); +enum class GuestType { qemu, lxc }; +NLOHMANN_JSON_SERIALIZE_ENUM(GuestType, { + {GuestType::qemu, "qemu"}, + {GuestType::lxc, "lxc"}, + }) + +enum class QemuFsType { _9p, virtiofs }; +NLOHMANN_JSON_SERIALIZE_ENUM(QemuFsType, { + {QemuFsType::_9p, "9p"}, + {QemuFsType::virtiofs, "virtiofs"}, + }) + +struct GuestConfig final { + GuestType guest_type; + QemuFsType qemu_fs_type; +}; + +inline void from_json(const nlohmann::json &j, GuestConfig &cfg) { + j.at("guestType").get_to(cfg.guest_type); + j.at("qemu").at("fsType").get_to(cfg.qemu_fs_type); +} + } // namespace miniguest diff --git a/tool/create.cpp b/tool/create.cpp index 372fc9f..a6cf5a2 100644 --- a/tool/create.cpp +++ b/tool/create.cpp @@ -49,6 +49,16 @@ struct CmdCreate : virtual EvalCommand, virtual MixProfile { -t, --hypervisor: hypervisor to configure. Can be one of: 'libvirt' and 'lxc' (default: 'libvirt'))""; } + GuestConfig load_config() { + auto path = + fs::path("/etc/miniguests") / guest_name / "miniguest-config.json"; + try { + return nlohmann::json::parse(readFile(path)).get(); + } catch (SysError &err) { logWarning(err.info()); } + warn("metadata unavailable: falling back to defaults"); + return {}; + } + void display_command(Strings cmd) const { std::cout << "# Create " << guest_name << " using:" << std::endl; for (auto &line : cmd) @@ -56,24 +66,28 @@ struct CmdCreate : virtual EvalCommand, virtual MixProfile { std::cout << std::endl; } - void display_command_libvirt() const { + void display_command_libvirt(const GuestConfig &cfg) const { + auto virtiofs = cfg.qemu_fs_type == QemuFsType::virtiofs; + std::string memorybacking = + virtiofs ? " --memorybacking=access.mode=shared" : ""; + std::string fsArgs = + virtiofs ? "driver.type=virtiofs" : "readonly=yes,accessmode=squash"; Strings cmd{ "virt-install -n " + guest_name, "--connect qemu:///system", "--os-variant nixos-unstable", - "--memory 1536", + "--memory 1536" + memorybacking, "--disk none", "--import", "--boot kernel=/etc/miniguests/" + guest_name + "/kernel,initrd=/etc/miniguests/" + guest_name + "/initrd", - "--filesystem /nix/store/,nix-store,readonly=yes,accessmode=squash", - "--filesystem /etc/miniguests/" + guest_name + - "/boot/,boot,readonly=yes,accessmode=squash", + "--filesystem /nix/store/,nix-store," + fsArgs, + "--filesystem /etc/miniguests/" + guest_name + "/boot/,boot," + fsArgs, }; display_command(cmd); } - void display_command_lxc() const { + void display_command_lxc(const GuestConfig &cfg) const { Strings cmd = { "lxc-create " + guest_name, "-f extra-config", @@ -89,7 +103,7 @@ struct CmdCreate : virtual EvalCommand, virtual MixProfile { } struct HypervisorData { - void (CmdCreate::*display_commmand)() const; + void (CmdCreate::*display_commmand)(const GuestConfig &cfg) const; }; static const std::map hypervisors; @@ -119,13 +133,15 @@ struct CmdCreate : virtual EvalCommand, virtual MixProfile { } void run(ref store) override { + auto cfg = load_config(); + if (!hypervisor) - hypervisor = "libvirt"; + hypervisor = cfg.guest_type == GuestType::lxc ? "lxc" : "libvirt"; if (auto it = hypervisors.find(*hypervisor); it != hypervisors.end()) { - (this->*it->second.display_commmand)(); + (this->*it->second.display_commmand)(cfg); } else - throw Error(2, "unknown hypervisor type"); + throw Error(2, "unknown hypervisor type: " + *hypervisor); } virtual ~CmdCreate() = default;