250 lines
13 KiB
PowerShell
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 {
|
|
|
|
}
|
|
} |