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-NetworkAdapter | Get-VDPortgroup).name } },
                        @{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
       This function checks the VMware tools status on one or more virtual machines and returns the name of the virtual machine and VMware tools version 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.
    .EXAMPLE
       Get-VMTools -VirtualMachine Luis-VM01
       This example gets the VMware tools status for the virtual machine named "Luis-VM01".
    .EXAMPLE
       Get-VM | Get-VMTools
       This example gets all virtual machines and then checks the VMware tools status on each virtual machine.
    .INPUTS
       The function accepts an array of strings that specifies one or more virtual machine names.
    .OUTPUTS
       The function returns virtual machine name and VMware tools version installed.
    .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 = $true,
            ValueFromPipeline = $false)]
        [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-Host -ForegroundColor DarkYellow "VMware Tools out of date on VM $($VM)"
                    Write-Verbose "VMware Tools - out of date on VM $($VM)"
                    $vmTools | Select-Object Name, @{
                        N = "ToolsVersion"
                        E = { $_.ExtensionData.Guest.Toolsversion }
                    }
                }

                else {
                    Write-Host -ForegroundColor Green "VMTools - OK on VM $VM"
                    Write-Verbose "VMware Tools OK on VM $VM"
                    $vmTools | Select-Object Name, @{
                        N = "ToolsVersion"
                        E = { $_.ExtensionData.Guest.Toolsversion }
                    }
                }
            } catch {
                Write-Error "An error occurred while trying to retrieve VMTools version for: $($VM)"
            }
        }

        # 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)."
    }
}