diff --git a/automation/Clean.ps1 b/automation/Clean.ps1 new file mode 100644 index 0000000..06f78e7 --- /dev/null +++ b/automation/Clean.ps1 @@ -0,0 +1,51 @@ + +param( + [string]$SwitchName = "Default Switch", + + [Parameter(Mandatory=$true)] + [string]$VMName, + + [Parameter()] + [string]$Platform = "Hyper-V" +) + +if ($VMName) { + try{ + if ($Platform -eq "Hyper-V") { + $dirPath = "C:\Users\$env:USERNAME\.minikube\machines\$VMName" + Stop-VM -Name $VMName -Force + Remove-Vm -Name $VMName -Force + } + elseif ($Platform -eq "VirtualBox") { + $dirPath = "C:\Users\$env:USERNAME\VirtualBox VMs\$VMName" + & VBoxManage controlvm $VMName poweroff --type headless + & VBoxManage unregistervm $VMName --delete + } + Start-Sleep -Seconds 10 + } + catch { + Write-Warning "Couldn't stop the $VMName Virtual Machine. It doesn't exist. $_" + } + try{ + if (Test-Path $dirPath) { + Remove-Item -Path $dirPath -Recurse -Force + "{0} - * The $dirPath directory has been removed." -f (Get-Date) >> logs + $VHDPath = "${env:homepath}\VirtualBox VMs\$VMName\VHD.vhdx" + # Unregister and delete the existing hard disk if it exists + if (Test-Path $VHDPath) { + & VBoxManage closemedium disk $VHDPath --delete + } + } + else { + Write-Warning "The $dirPath directory doesn't exist." + } + + "{0} - * The $VMName Virtual Machine has been removed." -f (Get-Date) > logs + } + catch { + Write-Warning "Couldn't remove the $VMName directory. It doesn't exist. $_" + } +} +else { + Write-Warning "VMName is required" +} \ No newline at end of file diff --git a/automation/ContainerdTools.psm1 b/automation/ContainerdTools.psm1 index d06493c..74d06b6 100644 --- a/automation/ContainerdTools.psm1 +++ b/automation/ContainerdTools.psm1 @@ -23,7 +23,7 @@ function Install-Containerd { $Version = $Version.TrimStart('v') Write-Output "* Downloading and installing Containerd v$version at $InstallPath" - "Downloading and installing Containerd v$version at $InstallPath" >> logs + "{0} - Downloading and installing Containerd v$version at $InstallPath" -f (Get-Date) >> logs # Download file from repo @@ -50,10 +50,10 @@ function Install-Containerd { Install-RequiredFeature @params | Out-Null Write-Output "* Containerd v$version successfully installed at $InstallPath" - "Containerd v$version successfully installed at $InstallPath" >> logs + "{0} Containerd v$version successfully installed at $InstallPath" -f (Get-Date) >> logs containerd.exe -v >> logs - "For containerd usage: run 'containerd -h'" >> logs + "{0} - For containerd usage: run 'containerd -h'" -f (Get-Date) >> logs } function Start-ContainerdService { @@ -69,7 +69,7 @@ function Start-ContainerdService { } Write-Output "* Containerd is installed and the service is started ..." - "Containerd is installed and the service is started" >> logs + "{0} - Containerd is installed and the service is started" -f (Get-Date) >> logs } @@ -77,7 +77,7 @@ function Stop-ContainerdService { $containerdStatus = Get-Service containerd -ErrorAction SilentlyContinue if (!$containerdStatus) { Write-Warning "Containerd service does not exist as an installed service." - "Containerd service does not exist as an installed service." >> logs + "{0} - Containerd service does not exist as an installed service." -f (Get-Date) >> logs return } @@ -99,7 +99,7 @@ function Initialize-ContainerdService { $ContainerdPath = "$Env:ProgramFiles\containerd" ) - "Configuring the containerd service" >> logs + "{0} - Configuring the containerd service" -f (Get-Date) >> logs #Configure containerd service $containerdConfigFile = "$ContainerdPath\config.toml" diff --git a/automation/Remote.psm1 b/automation/Remote.psm1 index 1abfbf9..386f026 100644 --- a/automation/Remote.psm1 +++ b/automation/Remote.psm1 @@ -36,28 +36,49 @@ function Start-VirtualMachine { [String] [ValidateNotNullOrEmpty()] - $ISOFile + $ISOFile, + + [String] + [ValidateNotNullOrEmpty()] + $Platform = "Hyper-V" ) - # set the vm switch first - $Switch = Set-VmSwitch -SwitchName $SwitchName + if($Platform -eq "Hyper-V"){ + # set the vm switch first + $Switch = Set-VmSwitch -SwitchName $SwitchName + $VM = @{ + Name = $VMName + MemoryStartupBytes = 1GB + NewVHDPath = "${env:homepath}\.minikube\machines\$VMName\VHD.vhdx" + NewVHDSizeBytes = 10GB + BootDevice = "VHD" + Path = "${env:homepath}\.minikube\machines\" + SwitchName = $Switch.Name + } - $VM = @{ - Name = $VMName - MemoryStartupBytes = 1GB - NewVHDPath = "${env:homepath}\.minikube\machines\$VMName\VHD.vhdx" - NewVHDSizeBytes = 10GB - BootDevice = "VHD" - Path = "${env:homepath}\.minikube\machines\" - SwitchName = $Switch.Name + New-VM @VM + + Set-VM -Name $VMName -ProcessorCount 2 -AutomaticCheckpointsEnabled $false + Set-VMProcessor -VMName $VMName -ExposeVirtualizationExtensions $true + Set-VMDvdDrive -VMName $VMName -Path $ISOFile + Start-VM -Name $VMName + } + elseif ($Platform -eq "VirtualBox") { + $VM = @{ + Name = $VMName; + OSType = "Windows10_64"; + Register = $true; + BaseFolder = "${env:homepath}\VirtualBox VMs"; + } + & VBoxManage createvm --name $VM.Name --ostype $VM.OSType --register --basefolder $VM.BaseFolder + & VBoxManage modifyvm $VMName --cpus 2 --memory 1024 | Out-Null + & VBoxManage createmedium disk --filename "${env:homepath}\VirtualBox VMs\$VMName\VHD.vhdx" --size 15000 | Out-Null + & VBoxManage storagectl $VMName --name "IDE Controller" --add ide + & VBoxManage storageattach $VMName --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium "${env:homepath}\VirtualBox VMs\$VMName\VHD.vhdx" | Out-Null + & VBoxManage storageattach $VMName --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium $ISOFilePath | Out-Null + & VBoxManage startvm $VMName --type headless | Out-Null + & VBoxManage modifyvm $VMName --nic1 bridged --bridgeadapter1 $Switch.Name --cableconnected1 on } - - New-VM @VM - - Set-VM -Name $VMName -ProcessorCount 2 -AutomaticCheckpointsEnabled $false - Set-VMProcessor -VMName $VMName -ExposeVirtualizationExtensions $true - Set-VMDvdDrive -VMName $VMName -Path $ISOFile - Start-VM -Name $VMName } function Set-NodeForMinikube { diff --git a/automation/Run.ps1 b/automation/Run.ps1 index fbe5a3a..32b8f31 100644 --- a/automation/Run.ps1 +++ b/automation/Run.ps1 @@ -9,14 +9,24 @@ function Run { [string]$UserName, [string]$Pass, [System.Management.Automation.PSCredential]$Credential, - [string]$KubernetesVersion + [string]$KubernetesVersion, + [ValidateSet("Hyper-V", "VirtualBox")] + [string]$Platform = "Hyper-V" ) # create and configure a new minikube cluster Write-Output "* Creating and configuring a new minikube cluster ..." - & minikube start --driver=hyperv --hyperv-virtual-switch=$SwitchName --nodes=2 --cni=flannel --container-runtime=containerd --kubernetes-version=$KubernetesVersion - # & minikube start --driver=hyperv --hyperv-virtual-switch=$SwitchName --memory=4096 --cpus=2 --kubernetes-version=v1.20.2 --network-plugin=cni --cni=flannel --container-runtime=containerd --disk-size=15GB --wait=false >> logs - Write-Output "* Minikube cluster is created and configured ..." + if ($Platform -eq "Hyper-V") { + & minikube start --driver=hyperv --hyperv-virtual-switch=$SwitchName --nodes=2 --cni=flannel --container-runtime=containerd --kubernetes-version=$KubernetesVersion + # & minikube start --driver=hyperv --hyperv-virtual-switch=$SwitchName --memory=4096 --cpus=2 --kubernetes-version=v1.20.2 --network-plugin=cni --cni=flannel --container-runtime=containerd --disk-size=15GB --wait=false >> logs + } + elseif ($Platform -eq "Virtualbox") { + & minikube start --driver=virtualbox --nodes=2 --cni=flannel --container-runtime=containerd --kubernetes-version=$KubernetesVersion + } else { + Write-Output "Unsupported platform: $Platform" + return + } + Write-Output "* Minikube cluster is created and configured ..." # Prepare the Linux nodes for Windows-specific Flannel CNI configuration # at the moment we are assuming that you only have two linux nodes named minikube and minikube-m02 & minikube ssh "sudo sysctl net.bridge.bridge-nf-call-iptables=1 && exit" >> logs diff --git a/automation/SetUp.ps1 b/automation/SetUp.ps1 index fdecfc5..0efbf33 100644 --- a/automation/SetUp.ps1 +++ b/automation/SetUp.ps1 @@ -13,88 +13,206 @@ param( [Parameter(Mandatory=$true)] [string]$Pass, - [string]$KubernetesVersion + [string]$KubernetesVersion, + + [ValidateSet("Hyper-V", "VirtualBox", "QEMU")] + [string]$Platform = "Hyper-V" ) Import-Module -Name "$PSScriptRoot\k8Tools.psm1" -Force - if ([string]::IsNullOrEmpty($KubernetesVersion)) { $KubernetesVersion = Get-k8LatestVersion Write-Output "* The latest Kubernetes version is $KubernetesVersion" $KubernetesVersion = $KubernetesVersion.TrimStart('v') } - -"* Starting the $VMName Virtual Machine ..." > logs +"{0} - * Starting the $VMName Virtual Machine ..." -f (Get-Date) > logs Write-Output "* Starting the $VMName Virtual Machine ..." -$VM = @{ - Name = $VMName; - Generation = 1; - MemoryStartupBytes = 1GB; - NewVHDPath = "${env:homepath}\.minikube\machines\$VMName\VHD.vhdx"; - NewVHDSizeBytes = 15GB; - BootDevice = "VHD"; - Path = "${env:homepath}\.minikube\machines\"; - SwitchName = $SwitchName -} +if ($Platform -eq "Hyper-V") { + $VM = @{ + Name = $VMName; + Generation = 1; + MemoryStartupBytes = 1GB; + NewVHDPath = "${env:homepath}\.minikube\machines\$VMName\VHD.vhdx"; + NewVHDSizeBytes = 15GB; + BootDevice = "VHD"; + Path = "${env:homepath}\.minikube\machines\"; + SwitchName = $SwitchName + } + Write-Output "* Please wait as we set up the $VMName Virtual Machine ..." + "{0} - Please wait as we set up the $VMName Virtual Machine ..." -f (Get-Date) >> logs + New-VM @VM | Out-Null + Set-VM -Name $VMName -ProcessorCount 2 -AutomaticCheckpointsEnabled $false + Set-VMProcessor -VMName $VMName -ExposeVirtualizationExtensions $true + Set-VMDvdDrive -VMName $VMName -Path $ISOFilePath + Start-VM -Name $VMName | Out-Null + + $timeout = 600 + $retryInterval = 15 + $elapsedTime = 0 + + do { + Start-Sleep -Seconds $retryInterval + + "{0} - Waiting for the VM to start ..." -f (Get-Date) >> logs + $heartbeat = Get-VMIntegrationService -VMName $VMName -Name "Heartbeat" + $elapsedTime += $retryInterval + + if ($elapsedTime -ge $timeout) { + Write-Output "* Timeout reached. Unable to start the VM ..." + Write-Output "* Exiting the script ..." + "Timeout reached. Exiting the script ..." >> logs + "Exiting the script ..." >> logs + exit + } + } while ($heartbeat.PrimaryStatusDescription -ne "OK") -Write-Output "* Please wait as we set up the $VMName Virtual Machine ..." -New-VM @VM | Out-Null -Set-VM -Name $VMName -ProcessorCount 2 -AutomaticCheckpointsEnabled $false -Set-VMProcessor -VMName $VMName -ExposeVirtualizationExtensions $true -Set-VMDvdDrive -VMName $VMName -Path $ISOFilePath -# Add-VMDvdDrive -VMName $VMName -Path "$PSScriptRoot\auto-install.iso" -ControllerNumber 1 -ControllerLocation 1 -Start-VM -Name $VMName | Out-Null + Write-Output "* The $VMName Virtual Machine is started ..." + $SecurePassword = ConvertTo-SecureString -String $Pass -AsPlainText -Force + $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, $SecurePassword + $VMStatus = Get-VM -Name $VMName | Select-Object -ExpandProperty State -$timeout = 600 -$retryInterval = 15 -$elapsedTime = 0 + $VMName = Get-VM | Select-Object -ExpandProperty Name -do { - Start-Sleep -Seconds $retryInterval - "Waiting for the VM to start ..." >> logs - $heartbeat = Get-VMIntegrationService -VMName $VMName -Name "Heartbeat" - $elapsedTime += $retryInterval + if ($VMStatus -eq 'Running') { + "The $VMName Virtual Machine is running" >> logs - if ($elapsedTime -ge $timeout) { - Write-Output "* Timeout reached. Unable to start the VM ..." - Write-Output "* Exiting the script ..." - "Timeout reached. Exiting the script ..." >> logs - "Exiting the script ..." >> logs + $retryInterval = 45 + $timeout = 120 + $elapsedTime = 0 + + do { + try { + $os = Invoke-Command -VMName $VMName -Credential $Credential -ScriptBlock { Get-WmiObject -Query "SELECT * FROM Win32_OperatingSystem" } -ErrorAction Stop + + if ($os) { + Write-Output "* Windows is successfully installed on $VMName" + "Windows is successfully installed on $VMName" >> logs + . .\Run.ps1 + RUN -VMName $VMName -UserName $UserName -Pass $Pass -Credential $Credential -KubernetesVersion $KubernetesVersion + break + } else { + Write-Output "* Windows is not installed on $VMName" + } + } catch { + Write-Output "* An error occurred while checking if Windows is installed on ${VMName}: $_" + } + Start-Sleep -Seconds $retryInterval + $elapsedTime += $retryInterval + } while ($elapsedTime -lt $timeout) + + } else { + Write-Output "The VM $VMName is not running" + } + +} elseif ($Platform -eq "VirtualBox") { + $VM = @{ + Name = $VMName; + OSType = "Windows10_64"; + Register = $true; + BaseFolder = "${env:homepath}\VirtualBox VMs"; + } + & VBoxManage createvm --name $VM.Name --ostype $VM.OSType --register --basefolder $VM.BaseFolder + & VBoxManage modifyvm $VMName --cpus 2 --memory 1024 | Out-Null + & VBoxManage createmedium disk --filename "${env:homepath}\VirtualBox VMs\$VMName\VHD.vhdx" --size 15000 | Out-Null + & VBoxManage storagectl $VMName --name "IDE Controller" --add ide + & VBoxManage storageattach $VMName --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium "${env:homepath}\VirtualBox VMs\$VMName\VHD.vhdx" | Out-Null + & VBoxManage storageattach $VMName --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium $ISOFilePath | Out-Null + & VBoxManage startvm $VMName --type headless | Out-Null + $runningVMs = & VBoxManage list runningvms + if ($runningVMs -like "*$VMName*") { + Write-Output "The $VMName Virtual Machine is running" >> logs + $retryInterval = 45 + $timeout = 120 + $elapsedTime = 0 + do { + try { + $os = & VBoxManage guestproperty get $VMName "/VirtualBox/GuestInfo/OS/Product" + if ($os) { + Write-Output "* Windows is successfully installed on $VMName" + "Windows is successfully installed on $VMName" >> logs + . .\Run.ps1 + RUN -VMName $VMName -UserName $UserName -Pass $Pass -Credential $Credential -KubernetesVersion $KubernetesVersion -Platform $Platform + break + } else { + Write-Output "* Windows is not installed on $VMName" + } + } catch { + Write-Output "* An error occurred while checking if Windows is installed on ${VMName}: $_" + } + Start-Sleep -Seconds $retryInterval + $elapsedTime += $retryInterval + } while ($elapsedTime -lt $timeout) + } else { + Write-Output "The VM $VMName is not running" + } + +} elseif ($Platform -eq "QEMU") { + $VM = @{ + Name = $VMName; + Memory = 1024; + CPUs = 2; + DiskPath = "${env:homepath}\QEMU\$VMName\VHD.vhdx"; + DiskSize = "15G"; + ISOPath = $ISOFilePath; + } + $diskPath = $VM.DiskPath + $diskDir = Split-Path -Path $diskPath -Parent + if (-Not (Test-Path -Path $diskDir)) { + New-Item -ItemType Directory -Path $diskDir -Force | Out-Null + } + & qemu-img create -f vhdx $VM.DiskPath $VM.DiskSize | Out-Null + + if (-not [int]::TryParse($VM.CPUs, [ref]$null)) { + Write-Output "Error: CPUs value '$($VM.CPUs)' is not a valid integer." exit } -} while ($heartbeat.PrimaryStatusDescription -ne "OK") -Write-Output "* The $VMName Virtual Machine is started ..." + Write-Output "Debug: CPUs value is $($VM.CPUs)" + & qemu-system-x86_64 -m $VM.Memory -smp $VM.CPUs -drive file="$($VM.DiskPath)",format=vhdx -cdrom "$($VM.ISOPath)" -boot d -net nic -net user,hostfwd=tcp::2222-:22 -machine type=pc -$SecurePassword = ConvertTo-SecureString -String $Pass -AsPlainText -Force -$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, $SecurePassword + $timeout = 600 + $retryInterval = 15 + $elapsedTime = 0 -$VMStatus = Get-VM -Name $VMName | Select-Object -ExpandProperty State + do { + Start-Sleep -Seconds $retryInterval -if ($VMStatus -eq 'Running') { - - "The $VMName Virtual Machine is running" >> logs + "{0} - Waiting for the VM to start ..." -f (Get-Date) >> logs + $result = & qemu-system-x86_64 -machine query-status | ConvertFrom-Json + $elapsedTime += $retryInterval + + if ($elapsedTime -ge $timeout) { + Write-Output "* Timeout reached. Unable to start the VM ..." + Write-Output "* Exiting the script ..." + "Timeout reached. Exiting the script ..." >> logs + "Exiting the script ..." >> logs + exit + } + } while ($result.Status -ne "running") + + Write-Output "* The $VMName Virtual Machine is started ..." + + $SecurePassword = ConvertTo-SecureString -String $Pass -AsPlainText -Force + $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, $SecurePassword $retryInterval = 45 $timeout = 120 $elapsedTime = 0 do { - try { - $os = Invoke-Command -VMName $VMName -Credential $Credential -ScriptBlock { Get-WmiObject -Query "SELECT * FROM Win32_OperatingSystem" } -ErrorAction Stop + $os = Invoke-Command -Hostname localhost -Port 2222 -Credential $Credential -ScriptBlock { Get-WmiObject -Query "SELECT * FROM Win32_OperatingSystem" } -ErrorAction Stop if ($os) { Write-Output "* Windows is successfully installed on $VMName" "Windows is successfully installed on $VMName" >> logs . .\Run.ps1 - # . "$PSScriptRoot\Run.ps1" === this also works RUN -VMName $VMName -UserName $UserName -Pass $Pass -Credential $Credential -KubernetesVersion $KubernetesVersion break } else { @@ -106,7 +224,8 @@ if ($VMStatus -eq 'Running') { Start-Sleep -Seconds $retryInterval $elapsedTime += $retryInterval } while ($elapsedTime -lt $timeout) - } else { - Write-Output "The VM $VMName is not running" + Write-Output "* Unsupported platform specified: $Platform" + exit } + \ No newline at end of file