VBox.ps1


if ($null -eq (get-command VBoxManage.exe -errorAction silentlyContinue) ) {
  $env:path = "C:\Program Files\Oracle\VirtualBox;$env:path"
}

#LockType
$LockType_Shared = 1
$LockType_Write = 2

$global:vboxcom

class Box {
  [string] $Name
  [string] $Address
}

function Connect-VBox() {
  param(
    [Parameter(position = 0, mandatory = $True)]
    [string] $Name 
  )

  # get Ip from $Name

  Connect-Ssh -Ip "192.168.56.20"

  
}

function Get-VBox() {

  $vbox = Get-VBoxCom
  $machines = $vbox.Machines
  Write-Host ($machines | Format-Table -GroupBy Name -Property Name, State | Out-String)
}

function Get-VBoxCom {
  if (-Not($global:vboxcom)) {
    $global:vboxcom = New-Object -ComObject "VirtualBox.VirtualBox"
    $status = "VirtualBox v{0} rev.{1}" -f $global:vboxcom.version, $global:vboxcom.revision
    Write-Host $status -ForegroundColor Cyan
  }
  return $global:vboxcom
}

# https://www.virtualbox.org/manual/ch08.html#vboxmanage-dhcpserver
function Get-VBoxHostOnlyAdpater {

  <#
  vboxmanage showvminfo core | grep "NIC 1:" | awk '{print tolower($4)}' | sed 's/.\{2\}/&:/g' | sed 's/.\{2\}$//'
 
arp -a | grep 08:00:27:a5:db:a3 | awk '{print $2}' | tail -c +2 | head -c -2
        #vboxmanage hostonlyif ipconfig $ifname --ip 192.168.56.1 --netmask 255.255.255.0
        #vboxmanage dhcpserver modify --ifname $ifname --disable
 
  #>


  #https://www.virtualbox.org/manual/ch08.html#vboxmanage-dhcpserver

  # ip -o -4 addr
  # IP address for the host 192.168.56.1
  # DHCP-Server Range 192.168.56.101 - 192.168.56.254
  # The IP range limiting the IP addresses that will be provided to the guest systems 192.168.56.2 - 192.168.56.100

  # TODO get name from ComObject

  $list = vboxmanage list hostonlyifs
  $name = $list[0] | Select-String '^Name:\s+(\w+)'
  if ($list -notlike "*$adapter*") {
    Write-Error ("box: host-only not found: $adapter")
    exit
  }

  return $name
}


function Get-VBoxPath {
  param(
    [string] $Name
  )

  $path = Get-BoxPath -Path "vbox"
  if ($Name) {
    $path = Join-Path $path $Name
  }
  return $path
}

function New-VBox() {
  param(
    [Parameter(Mandatory = $true)]
    [string] $Name,
    [string] $ImageVersion = "24.04" 
  )

  $box = [Box]::new()
  $box.Name = $Name
  $box.Address = "192.168.56.20/24"

  $image = Get-CloudImage -ImageVersion $ImageVersion
  $seedIso = New-CloudInit -Path (Get-VBoxPath -Name $box.Name) -Hostname $box.Name -Address $box.Address
  
  Write-Host("Creating machine '${Name}' ...")
  vboxmanage import $image --vsys 0 --vmname $box.Name --options importtovdi --basefolder (Get-VBoxPath)
  vboxmanage modifyvm $box.Name --nic1 nat
  vboxmanage modifyvm $box.Name --nic2 hostonly --hostonlyadapter2 (Get-VBoxHostOnlyAdpater)
  vboxmanage storageattach $box.Name --storagectl IDE --port 0 --device 0 --type dvddrive --medium $seedIso
}

function New-VBoxTmp {

  Write-Verbose "Creating the VirtualBox COM object"
  $vbox = New-Object -ComObject "VirtualBox.VirtualBox"
  $machines = $vbox.Machines
  Write-Host ($machines | Format-List | Out-String)

  # https://gitlab.com/xtec/box/-/blob/acc37ba85b4650806904c50306ecd12962b7090a/box.ps1

  
}


