Files
Backup/_NDGOV_WindowsTeam/ITD.Infra-VMware.VirtualMachine/Public/Set-ITDVMwareVMViaSnowTask.ps1
T
Zack Meier 1d304511b8 update
2026-04-15 15:45:50 -05:00

250 lines
13 KiB
PowerShell

<#
.SYNOPSIS
Function to process a VMware change request
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function Set-ITDVMwareVMViaSnowTask {
[CmdletBinding()]
param (
[string]
$SCTaskNum,
[switch]
$Override,
[switch]
$CloseTask
)
begin {
$FreePercentThreshold = 0.20 # 20% free space required before disk expansions are automated
}
process {
# get current user, SCTask, Ritm
$assignTo = Get-ITDServiceNowUser -Username $Env:USERNAME
$SCTask = Get-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum
$Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -SysId ($SCTask.request_item.value) -IncludeVariableSet
$RitmNum = $Ritm.number.value
# Get Hostname and CMDB object
[string]$SCTaskDescriptionHostname = $SCTask.description.display_value.split(' ')[-1]
$TaskCmdb = @()
Write-Verbose -Message ("Gathering VariableSet data from $RitmNum")
$MatchFound = $false
ForEach ($Row in $Ritm.VariableSet) {
$TempCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId ($Row.host_name_ref) -ErrorAction Stop
If ($SCTaskDescriptionHostname -eq $TempCi.name.display_value) {
$Ci = $TempCi
$MatchFound = $true
}
}
If ($MatchFound -eq $false) {
Write-Error -Message "ComputerName $ComputerName was not found in VariableSet for $RitmNum" -ErrorAction Stop
}
$FQDN = $Ci.fqdn.display_value
If ( @($Ci).count -gt 1 ) {
Write-Error -Message "More than one CMDB object found that matches the hostname in this task's description" -ErrorAction Stop
}
# update SCTask description and assignment for humans
Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{assigned_to = $assignTo.name }
# search for VMware VM
try {
$VM = Get-VM -Name $Ci.fqdn.display_value | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
}
catch {
Write-Error "Error on VM lookup. Are you connected to vCenter?" -ErrorAction Stop
}
switch ( @($VM).count ) {
{ 0 -or $null } {
# no matches
Write-Error -Message "Zero VM matches found, ending script" -ErrorAction Stop
}
{ $_ -ne 1 } {
# more than one match
Write-Error -Message "Multiple VM matches found, ending script" -ErrorAction Stop
}
{ 1 } {
# exactly one match, gather request information, and populate variables
Write-Verbose -Message ("VM: " + $VM.Name)
[int]$CPU = ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } ).Processors
[int]$MemoryGB = ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } ).memory_gb
[int]$Disk1 = ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } ).disk_1_os
[int]$Disk2 = ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } ).disk_2_swap_disk
3..16 | ForEach-Object {
$DiskNum = $_
Write-Verbose "Populating variable Disk$DiskNum"
###Set-Variable -Name "Disk$DiskNum" -Value ([int](($Ritm.CustomVariable | Where-Object Name -Like "disk_$DiskNum*").Value))
Set-Variable -Name "Disk$DiskNum" -Value ([int]( ($Ritm.VariableSet | Where-Object { $_.host_name_ref -EQ $Ci.sys_id.value } )."disk_$DiskNum"))
}
# CPU modification
If ($CPU -ne 0 -and $CPU -ne $VM.NumCpu) {
Write-Verbose -Message ($VM.Name + " attempt changing CPU from " + $VM.NumCPU + " to " + $CPU)
try {
$OldCpu = $VM.NumCpu
$VM | Set-VM -NumCpu $CPU -Confirm:$false -ErrorAction Stop
$CommentsForWorkNotes += "CPU was updated from $OldCpu to $CPU. `n"
}
catch {
}
}
# MemoryGB modification
If ($MemoryGB -ne 0 -and $MemoryGB -ne $VM.MemoryGB) {
Write-Verbose -Message ($VM.Name + " attempt changing MemoryGB to " + $MemoryGB)
try {
$OldMemoryGB = $VM.MemoryGB
$VM | Set-VM -MemoryGB $MemoryGB -Confirm:$false -ErrorAction Stop
$CommentsForWorkNotes += "MemoryGB was updated from $OldMemoryGB to $MemoryGB. `n"
}
catch {
}
}
# Disk modification loop
$VMDisks = $VM | Get-HardDisk
1..16 | ForEach-Object {
Write-Verbose "Start Loop for Disk $_"
$HardDisk = $null
$DiskGBNewValue = $null
$DiskVarName = $null
$DiskNum = $_
$DiskGBNewValue = (Get-Variable -Name Disk$DiskNum).Value
switch ($DiskNum){
1 {
$DiskVarName = "Disk1"
}
2 {
$DiskVarName = "Disk2"
}
Default {
$DiskVarName = ("Disk" + $DiskNum)
}
}
If ( (Get-Variable -Name $DiskVarName).Value -ne 0 ) {
Write-Verbose -Message ("DiskNum: $DiskNum, DiskGBNewValue: $DiskGBNewValue")
$HardDisk = $VM | Get-HardDisk -Name "Hard disk $DiskNum" -ErrorAction SilentlyContinue
If ($HardDisk) {
$Datastore = $HardDisk | Get-Datastore
$DiskGBOldValue = $HardDisk.CapacityGB
$HardDiskIncreaseGB = $DiskGBNewValue - $DiskGBOldValue
If ($HardDiskIncreaseGB -ge 500) {
# manual intervention
}
$FreePercentBefore = ($Datastore.FreeSpaceGB) / $Datastore.CapacityGB
$FreePercentAfter = ($Datastore.FreeSpaceGB - $HardDiskIncreaseGB) / $Datastore.CapacityGB
Write-Verbose -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore, 4) + " to " + [math]::round($FreePercentAfter, 4) + "") -Verbose
Write-Verbose -Message ("Override is " + $Override)
If ( ($FreePercentAfter -gt $FreePercentThreshold) -or ($Override -eq $true)) {
try {
Write-Verbose -Message ("Hard disk $DiskNum : Increasing from " + $HardDisk.CapacityGB + "GB to " + $DiskGBNewValue + "GB") -Verbose
$VM | Get-HardDisk -Name "Hard disk $DiskNum" | Set-HardDisk -CapacityGB $DiskGBNewValue -Confirm:$false
$CommentsForWorkNotes += "Hard disk $DiskNum CapacityGB was modified from $DiskGBOldValue GB to $DiskGBNewValue GB. `n"
$DiskChanged = $true
}
catch {
Write-Error -Message "Disk $DiskNum expansion failed" -ErrorAction Stop
}
}
Else {
try {
Write-Error -Message ("Hard disk $DiskNum failed. " + $FreePercentThreshold * 100 + "% free space is required for automated disk expansions. " + $Datastore.Name + " would be " + [math]::round($FreePercentAfter, 4) + ".") -ErrorAction Stop
}
catch {
Write-Error -Message ("Hard disk $DiskNum failed. " + $FreePercentThreshold * 100 + "% free space is required for automated disk expansions. " + $Datastore.Name + " would be " + [math]::round($FreePercentAfter, 4) + ".") -ErrorAction Stop
}
}
}
Else {
Write-Verbose "Hard disk $DiskNum was not found. New disk will attempt to be created." -Verbose
# get licensing and storage format of existing disks
$VMTag = Get-TagAssignment -Entity $VM -Category LicensingRestrictions
If (@($VMDisks | Where-Object StorageFormat -Like "*Thick*").count -gt 0) {
$StorageFormat = 'EagerZeroedThick'
}
Else {
$StorageFormat = 'Thin'
}
# if not SQL, validate available space and create if possible. if VM is SQL, stop
If ($VMTag.Tag.Name -notlike "*SQL*") {
# place new disk with disk 1 and validate datastore free space
$Datastore = $VM | Get-HardDisk -Name "Hard disk 1" | Get-Datastore
$DiskGBOldValue = 0
$HardDiskIncreaseGB = $DiskGBNewValue - $DiskGBOldValue
If ($HardDiskIncreaseGB -ge 500) {
# manual intervention ?
}
$FreePercentBefore = ($Datastore.FreeSpaceGB) / $Datastore.CapacityGB
$FreePercentAfter = ($Datastore.FreeSpaceGB - $HardDiskIncreaseGB) / $Datastore.CapacityGB
#create the disk, with decided storageformat and persistent persistence on hard disk 1 datastore
If ($FreePercentAfter -gt $FreePercentThreshold) {
try {
Write-Warning -Message ("Hard disk $DiskNum : Creating new disk " + $DiskGBNewValue + " GB")
#Write-Warning -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore,4)*100 + "% to " + [math]::round($FreePercentAfter,4)*100 + "%")
Write-Warning -Message ("Datastore " + $Datastore.Name + " free space will lower from " + [math]::round($FreePercentBefore, 4) + " to " + [math]::round($FreePercentAfter, 4) + "")
$VM | New-HardDisk -CapacityGB $DiskGBNewValue -StorageFormat $StorageFormat
$CommentsForWorkNotes += "Hard disk $DiskNum was created with $DiskGBNewValue GB. "
$DiskChanged = $true
}
catch {
}
}
Else {
Write-Error -Message ("Hard disk $_ failed. " + $FreePercentThreshold * 100 + "% free space is required for automated disk expansions. " + $Datastore.Name + " would be " + [math]::round($FreePercentAfter, 4) + ".")
$DiskChanged = $false
$DiskError = $true
}
}
Else {
# require human review
Write-Error -Message ($HostName + " has SQL licensing, create the new disk manually due to SQL Server best practices. Once complete, rerun to validate size and close task.") -ErrorAction Stop
}
}
}
}
# update sctask and ritm, reassign if disk changed
$CommentsToAdd = "VMware VM " + $VM.Name + " was modified: `n" + $CommentsForWorkNotes
Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{comments = $CommentsToAdd }
Update-ITDServiceNowRecord -ItemType 'Request Item' -Number $Ritm.number.value -Values @{comments = $CommentsToAdd }
If ($CloseTask) {
Update-ITDServiceNowRecord -ItemType 'Catalog Task' -Number $SCTaskNum -Values @{close_notes = $CommentsToAdd; state = "Closed Complete" }
}
}
}
}
end {
}
}