VMwareAdmin-Extras.psm1

function Get-VMInfo {
    <#
.SYNOPSIS
Get-VMInfo
The Get-VMInfo function gathers Virtual Machine (VM) information such as Name, Hostname, Number of CPUs, Power State, Memory Size, IP Address, Creation Date, VLAN ID, Used Disk Space, Disk Size, Operating System, Folder Location and Cluster Name from multiple vCenters using PowerCLI module.
 
.DESCRIPTION
This function takes a string array of multiple hostnames or partial names. To use this function, you must install the PowerCLI module and provide credentials for the vCenters. This function can be used with multiple vCenters and multiple VMs. It also supports pipeline input.
 
.EXAMPLE
Get-VMInfo -VirtualMachines "server1", "server2" -VCenters "vc1" -Credential $cred
This command gets the information for VMs "server1" and "server2" from the vCenter "vc1" using the credential $cred.
 
.EXAMPLE
vm1, vm2, vm3, vm4 | Get-VMInfo -VCenters "vc1" -Credential $cred
This command gets the information for VMs vm1, vm2, vm3, and vm4 from the vCenter "vc1" using the credential $cred.
 
.EXAMPLE
Get-VMInfo -VirtualMachines "server1", "server2" -VCenters "vc1", "vc2" -Credential $cred
This command gets the information for VMs "server1" and "server2" from the vCenters "vc1" and "vc2" using the credential $cred.
 
.EXAMPLE
vm1, vm2, vm3, vm4 | Get-VMInfo -VCenters "vc1", "vc2" -Credential $cred
This command gets the information for VMs vm1, vm2, vm3, and vm4 from the vCenters "vc1" and "vc2" using the credential $cred
 
.PARAMETER VirtualMachines
The list of Virtual Machines to get information for. Accepts string arrays.
 
    Get-VMInfo -VirtualMachines "server1", "server2"
    vm1, vm2, vm3, vm4 | Get-VMInfo
 
.PARAMETER VCenters
The vCenter name or IP address to connect to. Accepts a string.
 
    Get-VMInfo vm1, vm2 -VCenter "vc1"
 
.INPUTS
String[]
 
.OUTPUTS
Custom Object with VM information.
Name
Hostname
vCenter
PowerState
NumCpu
MemoryGB
IPAddress
CreateDate
VlanId
UsedDiskSpaceGB
DiskSizeGB
OperatingSystem
FolderLocation
ClusterName
VMHost
Notes
 
.LINK
       This script is a custom function created by Luis Carrillo.
       Github: https://github.com/LuisCarrilloTech
#>


    [CmdletBinding()]
    Param (
        # Parameter help description
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            Position = 0)]
        [String[]]$VirtualMachines,

        # Parameter help description
        [Parameter(Mandatory = $true,
            ValueFromPipelineByPropertyName = $true)]
        [String[]]$VCenters
    )

    Begin {
        # Check if VMWare PowerCLI module is installed:
        $moduleName = "VMware.VimAutomation.Core"
        if (!(Get-Module -Name $moduleName)) {
            try {
                Import-Module -Name $moduleName -Force -ErrorAction Stop
            } catch {
                Write-Error "Error loading VMWare PowerCLI module"
            }
        }
    }

    Process {

        if ($global:DefaultVIServers.name -notcontains $VCenters) {

            [System.Management.Automation.PSCredential]$Credential = Get-Credential

            # Connect to vCenter server:
            foreach ($vcenter in $vCenters) {
                try {
                    Connect-VIServer -Server $vCenter -Credential $Credential -ErrorAction Stop
                } catch [VMware.Vim.VimException] {
                    Write-Error "Failed to connect to vCenter. Please verify your credentials and try again."
                    return
                } catch {
                    Write-Error "An error occurred. Please try again."
                    return
                }
                Write-Verbose "Connected to vCenter $($vCenter)"
            }
        }

        # Gathers VM information:
        try {
            Foreach ($vc in $vCenters) {
                try {
                    foreach ($VMs in $VirtualMachines) {
                        Get-VM -Server $vc -ErrorAction Stop |
                        Where-Object { $_.Name -match $VMs } |
                        Select-Object Name,
                        @{l = 'Hostname' ; e = { $_.ExtensionData.guest.hostname } },
                        @{l = 'vCenter'; e = { $_.UID -replace "(^.+@)", '' -replace "\:.+$" } },
                        PowerState,
                        NumCpu,
                        @{l = 'MemoryGB'; e = { '{0:N1}' -f $_.MemoryGB } },
                        @{l = 'IPAddress'; e = { $_.Guest.IPAddress } },
                        @{l = 'CreateDate'; e = { $_.CreateDate } },
                         @{l = 'VlanId'; e = { (Get-VM $_ | Get-VMGuest).ExtensionData.net.network } },
                        @{l = 'UsedDiskSpaceGB'; e = { '{0:N1}' -f $_.UsedSpaceGB } },
                        @{l = 'DiskSizeGB'; e = { ('{0:N0}' -f ($_).Guest.Disks.CapacityGB) } },
                        @{l = 'OperatingSystem'; e = { $_.Guest.OSFullName } },
                        @{l = 'FolderLocation'; e = { $_.Folder } },
                        @{l = 'ClusterName'; e = { (Get-Cluster -VM $_).Name } },
                        VMHost,
                        Notes
                    }

                } catch {
                    "Error retrieving information for VM $($VMs) on vCenter: $vc"
                }
            }
        } catch {
            "Error retrieving information from vCenter: $($vc)"
        }


    }
}
function Get-VMTools {
    <#
.SYNOPSIS
Get-VMTools Function
This PowerShell function retrieves information about VMware Tools for one or more virtual machines. It requires the VMware PowerCLI module to be installed.
 
.DESCRIPTION
This function gets the VMware tools status for one or more virtual machines. If VMware tools are not up to date or are not installed, this function will return the virtual machine name and the outdated tools version.
For this function to work properly, VMware PowerCLI module needs to be installed.
 
.PARAMETER VirtualMachine
Specifies the name(s) of the virtual machine(s) to retrieve VMware Tools information for. This parameter is mandatory.
 
.PARAMETER vCenters
Specifies the vCenter Server(s) to connect to. This parameter is optional. If not provided, the function will prompt for the vCenter Server FQDN and credentials.
 
.PARAMETER Disconnect
Specifies whether to disconnect from the vCenter Server(s) after retrieving the information. This switch is optional.
 
.EXAMPLE
Retrieve VMware Tools information for a single virtual machine Get-VMTools -VirtualMachine "VM1"
 
.EXAMPLE
Retrieve VMware Tools information for multiple virtual machines
 
Get-VMTools -VirtualMachine "TESTVM1", "TESTVM2", "TESTVM3"
VMware Tools - out of date on VM1
VMware Tools - out of date on VM2
 
VMName ToolsVersion ToolsStatus ToolsVersionStatus ToolsRunningStatus ToolsInstallType
------ ------------ ----------- ------------------ ------------------ ----------------
VM1 11297 toolsOld guestToolsSupportedOld guestToolsRunning guestToolsTypeMSI
VM2 11328 toolsOk guestToolsUnmanaged guestToolsRunning guestToolsTypeOpenVMTools
VM3 11297 toolsOld guestToolsSupportedOld guestToolsRunning guestToolsTypeMSI
 
.EXAMPLE
Retrieve VMware Tools information for multiple virtual machines using wildcard *
 
Get-VMTools -VirtualMachine *VM*
VMware Tools - out of date on *VM*
 
VMName ToolsVersion ToolsStatus ToolsVersionStatus ToolsRunningStatus ToolsInstallType
------ ------------ ----------- ------------------ ------------------ ----------------
VM1 11297 toolsOld guestToolsSupportedOld guestToolsRunning guestToolsTypeMSI
VM2 11328 toolsOk guestToolsUnmanaged guestToolsRunning guestToolsTypeOpenVMTools
VM3 11297 toolsOld guestToolsSupportedOld guestToolsRunning guestToolsTypeMSI
 
.EXAMPLE
Retrieve VMware Tools information for multiple virtual machines and specify vCenter Server(s)
Get-VMTools -VirtualMachine "VM1", "VM2" -vCenters "vcenter1.example.com", "vcenter2.example.com"
 
.EXAMPLE
Retrieve VMware Tools information and disconnect from vCenter Server(s)
Get-VMTools -VirtualMachine "VM1" -Disconnect
 
.OUTPUTS
The function returns a PowerShell object with the following properties for each virtual machine:
 
ToolsVersion: The version of VMware Tools installed on the virtual machine.
ToolsStatus: The status of VMware Tools on the virtual machine.
ToolsVersionStatus: The status of the VMware Tools version on the virtual machine.
ToolsRunningStatus: The running status of VMware Tools on the virtual machine.
ToolsInstallType: The installation type of VMware Tools on the virtual machine.
 
If VMware Tools is out of date, the function will display a warning message and highlight the virtual machine with outdated VMware Tools.
 
.NOTES
This function requires VMware PowerCLI module to be installed. The function also leverages PowerCLI’s Connect-VIServer cmdlet to connect to the vCenter server. Prompts the user to enter the vCenter server credentials.
 
.ROLE
This script checks the VMware tools status on one or more virtual machines.
 
.FUNCTIONALITY
This function checks the VMware tools status on one or more virtual machines.
 
.LINK
This script is a custom function created by Luis Carrillo.
Github: https://github.com/LuisCarrilloTech
#>


    [CmdletBinding()]
    param(
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            Position = 0,
            HelpMessage = 'Enter a VM or list of VMs')]
        [ValidateNotNullOrEmpty()]
        [String[]]$VirtualMachine,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $true,
            Position = 1
        )]
        [string]$vCenters,

        [switch]$Disconnect
    )

    BEGIN {
        # Check if VMWare PowerCLI module is installed:
        $moduleName = "VMware.VimAutomation.Core"
        if (!(Get-Module -Name $moduleName)) {
            Import-Module -Name $moduleName -Force
        } else {
            Write-Verbose "VMWare PowerCLI module already installed."
        }

        # Prompt user to input vCenter FQDN and connect to server:

        if (($global:DefaultVIServers).name -match $vCenters) {
            Write-Output "Connected to vCenter..."
        } else {
            [System.Management.Automation.PSCredential]$Credential = Get-Credential

            foreach ($vcenter in $vCenters) {
                # Connect to vCenter server:
                try {
                    Connect-VIServer -Server $vCenter -Credential $Credential -ErrorAction Stop
                } catch [VMware.Vim.VimException] {
                    Write-Error "Failed to connect to vCenter. Please verify your credentials and try again."
                    return
                } catch {
                    Write-Error "An error occurred. Please try again."
                    return
                }
                Write-Verbose "Connected to vCenter $($vCenter)"
            }
        }
    }

    PROCESS {
        foreach ($VM in $VirtualMachine) {
            try {
                $vmTools = Get-VM $VM -ErrorAction Stop
                if ($vmTools.ExtensionData.Guest.ToolsStatus -ne "ToolsOK") {
                    Write-Verbose -Message "VMware Tools - out of date on VM $($VM)"
                    Write-Host -ForegroundColor DarkYellow "VMware Tools - out of date on VM $($VM)"
                    $vmTools | ForEach-Object { [PSCustomObject] @{
                            VMName             = $_.Name
                            ToolsVersion       = $_.ExtensionData.Guest.Toolsversion
                            ToolsStatus        = $_.ExtensionData.Guest.ToolsStatus
                            ToolsVersionStatus = $_.ExtensionData.Guest.ToolsVersionStatus2
                            ToolsRunningStatus = $_.ExtensionData.Guest.ToolsRunningStatus
                            ToolsInstallType   = $_.ExtensionData.Guest.ToolsInstallType
                        }
                    }
                }

                else {
                    Write-Verbose -Message "VMTools - OK on VM $VM"
                    Write-Host -ForegroundColor Green "VMTools - OK on VM $VM"
                    $vmTools | ForEach-Object { [PSCustomObject] @{
                            VMName             = $_.Name
                            ToolsVersion       = $_.ExtensionData.Guest.Toolsversion
                            ToolsStatus        = $_.ExtensionData.Guest.ToolsStatus
                            ToolsVersionStatus = $_.ExtensionData.Guest.ToolsVersionStatus2
                            ToolsRunningStatus = $_.ExtensionData.Guest.ToolsRunningStatus
                            ToolsInstallType   = $_.ExtensionData.Guest.ToolsInstallType
                        }
                    }
                }
            } catch {
                Write-Error "An error occurred while trying to retrieve VMTools version for: $($VM). Please try again."
                Write-Output $($_.Exception.Message)
            }
        }

        # Disconnect from vCenter:
        if ($Disconnect) {
            $global:DefaultVIServers | Disconnect-VIServer -Force -Confirm:$false
            Write-Verbose "Disconnected from vCenter $($vCenter)."
        } else {
            Write-Verbose "vCenter $($vCenter) still connected."
        }

    }
    END {
    }
}