function Remove-VBox() {
  param(
    [Parameter(Position = 0, Mandatory = $True, HelpMessage = "Enter a virtual machine name")]
    [ValidateNotNullorEmpty()]
    [string] $Name 
  )

  try {
    $vbox = Get-VBoxCom
    $vbox.FindMachine($Name) | Out-Null
    Stop-VBox $Name
    Write-Host("Removing machine '${Name}' ...")
    vboxmanage unregistervm $Name --delete
  }
  catch {
    Write-Host -f Yellow $_
  }

  Remove-Item -Path (Get-VBoxPath $Name) -Recurse -Force -ErrorAction Ignore
}

#$json = $vm | ConvertTo-Json
#Write-Host($json)

#https://www.virtualbox.org/sdkref/interface_i_machine.html#af28da645b00a821547d9cb8e92f8b7b0

# https://www.virtualbox.org/sdkref/interface_i_console.html

function Start-VBox() {
  [cmdletbinding()]
  param(
    [Parameter(Position = 0, Mandatory = $True, HelpMessage = "Enter a virtual machine name", ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
    [ValidateNotNullorEmpty()]
    [string] $Name,
    [switch] $New 
  )

  try {
    $vbox = Get-VBoxCom
    $machine = $vbox.FindMachine($name)
  }
  catch {
    if ($New) {
      New-VBox $Name
    }
    else {
      Write-Host -f Yellow $_
      return
    }
  }

  if ($machine.State -lt 5) {
    
    $session = New-Object -ComObject "VirtualBox.Session"

    Write-Host("Starting machine '${Name}' ...")
    vboxmanage startvm $Name --type headless


    #$machine.GetType() | Out-Host
    # https://www.virtualbox.org/sdkref/interface_i_machine.html#aa75e76da42ef908795d235d995262c6f
    #$machine.GetSerialPort(1) | Out-Host
    #$machine.LockMachine($session, 1)
    #$progress = $machine.LaunchVMProcess($session, "headless", "")
    #Write-Host("Starting VM ...")
    #$progress.WaitForCompletion(-1)
  }
  else {
    Write-Host "I can only start machines that have been stopped." -ForegroundColor Magenta
  }

}

function Stop-VBox() {

  param(
    [Parameter(Position = 0, Mandatory = $True, HelpMessage = "Power off (stop) a running VM.")]
    [ValidateNotNullorEmpty()]
    [string] $Name 
  )   

  try {
    $vbox = Get-VBoxCom
    $machine = $vbox.FindMachine($Name)
  }
  catch {
    Write-Host -f Yellow $_
    return
  }

  # Virtual machine must be Running, Paused or Stuck to be powered down.
  if (@(5, 6, 7) -Contains $machine.State) {
    $session = New-Object -ComObject "VirtualBox.Session"
    $machine.LockMachine($session, $LockType_Shared)
    $progress = $session.Console.PowerDown()
    Write-Host("Stopping machine '${Name}' ...")
    $progress.WaitForCompletion(-1)
    #$session.UnlockMachine()
  }
}



function StateAsString {
  param(
    [int] $State
  )

  
  Switch ($vstate) {
    1 { "Stopped" }
    2 { "Saved" }
    3 { "Teleported" }
    4 { "Aborted" }
    5 { "Running" }
    6 { "Paused" }
    7 { "Stuck" }
    8 { "Snapshotting" }
    9 { "Starting" }
    10 { "Stopping" }
    11 { "Restoring" }
    12 { "TeleportingPausedVM" }
    13 { "TeleportingIn" }
    14 { "FaultTolerantSync" }
    15 { "DeletingSnapshotOnline" }
    16 { "DeletingSnapshot" }
    17 { "SettingUp" }
  }
}

<#
if ($null -eq (get-command VBoxManage.exe -errorAction silentlyContinue) ) {
    $env:path = "C:\Program Files\Oracle\VirtualBox;$env:path"
}
 
#>