Unverified Commit 5cdb38bb authored by adisbladis's avatar adisbladis Committed by GitHub
Browse files

Merge pull request #288579 from blitz/vbox-kvm-2

virtualboxKvm: init
parents 311a4be9 c9f940be
Loading
Loading
Loading
Loading
+44 −7
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ let
  cfg = config.virtualisation.virtualbox.host;

  virtualbox = cfg.package.override {
    inherit (cfg) enableHardening headless enableWebService;
    inherit (cfg) enableHardening headless enableWebService enableKvm;
    extensionPack = if cfg.enableExtensionPack then pkgs.virtualboxExtpack else null;
  };

@@ -81,13 +81,24 @@ in
        Build VirtualBox web service tool (vboxwebsrv) to allow managing VMs via other webpage frontend tools. Useful for headless servers.
      '';
    };

    enableKvm = mkOption {
      type = types.bool;
      default = false;
      description = lib.mdDoc ''
        Enable KVM support for VirtualBox. This increases compatibility with Linux kernel versions, because the VirtualBox kernel modules
        are not required.

        This option is incompatible with `enableHardening` and `addNetworkInterface`.

        Note: This is experimental. Please check https://github.com/cyberus-technology/virtualbox-kvm/issues.
      '';
    };
  };

  config = mkIf cfg.enable (mkMerge [{
    warnings = mkIf (pkgs.config.virtualbox.enableExtensionPack or false)
      ["'nixpkgs.virtualbox.enableExtensionPack' has no effect, please use 'virtualisation.virtualbox.host.enableExtensionPack'"];
    boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ];
    boot.extraModulePackages = [ kernelModules ];
    environment.systemPackages = [ virtualbox ];

    security.wrappers = let
@@ -114,17 +125,43 @@ in

    services.udev.extraRules =
      ''
        KERNEL=="vboxdrv",    OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
        KERNEL=="vboxdrvu",   OWNER="root", GROUP="root",      MODE="0666", TAG+="systemd"
        KERNEL=="vboxnetctl", OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
        SUBSYSTEM=="usb_device", ACTION=="add", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
        SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
        SUBSYSTEM=="usb_device", ACTION=="remove", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
        SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
      '';
  } (mkIf cfg.enableKvm {
    assertions = [
      {
        assertion = !cfg.addNetworkInterface;
        message = "VirtualBox KVM only supports standard NAT networking for VMs. Please turn off virtualisation.virtualbox.host.addNetworkInferface.";
      }

      {
        assertion = !cfg.enableHardening;
        message = "VirtualBox KVM is not compatible with hardening: Please turn off virtualisation.virtualbox.host.enableHardening.";
      }
    ];

    warnings = [
      ''
        KVM support in VirtualBox is experimental. Not all security features are available yet.
        See: https://github.com/cyberus-technology/virtualbox-kvm/issues/12
      ''
    ];
  }) (mkIf (!cfg.enableKvm) {
    boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ];
    boot.extraModulePackages = [ kernelModules ];

    services.udev.extraRules =
      ''
        KERNEL=="vboxdrv",    OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
        KERNEL=="vboxdrvu",   OWNER="root", GROUP="root",      MODE="0666", TAG+="systemd"
        KERNEL=="vboxnetctl", OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
     '';

    # Since we lack the right setuid/setcap binaries, set up a host-only network by default.
  } (mkIf cfg.addNetworkInterface {
  }) (mkIf cfg.addNetworkInterface {
    systemd.services.vboxnet0 =
      { description = "VirtualBox vboxnet0 Interface";
        requires = [ "dev-vboxnetctl.device" ];
+38 −9
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
  pkgs ? import ../.. { inherit system config; },
  debug ? false,
  enableUnfree ? false,
  enableKvm ? false,
  use64bitGuest ? true
}:

@@ -340,7 +341,7 @@ let
    testExtensionPack.vmFlags = enableExtensionPackVMFlags;
  };

  mkVBoxTest = useExtensionPack: vms: name: testScript: makeTest {
  mkVBoxTest = vboxHostConfig: vms: name: testScript: makeTest {
    name = "virtualbox-${name}";

    nodes.machine = { lib, config, ... }: {
@@ -349,14 +350,23 @@ let
        vmConfigs = mapAttrsToList mkVMConf vms;
      in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs;
      virtualisation.memorySize = 2048;
      virtualisation.qemu.options = ["-cpu" "kvm64,svm=on,vmx=on"];
      virtualisation.virtualbox.host.enable = true;

      virtualisation.qemu.options = let
        # IvyBridge is reasonably ancient to be compatible with recent
        # Intel/AMD hosts and sufficient for the KVM flavor.
        guestCpu = if config.virtualisation.virtualbox.host.enableKvm then "IvyBridge" else "kvm64";
      in ["-cpu" "${guestCpu},svm=on,vmx=on"];

      test-support.displayManager.auto.user = "alice";
      users.users.alice.extraGroups = let
        inherit (config.virtualisation.virtualbox.host) enableHardening;
      in lib.mkIf enableHardening (lib.singleton "vboxusers");
      virtualisation.virtualbox.host.enableExtensionPack = useExtensionPack;
      nixpkgs.config.allowUnfree = useExtensionPack;
      in lib.mkIf enableHardening [ "vboxusers" ];

      virtualisation.virtualbox.host = {
        enable = true;
      } // vboxHostConfig;

      nixpkgs.config.allowUnfree = config.virtualisation.virtualbox.host.enableExtensionPack;
    };

    testScript = ''
@@ -390,7 +400,7 @@ let
    };
  };

  unfreeTests = mapAttrs (mkVBoxTest true vboxVMsWithExtpack) {
  unfreeTests = mapAttrs (mkVBoxTest { enableExtensionPack = true; } vboxVMsWithExtpack) {
    enable-extension-pack = ''
      create_vm_testExtensionPack()
      vbm("startvm testExtensionPack")
@@ -409,7 +419,24 @@ let
    '';
  };

in mapAttrs (mkVBoxTest false vboxVMs) {
  kvmTests = mapAttrs (mkVBoxTest {
    enableKvm = true;

    # Once the KVM version supports these, we can enable them.
    addNetworkInterface = false;
    enableHardening = false;
  } vboxVMs) {
    kvm-headless = ''
      create_vm_headless()
      machine.succeed(ru("VBoxHeadless --startvm headless >&2 & disown %1"))
      wait_for_startup_headless()
      wait_for_vm_boot_headless()
      shutdown_vm_headless()
      destroy_vm_headless()
    '';
  };

in mapAttrs (mkVBoxTest {} vboxVMs) {
  simple-gui = ''
    # Home to select Tools, down to move to the VM, enter to start it.
    def send_vm_startup():
@@ -519,4 +546,6 @@ in mapAttrs (mkVBoxTest false vboxVMs) {
    destroy_vm_test1()
    destroy_vm_test2()
  '';
} // (optionalAttrs enableUnfree unfreeTests)
}
// (optionalAttrs enableKvm kvmTests)
// (optionalAttrs enableUnfree unfreeTests)
+24 −3
Original line number Diff line number Diff line
@@ -17,9 +17,13 @@
, headless ? false
, enable32bitGuests ? true
, enableWebService ? false
, enableKvm ? false
, extraConfigureFlags ? ""
}:

# See https://github.com/cyberus-technology/virtualbox-kvm/issues/12
assert enableKvm -> !enableHardening;

with lib;

let
@@ -27,6 +31,10 @@ let
  # Use maintainers/scripts/update.nix to update the version and all related hashes or
  # change the hashes in extpack.nix and guest-additions/default.nix as well manually.
  version = "7.0.14";

  # The KVM build is not compatible to VirtualBox's kernel modules. So don't export
  # modsrc at all.
  withModsrc = !enableKvm;
in stdenv.mkDerivation {
  pname = "virtualbox";
  inherit version;
@@ -36,7 +44,7 @@ in stdenv.mkDerivation {
    sha256 = "45860d834804a24a163c1bb264a6b1cb802a5bc7ce7e01128072f8d6a4617ca9";
  };

  outputs = [ "out" "modsrc" ];
  outputs = [ "out" ] ++ optional withModsrc "modsrc";

  nativeBuildInputs = [ pkg-config which docbook_xsl docbook_xml_dtd_43 yasm glslang ]
    ++ optional (!headless) wrapQtAppsHook;
@@ -104,6 +112,16 @@ in stdenv.mkDerivation {
      src = ./qt-env-vars.patch;
      qtPluginPath = "${qtbase.bin}/${qtbase.qtPluginPrefix}:${qtsvg.bin}/${qtbase.qtPluginPrefix}:${qtwayland.bin}/${qtbase.qtPluginPrefix}";
  })
     # While the KVM patch should not break any other behavior if --with-kvm is not specified,
     # we don't take any chances and only apply it if people actually want to use KVM support.
  ++ optional enableKvm (fetchpatch
    (let
      patchVersion = "20240226";
    in {
      name = "virtualbox-${version}-kvm-dev-${patchVersion}.patch";
      url = "https://github.com/cyberus-technology/virtualbox-kvm/releases/download/dev-${patchVersion}/virtualbox-${version}-kvm-dev-${patchVersion}.patch";
      hash = "sha256-3YT1ZN/TwoNWNb2eqOcPF8GTrVGfOPaPb8vpGoPNISY=";
    }))
  ++ [
    ./qt-dependency-paths.patch
    # https://github.com/NixOS/nixpkgs/issues/123851
@@ -165,6 +183,7 @@ in stdenv.mkDerivation {
      ${optionalString (!enable32bitGuests) "--disable-vmmraw"} \
      ${optionalString enableWebService "--enable-webservice"} \
      ${optionalString (open-watcom-bin != null) "--with-ow-dir=${open-watcom-bin}"} \
      ${optionalString (enableKvm) "--with-kvm"} \
      ${extraConfigureFlags} \
      --disable-kmods
    sed -e 's@PKG_CONFIG_PATH=.*@PKG_CONFIG_PATH=${libIDL}/lib/pkgconfig:${glib.dev}/lib/pkgconfig ${libIDL}/bin/libIDL-config-2@' \
@@ -224,7 +243,9 @@ in stdenv.mkDerivation {
      ln -sv $libexec/nls "$out/share/virtualbox"
    ''}

    ${optionalString withModsrc ''
      cp -rv out/linux.*/${buildType}/bin/src "$modsrc"
    ''}

    mkdir -p "$out/share/virtualbox"
    cp -rv src/VBox/Main/UnattendedTemplates "$out/share/virtualbox"
+4 −0
Original line number Diff line number Diff line
@@ -35866,6 +35866,10 @@ with pkgs;
    inherit (gnome2) libIDL;
  };
  virtualboxKvm = lowPrio (virtualbox.override {
    enableKvm = true;
  });
  virtualboxHardened = lowPrio (virtualbox.override {
    enableHardening = true;
  });