Function Update-VMAdvancedSetting {
<#
.SYNOPSIS
Enables Change Block Tracking (CBT) for the specified virtual machines in a vCenter environment.
 
.DESCRIPTION
This script enables Change Block Tracking (CBT) for the specified virtual machines in a vCenter environment. CBT tracks disk changes in VMs and is used by backup solutions to determine which disk blocks need to be backed up, improving backup speed and efficiency.
 
.EXAMPLE
Enable-CBT -VirtualMachines "vm1, vm2" -vCenter "vcenter.domain.com" -AdvancedSetting "changeTrackingEnabled" -Value $TRUE
 
This example sets the advanced setting "changeTrackingEnabled" to $TRUE on VMs "vm1" and "vm2" on vCenter server "vcenter.domain.com".
 
.EXAMPLE
Enable-CBT -VirtualMachines vm1, vm2, vm3 -vCenter "myvcenter.domain.com" -AdvancedSetting "changeTrackingEnabled" -Value $TRUE
 
This example enables CBT for VMs "vm1", "vm2", and "vm3" on vCenter server "myvcenter.domain.com".
 
.EXAMPLE
Enable-CBT -VirtualMachines vm1, vm2, vm3 -vCenter "myvcenter.domain.com" -AdvancedSetting "changeTrackingEnabled" -Value $TRUE -Disconnect
 
This example enables CBT for VMs "vm1", "vm2", and "vm3" on vCenter server "myvcenter.domain.com" and Disconnects from vCenter(s) by using the -Disconnect switch parameter.
 
.INPUTS
VirtualMachines:
The virtual machines to enable CBT for. This parameter accepts an array of virtual machine names.
 
vCenter:
The vCenter server to connect to.
 
AdvancedSetting:
The advanced setting to configure for the specified virtual machine. Example: "changeTrackingEnabled".
 
Value:
The value to set for the advanced setting as either True or False.
 
.OUTPUTS
None, it enables CBT for the specified virtual machines.
 
.LINK
Author: Luis Carrillo
Github: https://github.com/LuisCarrilloTech
 
#>



    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true)]
        [string[]]$VirtualMachines,

        [Parameter(Mandatory = $true,
            ValueFromPipeline = $false)]
        [string]$vCenters,

        [Parameter(Mandatory = $true,
            ValueFromPipeline = $false)]
        [string]$AdvancedSetting,

        [Parameter(Mandatory = $true,
            ValueFromPipeline = $false)]
        $Value,
        [switch]$Disconnect
    )

    # Check if VMWare PowerCLI module is installed:
    $moduleName = "VMware.VimAutomation.Core"
    if (!(Get-Module -Name $moduleName)) {
        Import-Module -Name $moduleName -Force
    } else {
        Write-Output "Loading module. Please wait..."
    }

    # Prompt user to input vCenter FQDN and connect to server:
    if (!($global:DefaultVIServers)) {

        [System.Management.Automation.PSCredential]$Credential = Get-Credential

        foreach ($vcenter in $vCenters) {
            # Connect to vCenter server:
            try {
                Connect-VIServer -Server $vCenter -Credential $Credential -ErrorAction Stop
                Write-Host "Connected to vCenter $($vCenter)"
            } catch [VMware.Vim.VimException] {
                Write-Error "Failed to connect to vCenter. Please verify your credentials and try again."
                break
            } catch {
                Write-Error "An error occurred. Please try again."
                break
            }
        }
    }

    # Enable CBT on each VM:
    foreach ($vm in $VirtualMachines) {
        try {
            # Check if VM exists and get view object:
            $vmview = Get-VM $vm -ErrorAction Stop | Get-View
            $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
        } catch {
            Write-Error "Failed to find VM $($vm). Please verify the VM name and try again."
            continue
        }

        # Create snapshot before enabling CBT and set setting:
        try {
            New-Snapshot $vm -Name "Prior to enabling setting $($AdvancedSetting)" -ea Stop
        } catch {
            Write-Error "Failed to create snapshot for $($vm). Please verify try again."
            continue
        }

        # Enable CBT:
        $vmConfigSpec.($AdvancedSetting) = $Value
        $vmview.reconfigVM($vmConfigSpec)

        # Wait for task to complete:
        Start-Sleep 15

        # Verify settings has been configured, if so, delete pre-setting snapshot:
        if ((Get-VM $vm | Get-View).config.$AdvancedSetting -eq $value) {
            Write-Host "Setting $($AdvancedSetting) set to $($Value) on VM $($vm)."
            # Remove snapshot:
            try {
                Get-Snapshot -VM $vm -Name "Prior to enabling setting $($AdvancedSetting)" | Remove-Snapshot -Confirm:$false -ErrorAction Stop
                Write-Host "Snapshot removed."
            } catch {
                Write-Error "Failed to remove snapshot. Please check if the snapshot exists and try again."
                continue
            }
        }

    }

    # Disconnect from vCenter:
    if ($Disconnect) {
        $global:DefaultVIServers | Disconnect-VIServer -Force -Confirm:$false
        Write-Host "Disconnected from vCenter $($vCenter)."
    } else {
        Write-Error "Failed to disconnect from vCenter $($vCenter)."
    }
}