OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
HASH      df43606f2e0f
DATE      2025-05-03
SUBJECT   virtualization: nixos install vm script init
FILES     3 CHANGED
HASH      df43606f2e0f
DATE      2025-05-03
SUBJECT   virtualization: nixos install vm
          script init
FILES     3 CHANGED
 

diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix
index 0452446..549c5f8 100644
--- a/hosts/ooksdesk/default.nix
+++ b/hosts/ooksdesk/default.nix
@@ -36,6 +36,9 @@
       editor = "nvim";
       multiplexer = "zellij";
     };
+    virtualization = {
+      ooknet-install-vm.enable = true;
+    };
   };
   boot.kernelPackages = pkgs.linuxPackages_xanmod_latest;
 

diff --git a/hosts/ooksdesk/default.nix b/ho
sts/ooksdesk/default.nix
index 0452446..549c5f8 100644
--- a/hosts/ooksdesk/default.nix
+++ b/hosts/ooksdesk/default.nix
@@ -36,6 +36,9 @@
       editor = "nvim";
       multiplexer = "zellij";
     };
+    virtualization = {
+      ooknet-install-vm.enable = true;
+    };
   };
   boot.kernelPackages = pkgs.linuxPackages_
xanmod_latest;
 
 

diff --git a/modules/nixos/workstation/virtualization/default.nix b/modules/nixos/
workstation/virtualization/default.nix
index 9c7be83..03eb893 100644
--- a/modules/nixos/workstation/virtualization/default.nix
+++ b/modules/nixos/workstation/virtualization/default.nix
@@ -1,5 +1,6 @@
 {
   imports = [
     ./virt-manager.nix
+    ./ooknet-install-vm.nix
   ];
 }

diff --git a/modules/nixos/workstation/virtu
alization/default.nix b/modules/nixos/workst
ation/virtualization/default.nix
index 9c7be83..03eb893 100644
--- a/modules/nixos/workstation/virtualizati
on/default.nix
+++ b/modules/nixos/workstation/virtualizati
on/default.nix
@@ -1,5 +1,6 @@
 {
   imports = [
     ./virt-manager.nix
+    ./ooknet-install-vm.nix
   ];
 }
 

diff --git a/modules/nixos/workstation/virtualization/ooknet-install-vm.nix b/modu
les/nixos/workstation/virtualization/ooknet-install-vm.nix
new file mode 100644
index 0000000..1048aaa
--- /dev/null
+++ b/modules/nixos/workstation/virtualization/ooknet-install-vm.nix
@@ -0,0 +1,204 @@
+{
+  pkgs,
+  lib,
+  config,
+  self,
+  ...
+}: let
+  inherit (builtins) toFile;
+  inherit (lib) mkIf mkEnableOption mkOption;
+  inherit (lib.types) path string int;
+  inherit (self.nixosConfigurations.ooksinstall.config.image) filePath;
+  inherit (config.ooknet.host) admin;
+  iso = self.images.ooksinstall;
+  checkSudo =
+    if config.virtualisation.libvirtd.qemu.runAsRoot
+    then ''
+      if [ "$EUID" -ne 0 ]; then
+        log error "Sudo not provided: set 'virtualisation.libvirtd.qemu.runAsRoot
 = false;' to use without sudo."
