AutomatedLabVMWareWorkerVirtualMachines.psm1
trap { if ((($_.Exception.Message -like '*Get-VM*') -or ` ($_.Exception.Message -like '*Save-VM*') -or ` ($_.Exception.Message -like '*Get-VMSnapshot*') -or ` ($_.Exception.Message -like '*Suspend-VM*') -or ` ($_.Exception.Message -like '*CheckPoint-VM*')) -and (-not (Get-Module -ListAvailable Hyper-V))) { } else { Write-Error $_ } continue } #region New-LWVMWareVM function New-LWVMWareVM { [Cmdletbinding()] Param ( [Parameter(Mandatory)] [string]$Name, [Parameter(Mandatory)] [string]$ReferenceVM, [Parameter(Mandatory)] [string]$AdminUserName, [Parameter(Mandatory)] [string]$AdminPassword, [Parameter(ParameterSetName = 'DomainJoin')] [string]$DomainName, [Parameter(Mandatory, ParameterSetName = 'DomainJoin')] [pscredential]$DomainJoinCredential, [switch]$AsJob, [switch]$PassThru ) Write-LogFunctionEntry $lab = Get-Lab $folderName = 'Microsoft Workshop' $parameters = @{ Name = $Name ReferenceVM = $ReferenceVM AdminUserName = $AdminUserName AdminPassword = $AdminPassword DomainName = $DomainName DomainCred = $DomainJoinCredential FolderName = $FolderName } if ($AsJob) { $job = Start-Job -ScriptBlock { throw 'Not implemented yet' } -ArgumentList $parameters if ($PassThru) { $job } } else { $osSpecs = Get-OSCustomizationSpec -Name AutomatedLabSpec -Type NonPersistent -ErrorAction SilentlyContinue if ($osSpecs) { Remove-OSCustomizationSpec -OSCustomizationSpec $osSpecs -Confirm:$false } if (-not $parameters.DomainName) { $osSpecs = New-OSCustomizationSpec -Name AutomatedLabSpec -FullName $parameters.AdminUserName -AdminPassword $parameters.AdminPassword ` -OSType Windows -Type NonPersistent -OrgName AutomatedLab -Workgroup AutomatedLab -ChangeSid #$osSpecs = Get-OSCustomizationSpec -Name Standard | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $ipaddress -SubnetMask $netmask -DefaultGateway $gateway -Dns $DNS } else { $osSpecs = New-OSCustomizationSpec -Name AutomatedLabSpec -FullName $parameters.AdminUserName -AdminPassword $parameters.AdminPassword ` -OSType Windows -Type NonPersistent -OrgName AutomatedLab -Domain $parameters.DomainName -DomainCredentials $DomainJoinCredential -ChangeSid } $referenceVM = Get-VM -Name $parameters.ReferenceVM if (-not $referenceVM) { Write-Error "Reference VM '$($parameters.ReferenceVM)' could not be found, cannot create the machine '$($machine.Name)'" return } $result = New-VM -Name $parameters.Name -VM $referenceVM -ResourcePool $lab.VMWareSettings.ResourcePool ` -Datastore $lab.VMWareSettings.DataStore -Location (Get-Folder -Name $parameters.FolderName) -OSCustomizationSpec $osSpecs } if ($PassThru) { $result } Write-LogFunctionExit } #endregion New-LWVM #region Remove-LWVMWareVM function Remove-LWVMWareVM { Param ( [Parameter(Mandatory)] [string]$ComputerName, [switch]$AsJob, [switch]$PassThru ) Write-LogFunctionEntry if ($AsJob) { $job = Start-Job -ScriptBlock { param ( [Parameter(Mandatory)] [hashtable]$ComputerName ) Add-PSSnapin -Name VMware.VimAutomation.Core, VMware.VimAutomation.Vds $vm = Get-VM -Name $ComputerName if ($vm) { if ($vm.PowerState -eq "PoweredOn") { Stop-vm -VM $vm -Confirm:$false } Remove-VM -DeletePermanently -VM $ComputerName -Confirm:$false } } -ArgumentList $ComputerName if ($PassThru) { $job } } else { $vm = Get-VM -Name $ComputerName if ($vm) { if ($vm.PowerState -eq "PoweredOn") { Stop-vm -VM $vm -Confirm:$false } Remove-VM -DeletePermanently -VM $ComputerName -Confirm:$false } } Write-LogFunctionExit } #endregion Remove-LWVMWareVM #region Start-LWVMWareVM function Start-LWVMWareVM { param ( [Parameter(Mandatory = $true)] [string[]]$ComputerName, [int]$DelayBetweenComputers = 0 ) Write-LogFunctionEntry foreach ($name in $ComputerName) { if (Get-VM -Name $name) { $result = Start-VM $name -ErrorAction SilentlyContinue if ($result.PowerState -ne "PoweredOn") { Write-Error "Could not start machine '$name'" } } Start-Sleep -Seconds $DelayBetweenComputers } Write-LogFunctionExit } #endregion Start-LWVMWareVM #region Save-LWVMWareVM workflow Save-LWVMWareVM { param ( [Parameter(Mandatory)] [string[]]$ComputerName ) sequence { Write-LogFunctionEntry foreach -parallel -throttlelimit 50 ($Name in $ComputerName) { Suspend-VM -VM $Name -ErrorAction SilentlyContinue -Confirm:$false } Write-LogFunctionExit } } #endregion Save-LWVMWareVM #region Stop-LWVMWareVM function Stop-LWVMWareVM { param ( [Parameter(Mandatory)] [string[]]$ComputerName ) Write-LogFunctionEntry foreach ($name in $ComputerName) { if (Get-VM -Name $name) { $result = Shutdown-VMGuest -VM $name -ErrorAction SilentlyContinue -Confirm:$false if ($result.PowerState -ne "PoweredOff") { Write-Error "Could not stop machine '$name'" } } else { Write-Warning "The machine '$name' does not exist on the connected ESX Server" } } Write-LogFunctionExit } #endregion Stop-LWVMWareVM #region Wait-LWVMWareRestartVM function Wait-LWVMWareRestartVM { param ( [Parameter(Mandatory)] [string[]]$ComputerName, [double]$TimeoutInMinutes = 15 ) Write-LogFunctionEntry $prevErrorActionPreference = $Global:ErrorActionPreference $Global:ErrorActionPreference = 'SilentlyContinue' $preVerboseActionPreference = $Global:VerbosePreference $Global:VerbosePreference = 'SilentlyContinue' $start = Get-Date Write-Verbose "Starting monitoring the servers at '$start'" $machines = Get-LabMachine -ComputerName $ComputerName $cmd = { param ( [datetime]$Start ) $events = Get-EventLog -LogName System -InstanceId 2147489653 -After $Start -Before $Start.AddHours(1) $events } do { $azureVmsToWait = foreach ($machine in $machines) { $events = Invoke-LabCommand -ComputerName $machine -ActivityName WaitForRestartEvent -ScriptBlock $cmd -ArgumentList $start.Ticks -UseLocalCredential -PassThru if ($events) { Write-Verbose "VM '$machine' has been restarted" } else { $machine } Start-Sleep -Seconds 15 } } until ($azureVmsToWait.Count -eq 0 -or (Get-Date).AddMinutes(- $TimeoutInMinutes) -gt $start) $Global:ErrorActionPreference = $prevErrorActionPreference $Global:VerbosePreference = $preVerboseActionPreference if ((Get-Date).AddMinutes(- $TimeoutInMinutes) -gt $start) { Write-Error -Message "Timeout while waiting for computers to restart. Computers not restarted: $($azureVmsToWait.Name -join ', ')" } Write-LogFunctionExit } #endregion Wait-LWVMWareRestartVM #region Get-LWVMWareVMStatus function Get-LWVMWareVMStatus { param ( [Parameter(Mandatory)] [string[]]$ComputerName ) Write-LogFunctionEntry $result = @{ } foreach ($name in $ComputerName) { $vm = Get-VM -Name $name if ($vm) { if ($vm.PowerState -eq 'PoweredOn') { $result.Add($vm.Name, 'Started') } elseif ($vm.PowerState -eq 'PoweredOff') { $result.Add($vm.Name, 'Stopped') } else { $result.Add($vm.Name, 'Unknown') } } } $result Write-LogFunctionExit } #endregion Get-LWVMWareVMStatus #region Enable-LWVMWareVMRemoting function Enable-LWVMWareVMRemoting { param( [Parameter(Mandatory, Position = 0)] $ComputerName ) if ($ComputerName) { $machines = Get-LabMachine -All | Where-Object Name -in $ComputerName } else { $machines = Get-LabMachine -All } $script = { param ($DomainName, $UserName, $Password) $VerbosePreference = 'Continue' $RegPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' Set-ItemProperty -Path $RegPath -Name AutoAdminLogon -Value 1 -ErrorAction SilentlyContinue Set-ItemProperty -Path $RegPath -Name DefaultUserName -Value $UserName -ErrorAction SilentlyContinue Set-ItemProperty -Path $RegPath -Name DefaultPassword -Value $Password -ErrorAction SilentlyContinue Set-ItemProperty -Path $RegPath -Name DefaultDomainName -Value $DomainName -ErrorAction SilentlyContinue Enable-WSManCredSSP -Role Server -Force | Out-Null } foreach ($machine in $machines) { $cred = $machine.GetCredential((Get-Lab)) try { Invoke-LabCommand -ComputerName $machine -ActivityName SetLabVMRemoting -ScriptBlock $script ` -ArgumentList $machine.DomainName, $cred.UserName, $cred.GetNetworkCredential().Password -ErrorAction Stop -Verbose } catch { Connect-WSMan -ComputerName $machine -Credential $cred Set-Item -Path "WSMan:\$machine\Service\Auth\CredSSP" -Value $true Disconnect-WSMan -ComputerName $machine } } } #endregion Enable-LWVMWareVMRemoting |