at 22.05-pre 6.8 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.virtualbox; 8 9in { 10 11 options = { 12 virtualbox = { 13 baseImageSize = mkOption { 14 type = with types; either (enum [ "auto" ]) int; 15 default = "auto"; 16 example = 50 * 1024; 17 description = '' 18 The size of the VirtualBox base image in MiB. 19 ''; 20 }; 21 baseImageFreeSpace = mkOption { 22 type = with types; int; 23 default = 30 * 1024; 24 description = '' 25 Free space in the VirtualBox base image in MiB. 26 ''; 27 }; 28 memorySize = mkOption { 29 type = types.int; 30 default = 1536; 31 description = '' 32 The amount of RAM the VirtualBox appliance can use in MiB. 33 ''; 34 }; 35 vmDerivationName = mkOption { 36 type = types.str; 37 default = "nixos-ova-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}"; 38 description = '' 39 The name of the derivation for the VirtualBox appliance. 40 ''; 41 }; 42 vmName = mkOption { 43 type = types.str; 44 default = "NixOS ${config.system.nixos.label} (${pkgs.stdenv.hostPlatform.system})"; 45 description = '' 46 The name of the VirtualBox appliance. 47 ''; 48 }; 49 vmFileName = mkOption { 50 type = types.str; 51 default = "nixos-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.ova"; 52 description = '' 53 The file name of the VirtualBox appliance. 54 ''; 55 }; 56 params = mkOption { 57 type = with types; attrsOf (oneOf [ str int bool (listOf str) ]); 58 example = { 59 audio = "alsa"; 60 rtcuseutc = "on"; 61 usb = "off"; 62 }; 63 description = '' 64 Parameters passed to the Virtualbox appliance. 65 66 Run <literal>VBoxManage modifyvm --help</literal> to see more options. 67 ''; 68 }; 69 exportParams = mkOption { 70 type = with types; listOf (oneOf [ str int bool (listOf str) ]); 71 example = [ 72 "--vsys" "0" "--vendor" "ACME Inc." 73 ]; 74 default = []; 75 description = '' 76 Parameters passed to the Virtualbox export command. 77 78 Run <literal>VBoxManage export --help</literal> to see more options. 79 ''; 80 }; 81 extraDisk = mkOption { 82 description = '' 83 Optional extra disk/hdd configuration. 84 The disk will be an 'ext4' partition on a separate VMDK file. 85 ''; 86 default = null; 87 example = { 88 label = "storage"; 89 mountPoint = "/home/demo/storage"; 90 size = 100 * 1024; 91 }; 92 type = types.nullOr (types.submodule { 93 options = { 94 size = mkOption { 95 type = types.int; 96 description = "Size in MiB"; 97 }; 98 label = mkOption { 99 type = types.str; 100 default = "vm-extra-storage"; 101 description = "Label for the disk partition"; 102 }; 103 mountPoint = mkOption { 104 type = types.str; 105 description = "Path where to mount this disk."; 106 }; 107 }; 108 }); 109 }; 110 }; 111 }; 112 113 config = { 114 115 virtualbox.params = mkMerge [ 116 (mapAttrs (name: mkDefault) { 117 acpi = "on"; 118 vram = 32; 119 nictype1 = "virtio"; 120 nic1 = "nat"; 121 audiocontroller = "ac97"; 122 audio = "alsa"; 123 audioout = "on"; 124 graphicscontroller = "vmsvga"; 125 rtcuseutc = "on"; 126 usb = "on"; 127 usbehci = "on"; 128 mouse = "usbtablet"; 129 }) 130 (mkIf (pkgs.stdenv.hostPlatform.system == "i686-linux") { pae = "on"; }) 131 ]; 132 133 system.build.virtualBoxOVA = import ../../lib/make-disk-image.nix { 134 name = cfg.vmDerivationName; 135 136 inherit pkgs lib config; 137 partitionTableType = "legacy"; 138 diskSize = cfg.baseImageSize; 139 additionalSpace = "${toString cfg.baseImageFreeSpace}M"; 140 141 postVM = 142 '' 143 export HOME=$PWD 144 export PATH=${pkgs.virtualbox}/bin:$PATH 145 146 echo "creating VirtualBox pass-through disk wrapper (no copying involved)..." 147 VBoxManage internalcommands createrawvmdk -filename disk.vmdk -rawdisk $diskImage 148 149 ${optionalString (cfg.extraDisk != null) '' 150 echo "creating extra disk: data-disk.raw" 151 dataDiskImage=data-disk.raw 152 truncate -s ${toString cfg.extraDisk.size}M $dataDiskImage 153 154 parted --script $dataDiskImage -- \ 155 mklabel msdos \ 156 mkpart primary ext4 1MiB -1 157 eval $(partx $dataDiskImage -o START,SECTORS --nr 1 --pairs) 158 mkfs.ext4 -F -L ${cfg.extraDisk.label} $dataDiskImage -E offset=$(sectorsToBytes $START) $(sectorsToKilobytes $SECTORS)K 159 echo "creating extra disk: data-disk.vmdk" 160 VBoxManage internalcommands createrawvmdk -filename data-disk.vmdk -rawdisk $dataDiskImage 161 ''} 162 163 echo "creating VirtualBox VM..." 164 vmName="${cfg.vmName}"; 165 VBoxManage createvm --name "$vmName" --register \ 166 --ostype ${if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then "Linux26_64" else "Linux26"} 167 VBoxManage modifyvm "$vmName" \ 168 --memory ${toString cfg.memorySize} \ 169 ${lib.cli.toGNUCommandLineShell { } cfg.params} 170 VBoxManage storagectl "$vmName" --name SATA --add sata --portcount 4 --bootable on --hostiocache on 171 VBoxManage storageattach "$vmName" --storagectl SATA --port 0 --device 0 --type hdd \ 172 --medium disk.vmdk 173 ${optionalString (cfg.extraDisk != null) '' 174 VBoxManage storageattach "$vmName" --storagectl SATA --port 1 --device 0 --type hdd \ 175 --medium data-disk.vmdk 176 ''} 177 178 echo "exporting VirtualBox VM..." 179 mkdir -p $out 180 fn="$out/${cfg.vmFileName}" 181 VBoxManage export "$vmName" --output "$fn" --options manifest ${escapeShellArgs cfg.exportParams} 182 183 rm -v $diskImage 184 185 mkdir -p $out/nix-support 186 echo "file ova $fn" >> $out/nix-support/hydra-build-products 187 ''; 188 }; 189 190 fileSystems = { 191 "/" = { 192 device = "/dev/disk/by-label/nixos"; 193 autoResize = true; 194 fsType = "ext4"; 195 }; 196 } // (lib.optionalAttrs (cfg.extraDisk != null) { 197 ${cfg.extraDisk.mountPoint} = { 198 device = "/dev/disk/by-label/" + cfg.extraDisk.label; 199 autoResize = true; 200 fsType = "ext4"; 201 }; 202 }); 203 204 boot.growPartition = true; 205 boot.loader.grub.device = "/dev/sda"; 206 207 swapDevices = [{ 208 device = "/var/swap"; 209 size = 2048; 210 }]; 211 212 virtualisation.virtualbox.guest.enable = true; 213 214 }; 215}