+        exit 1
+      fi
+    ''
+    else "";
+  networkConfig = toFile "ooknet-install-network.xml" ''
+    <network>
+      <name>${cfg.network.name}</name>
+      <bridge name='${cfg.network.bridgeName}' stp='on' delay='0'/>
+      <forward mode='nat'/>
+      <ip address='${cfg.network.ip}' netmask='255.255.255.0'>
+        <dhcp>
+          <range start='${cfg.network.ipRange.start}' end='${cfg.network.ipRange.
end}'/>
+          <host mac='${cfg.macAddress}' name='${cfg.name}' ip='${cfg.ipAddress}'/
>
+        </dhcp>
+      </ip>
+    </network>
+  '';
+  cfg = config.ooknet.virtualization.ooknet-install-vm;
+in {
+  options.ooknet.virtualization = {
+    ooknet-install-vm = {
+      enable = mkEnableOption "Enable virtual installation testing environment";
+      isoPath = mkOption {
+        type = path;
+        default = "${iso}/${filePath}";
+        description = "Path to iso to use";
+      };
+      name = mkOption {
+        type = string;
+        default = "ooknet-install-test";
+        description = "Name of virtual machine";
+      };
+      user = mkOption {
+        type = string;
+        default = admin.name;
+        description = "SSH user to connect to virtual machine";
+        example = "root";
+      };
+      macAddress = mkOption {
+        type = string;
+        default = "52:55:00:11:22:33";
+      };
+      ipAddress = mkOption {
+        type = string;
+        default = cfg.network.ipRange.start;
+        description = "IP address to assign to the virtual machine";
+      };
+      ram = mkOption {
+        type = int;
+        default = 2048;
+        description = "Amount of RAM to assign to the virtual machine";
+        example = 2048;
+      };
+      vcpus = mkOption {
+        type = int;
+        default = 2;
+        description = "Amount of cores to assign to the virtual machine";
+        example = 4;
+      };
+      storage = mkOption {
+        type = int;
+        default = 10;
+        description = "Amount in GB of storage to assign to the virtual machine";
+        example = 10;
+      };
+      network = {
+        name = mkOption {
+          type = string;
+          default = "ooknet-install-network";
+          description = "Name of virtual network";
+        };
+        bridgeName = mkOption {
+          type = string;
+          default = "virbr1";
+          description = "Name of virtual network bridge";
+        };
+        ip = mkOption {
+          type = string;
+          default = "192.168.150.1";
+        };
+        ipRange = {
+          start = mkOption {
+            type = string;
+            default = "192.168.150.2";
+          };
+          end = mkOption {
+            type = string;
+            default = "192.168.150.2";
+          };
+        };
+      };
+    };
+  };
+  config = mkIf cfg.enable {
+    environment.systemPackages = [
+      (pkgs.writeShellApplication {
+        name = "ooknet-test-vm";
+        runtimeInputs = [
+          pkgs.gum
+        ];
+        text = ''
+          set -e
+
+          log() {
+            local type="$1"
+            local message="$2"
+            gum log --structured --level "$type" "$message"
+          }
+
+          ${checkSudo}
+
+          NAME=${cfg.name}
+          IMAGE_PATH="/var/lib/libvirt/images/$NAME.img"
+
+          buildVM() {
+            log info "Setting up virtual network..."
+            if ! virsh net-info ${cfg.network.name} >/dev/null 2>&1; then
+              virsh net-define ${networkConfig} >/dev/null
+              log info "Network defined..."
+            else
+              log warn "Network was already defined..."
+              destroyNetwork
+              virsh net-define ${networkConfig} >/dev/null
+            fi
+            virsh net-start ${cfg.network.name} >/dev/null || true
+            log info "Network started..."
+
+            log info "Building $NAME VM..."
+            gum spin --spinner dot --title "Installing VM..." -- \
+            virt-install \
+              -n "$NAME" \
+              --ram=${toString cfg.ram} \
+              --vcpus=${toString cfg.vcpus} \
+              --disk path="$IMAGE_PATH",bus=virtio,size=${toString cfg.storage} \
+              --graphics none \
+              --cdrom ${cfg.isoPath} \
+              --network network=${cfg.network.name},mac=${cfg.macAddress} \
+              --noautoconsole;
+          }
+
+          destroyNetwork() {
+            virsh net-destroy ${cfg.network.name}
+            log info "Network destroyed";
+            virsh net-undefine ${cfg.network.name}
+            log info "Network undefined"
+          }
+
+          destroyVM() {
+            log warn "Shutting VM down..."
+            virsh destroy "$NAME" >/dev/null || true
+            log warn "Deleting VM..."
+            virsh undefine "$NAME" --remove-all-storage >/dev/null
+            log info "VM successfully removed..."
+          }
+
+          gum log --structured --level info "Checking if image already exists..."
+
+          if virsh list --all | grep -q "\b$NAME\b"; then
+            log info "$NAME VM Found:"
+            if gum confirm "Remove existing $NAME VM?"; then
+              destroyVM
+              buildVM
+            else
+              log info "Aborting VM creation..."
+              exit 0
+            fi
+          elif [ -f "$IMAGE_PATH" ]; then
+            log warn "Disk Image for '$NAME' exists without VM"
+            if gum confirm "Would you like to remove the orphaned disk?"; then
+              rm -f "$IMAGE_PATH"
+              buildVM
+            else
+              log error "Cannot create VM while orphaned disk exists"
+              exit 1
+            fi
+          else
+            buildVM
+          fi
+
+          log info "VM successfully created"
+          log info "Connect with: ssh ${cfg.user}@${cfg.ipAddress}"
+        '';
+      })
+    ];
+  };
+}

diff --git a/modules/nixos/workstation/virtu
alization/ooknet-install-vm.nix b/modules/ni
xos/workstation/virtualization/ooknet-instal
l-vm.nix
new file mode 100644
index 0000000..1048aaa
--- /dev/null
+++ b/modules/nixos/workstation/virtualizati
on/ooknet-install-vm.nix
@@ -0,0 +1,204 @@
+{
+  pkgs,
+  lib,
+  config,
+  self,
+  ...
+}: let
+  inherit (builtins) toFile;
+  inherit (lib) mkIf mkEnableOption mkOptio
n;
+  inherit (lib.types) path string int;
+  inherit (self.nixosConfigurations.ooksins
tall.config.image) filePath;
+  inherit (config.ooknet.host) admin;
+  iso = self.images.ooksinstall;
+  checkSudo =
+    if config.virtualisation.libvirtd.qemu.
runAsRoot
+    then ''
+      if [ "$EUID" -ne 0 ]; then
+        log error "Sudo not provided: set '
virtualisation.libvirtd.qemu.runAsRoot = fal
se;' to use without sudo."
+        exit 1
+      fi
+    ''
+    else "";
+  networkConfig = toFile "ooknet-install-ne
twork.xml" ''
+    <network>
+      <name>${cfg.network.name}</name>
+      <bridge name='${cfg.network.bridgeNam
e}' stp='on' delay='0'/>
+      <forward mode='nat'/>
+      <ip address='${cfg.network.ip}' netma
sk='255.255.255.0'>
+        <dhcp>
+          <range start='${cfg.network.ipRan
ge.start}' end='${cfg.network.ipRange.end}'/
>
+          <host mac='${cfg.macAddress}' nam
e='${cfg.name}' ip='${cfg.ipAddress}'/>
+        </dhcp>
+      </ip>
+    </network>
+  '';
+  cfg = config.ooknet.virtualization.ooknet
-install-vm;
+in {
+  options.ooknet.virtualization = {
+    ooknet-install-vm = {
+      enable = mkEnableOption "Enable virtu
al installation testing environment";
+      isoPath = mkOption {
+        type = path;
+        default = "${iso}/${filePath}";
+        description = "Path to iso to use";
+      };
+      name = mkOption {
+        type = string;
+        default = "ooknet-install-test";
+        description = "Name of virtual mach
ine";
+      };
+      user = mkOption {
+        type = string;
+        default = admin.name;
+        description = "SSH user to connect 
to virtual machine";
+        example = "root";
+      };
+      macAddress = mkOption {
+        type = string;
+        default = "52:55:00:11:22:33";
+      };
+      ipAddress = mkOption {
+        type = string;
+        default = cfg.network.ipRange.start
;
+        description = "IP address to assign
 to the virtual machine";
+      };
+      ram = mkOption {
+        type = int;
+        default = 2048;
+        description = "Amount of RAM to ass
ign to the virtual machine";
+        example = 2048;
+      };
+      vcpus = mkOption {
+        type = int;
+        default = 2;
+        description = "Amount of cores to a
ssign to the virtual machine";
+        example = 4;
+      };
+      storage = mkOption {
+        type = int;
+        default = 10;
+        description = "Amount in GB of stor
age to assign to the virtual machine";
+        example = 10;
+      };
+      network = {
+        name = mkOption {
+          type = string;
+          default = "ooknet-install-network
";
+          description = "Name of virtual ne
twork";
+        };
+        bridgeName = mkOption {
+          type = string;
+          default = "virbr1";
+          description = "Name of virtual ne
twork bridge";
+        };
+        ip = mkOption {
+          type = string;
+          default = "192.168.150.1";
+        };
+        ipRange = {
+          start = mkOption {
+            type = string;
+            default = "192.168.150.2";
+          };
+          end = mkOption {
+            type = string;
+            default = "192.168.150.2";
+          };
+        };
+      };
+    };
+  };
+  config = mkIf cfg.enable {
+    environment.systemPackages = [
+      (pkgs.writeShellApplication {
+        name = "ooknet-test-vm";
+        runtimeInputs = [
+          pkgs.gum
+        ];
+        text = ''
+          set -e
+
+          log() {
+            local type="$1"
+            local message="$2"
+            gum log --structured --level "$
type" "$message"
+          }
+
+          ${checkSudo}
+
+          NAME=${cfg.name}
+          IMAGE_PATH="/var/lib/libvirt/imag
es/$NAME.img"
+
+          buildVM() {
+            log info "Setting up virtual ne
twork..."
+            if ! virsh net-info ${cfg.netwo
rk.name} >/dev/null 2>&1; then
+              virsh net-define ${networkCon
fig} >/dev/null
+              log info "Network defined..."
+            else
+              log warn "Network was already
 defined..."
+              destroyNetwork
+              virsh net-define ${networkCon
fig} >/dev/null
+            fi
+            virsh net-start ${cfg.network.n
ame} >/dev/null || true
+            log info "Network started..."
+
+            log info "Building $NAME VM..."
+            gum spin --spinner dot --title 
"Installing VM..." -- \
+            virt-install \
+              -n "$NAME" \
+              --ram=${toString cfg.ram} \
+              --vcpus=${toString cfg.vcpus}
 \
+              --disk path="$IMAGE_PATH",bus
=virtio,size=${toString cfg.storage} \
+              --graphics none \
+              --cdrom ${cfg.isoPath} \
+              --network network=${cfg.netwo
rk.name},mac=${cfg.macAddress} \
+              --noautoconsole;
+          }
+
+          destroyNetwork() {
+            virsh net-destroy ${cfg.network
.name}
+            log info "Network destroyed";
+            virsh net-undefine ${cfg.networ
k.name}
+            log info "Network undefined"
+          }
+
+          destroyVM() {
+            log warn "Shutting VM down..."
+            virsh destroy "$NAME" >/dev/nul
l || true
+            log warn "Deleting VM..."
+            virsh undefine "$NAME" --remove
-all-storage >/dev/null
+            log info "VM successfully remov
ed..."
+          }
+
+          gum log --structured --level info
 "Checking if image already exists..."
+
+          if virsh list --all | grep -q "\b
$NAME\b"; then
+            log info "$NAME VM Found:"
+            if gum confirm "Remove existing
 $NAME VM?"; then
+              destroyVM
+              buildVM
+            else
+              log info "Aborting VM creatio
n..."
+              exit 0
+            fi
+          elif [ -f "$IMAGE_PATH" ]; then
+            log warn "Disk Image for '$NAME
' exists without VM"
+            if gum confirm "Would you like 
to remove the orphaned disk?"; then
+              rm -f "$IMAGE_PATH"
+              buildVM
+            else
+              log error "Cannot create VM w
hile orphaned disk exists"
+              exit 1
+            fi
+          else
+            buildVM
+          fi
+
+          log info "VM successfully created
"
+          log info "Connect with: ssh ${cfg
.user}@${cfg.ipAddress}"
+        '';
+      })
+    ];
+  };
+}
 
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET