Skip to content

Instantly share code, notes, and snippets.

@evanjs
Created July 7, 2020 14:23
Show Gist options
  • Save evanjs/d03acbdcf3c763dc0df60a1d3d0ac4c3 to your computer and use it in GitHub Desktop.
Save evanjs/d03acbdcf3c763dc0df60a1d3d0ac4c3 to your computer and use it in GitHub Desktop.
nixos-generators helper with logic for esxi image handling, etc
{ format ? "virtualbox"
, cfgFile ? ./configuration.nix
, hubType ? "full"
, ...
}:
let
sources = import (nix/sources.nix) { };
pkgs = import (sources.nixpkgs) { };
nixos-generators = import
(pkgs.fetchFromGitHub {
owner = "evanjs";
repo = "nixos-generators";
rev = "3ccab611416e83ad171f593e4f36e85d05e39e56";
sha256 = "1mmcq35gkbgs0q8xa355qd8am4qxqd854abjyxvd708chj3kahmc";
}) { };
lib = pkgs.lib;
nixos-generators-path = "${nixos-generators}/share/nixos-generator";
defaultHardwareConfig = formatType:
(
if (formatType == "virtualbox") then
{
virtualbox = {
params = {
audio = "none";
};
};
} else { }
);
configSpecs = {
medcon = {
baseImageSize = 10 * 1024; # 500 GiB;
cpus = 2;
memorySize = 4 * 1024; # 4 GiB
};
full = {
baseImageSize = 20 * 1024; # 1 TB
cpus = 4;
memorySize = 16 * 1024; # 16 GiB
};
};
# Get the customized configuration depending on the hub type, format, etc
getHardwareConfig = formatConfig: targetConfig:
with lib; (
if (formatConfig == "azure") then {
# azure-image is atypical and needs to set e.g. virtualisation.azureImage.diskSize vs e.g. azure.baseImageSize
virtualisation.azureImage = {
#diskSize = targetConfig.baseImageSize;
};
} else {
"${formatConfig}" =
{
# TODO: determine how we can get disk sizes larger than 64GB
# See https://github.com/lkl/linux/issues/466 for more info
inherit (targetConfig) baseImageSize;
};
}
);
# Merge both the base and customized configurations for the specific hub type and format
getFinalHardwareConfig = type: formatConfig:
let
targetConfig = lib.getAttr type configSpecs;
formattedHardwareConfig = getHardwareConfig formatConfig targetConfig;
in
formattedHardwareConfig //
(
if (formatConfig == "virtualbox") then {
virtualbox = {
params = {
inherit (targetConfig) cpus memorySize;
};
};
}// (defaultHardwareConfig "virtualbox") else { }
);
in
with pkgs;
let
inherit cfgFile;
format-type = if (format == "esxi") then "virtualbox" else format;
formatOutput = if (format-type == "virtualbox") then "virtualBoxOVA" else "${format-type}Image";
getFormatConfig = format: "${nixos-generators-path}/formats/${format}.nix";
targetConfig = getFinalHardwareConfig hubType format-type;
# get the correct format-config to pass to nixos-generate.nix
# this is typically retrieved from the $format parameter passed to the nixos-generate (shell) script
format-config = if (format == "esxi") then (getFormatConfig "virtualbox") else (getFormatConfig format);
formattedImage = pkgs.callPackage "${nixos-generators-path}/nixos-generate.nix" {
configuration = { imports = [ cfgFile targetConfig ]; };
inherit format-config;
};
fixedImage =
let
vmConfig = formattedImage.config.system.build;
vboxImage = vmConfig.virtualBoxOVA;
vboxName = vboxImage.name;
in
pkgs.runCommand "fix-esxi-image"
{ }
''
echo "Generating an ESXi image for a ${hubType} hub"
mkdir $out
tar -xvf ${vboxImage}/*.ova
# Get the filenames for the OVF, MF, and VMDK
ovf=$(ls -1 *.ovf)
mf=$(ls -1 *.mf)
vmdk=$(ls -1 *.vmdk)
# Set the VirtualSystemType to VMX-14 to work better with ESXi
sed 's;\(.*<vssd:VirtualSystemType>\).*\(</vssd:VirtualSystemType>\);\1vmx-14\2;;' -i $ovf
# Recalculate the SHA1 hash for the OVF file
sum=$(sha1sum $ovf | cut -d ' ' -f-1)
echo "SHA1SUM for OVF is $sum"
# Update the SHA1 hash for the OVF file in the MF file
sed "s;SHA1 ($ovf) = .*;SHA1 ($ovf) = $sum;;" -i $mf
echo "OVF hash from MF file: $(cat $mf | grep ovf)"
# Recompress the OVF, MF, and VMDK files
tar -cvf nixos.ova $ovf $mf $vmdk
cp nixos.ova $out
'';
in
(if format == "esxi" then fixedImage else formattedImage.config.system.build.${formatOutput})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment