at 24.11-pre 7.9 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 = "${config.system.nixos.distroName} ${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 `VBoxManage modifyvm --help` 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 `VBoxManage export --help` 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 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 postExportCommands = mkOption { 111 type = types.lines; 112 default = ""; 113 example = '' 114 ${pkgs.cot}/bin/cot edit-hardware "$fn" \ 115 -v vmx-14 \ 116 --nics 2 \ 117 --nic-types VMXNET3 \ 118 --nic-names 'Nic name' \ 119 --nic-networks 'Nic match' \ 120 --network-descriptions 'Nic description' \ 121 --scsi-subtypes VirtualSCSI 122 ''; 123 description = '' 124 Extra commands to run after exporting the OVA to `$fn`. 125 ''; 126 }; 127 storageController = mkOption { 128 type = with types; attrsOf (oneOf [ str int bool (listOf str) ]); 129 example = { 130 name = "SCSI"; 131 add = "scsi"; 132 portcount = 16; 133 bootable = "on"; 134 hostiocache = "on"; 135 }; 136 default = { 137 name = "SATA"; 138 add = "sata"; 139 portcount = 4; 140 bootable = "on"; 141 hostiocache = "on"; 142 }; 143 description = '' 144 Parameters passed to the VirtualBox appliance. Must have at least 145 `name`. 146 147 Run `VBoxManage storagectl --help` to see more options. 148 ''; 149 }; 150 }; 151 }; 152 153 config = { 154 155 virtualbox.params = mkMerge [ 156 (mapAttrs (name: mkDefault) { 157 acpi = "on"; 158 vram = 32; 159 nictype1 = "virtio"; 160 nic1 = "nat"; 161 audiocontroller = "ac97"; 162 audio = "alsa"; 163 audioout = "on"; 164 graphicscontroller = "vmsvga"; 165 rtcuseutc = "on"; 166 usb = "on"; 167 usbehci = "on"; 168 mouse = "usbtablet"; 169 }) 170 (mkIf (pkgs.stdenv.hostPlatform.system == "i686-linux") { pae = "on"; }) 171 ]; 172 173 system.build.virtualBoxOVA = import ../../lib/make-disk-image.nix { 174 name = cfg.vmDerivationName; 175 176 inherit pkgs lib config; 177 partitionTableType = "legacy"; 178 diskSize = cfg.baseImageSize; 179 additionalSpace = "${toString cfg.baseImageFreeSpace}M"; 180 181 postVM = 182 '' 183 export HOME=$PWD 184 export PATH=${pkgs.virtualbox}/bin:$PATH 185 186 echo "converting image to VirtualBox format..." 187 VBoxManage convertfromraw $diskImage disk.vdi 188 189 ${optionalString (cfg.extraDisk != null) '' 190 echo "creating extra disk: data-disk.raw" 191 dataDiskImage=data-disk.raw 192 truncate -s ${toString cfg.extraDisk.size}M $dataDiskImage 193 194 parted --script $dataDiskImage -- \ 195 mklabel msdos \ 196 mkpart primary ext4 1MiB -1 197 eval $(partx $dataDiskImage -o START,SECTORS --nr 1 --pairs) 198 mkfs.ext4 -F -L ${cfg.extraDisk.label} $dataDiskImage -E offset=$(sectorsToBytes $START) $(sectorsToKilobytes $SECTORS)K 199 echo "creating extra disk: data-disk.vdi" 200 VBoxManage convertfromraw $dataDiskImage data-disk.vdi 201 ''} 202 203 echo "creating VirtualBox VM..." 204 vmName="${cfg.vmName}"; 205 VBoxManage createvm --name "$vmName" --register \ 206 --ostype ${if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then "Linux26_64" else "Linux26"} 207 VBoxManage modifyvm "$vmName" \ 208 --memory ${toString cfg.memorySize} \ 209 ${lib.cli.toGNUCommandLineShell { } cfg.params} 210 VBoxManage storagectl "$vmName" ${lib.cli.toGNUCommandLineShell { } cfg.storageController} 211 VBoxManage storageattach "$vmName" --storagectl ${cfg.storageController.name} --port 0 --device 0 --type hdd \ 212 --medium disk.vdi 213 ${optionalString (cfg.extraDisk != null) '' 214 VBoxManage storageattach "$vmName" --storagectl ${cfg.storageController.name} --port 1 --device 0 --type hdd \ 215 --medium data-disk.vdi 216 ''} 217 218 echo "exporting VirtualBox VM..." 219 mkdir -p $out 220 fn="$out/${cfg.vmFileName}" 221 VBoxManage export "$vmName" --output "$fn" --options manifest ${escapeShellArgs cfg.exportParams} 222 ${cfg.postExportCommands} 223 224 rm -v $diskImage 225 226 mkdir -p $out/nix-support 227 echo "file ova $fn" >> $out/nix-support/hydra-build-products 228 ''; 229 }; 230 231 fileSystems = { 232 "/" = { 233 device = "/dev/disk/by-label/nixos"; 234 autoResize = true; 235 fsType = "ext4"; 236 }; 237 } // (lib.optionalAttrs (cfg.extraDisk != null) { 238 ${cfg.extraDisk.mountPoint} = { 239 device = "/dev/disk/by-label/" + cfg.extraDisk.label; 240 autoResize = true; 241 fsType = "ext4"; 242 }; 243 }); 244 245 boot.growPartition = true; 246 boot.loader.grub.device = "/dev/sda"; 247 248 swapDevices = [{ 249 device = "/var/swap"; 250 size = 2048; 251 }]; 252 253 virtualisation.virtualbox.guest.enable = true; 254 255 }; 256}