Files
PowerCLI-Example-Scripts/Modules/Vi-Module/Vi-Module.psm1
Brian Wuchner 248a86f0a2 Fixing instances of sort with sort-object
Fixes #535 - module using sort instead of sort-object causing unexpected behavior on powershell core/Linux.
Instead of only addressing the issue at hand, I looked for other instances of sort being used instead of sort-object for other modules within this repo and corrected those as well.  I think I got most of them, but feel free to raise another issue if you find another.  If the sort was in an example/help statement, or was inside the logic/process of the function, I replaced sort with sort-object.  In the one case where the sort was only applied to the output I removed the statement -- this way the function user can add the sort in their script and not have to sort output twice.  I changed a couple  select/where with select-object/where-object along the way as well just as I saw them.

Signed-off-by: Brian Wuchner <brian.wuchner@gmail.com>
2022-02-03 20:11:02 -05:00

1242 lines
39 KiB
PowerShell

Function Get-RDM {
<#
.SYNOPSIS
Get all RDMs.
.DESCRIPTION
This function reports all VMs with their RDM disks.
.PARAMETER VM
VM's collection, returned by Get-VM cmdlet.
.EXAMPLE
C:\PS> Get-VM -Server VC1 |Get-RDM
.EXAMPLE
C:\PS> Get-VM |? {$_.Name -like 'linux*'} |Get-RDM |sort-object VM,Datastore,HDLabel |ft -au
.EXAMPLE
C:\PS> Get-Datacenter 'North' |Get-VM |Get-RDM |? {$_.HDSizeGB -gt 1} |Export-Csv -NoTypeInformation 'C:\reports\North_RDMs.csv'
.EXAMPLE
C:\PS> $res = Get-Cluster prod |Get-VM |Get-ViMRDM
C:\PS> $res |Export-Csv -NoTypeInformation 'C:\reports\ProdCluster_RDMs.csv'
Save the results in variable and than export them to a file.
.INPUTS
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]] Get-VM collection.
.OUTPUTS
[System.Management.Automation.PSCustomObject] PSObject collection.
.NOTES
Author: Roman Gelman.
Version 1.0 :: 16-Oct-2015 :: Release
Version 1.1 :: 03-Dec-2015 :: Bugfix :: Error message appear while VML mismatch,
when the VML identifier does not match for an RDM on two or more ESXi hosts.
VMware [KB2097287].
Version 1.2 :: 03-Aug-2016 :: Improvement :: GetType() method replaced by -is for type determine.
.LINK
http://www.ps1code.com/single-post/2015/10/16/How-to-get-RDM-Raw-Device-Mappings-disks-using-PowerCLi
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false,Position=1,ValueFromPipeline=$true,HelpMessage="VM's collection, returned by Get-VM cmdlet")]
[ValidateNotNullorEmpty()]
[Alias("VM")]
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]]$VMs = (Get-VM)
)
Begin {
$Object = @()
$regxVMDK = '^\[(?<Datastore>.+)\]\s(?<Filename>.+)$'
$regxLUNID = ':L(?<LUNID>\d+)$'
}
Process {
Foreach ($vm in ($VMs |Get-View)) {
Foreach ($dev in $vm.Config.Hardware.Device) {
If ($dev -is [VMware.Vim.VirtualDisk]) {
If ("physicalMode","virtualMode" -contains $dev.Backing.CompatibilityMode) {
Write-Progress -Activity "Gathering RDM ..." -CurrentOperation "Hard disk - [$($dev.DeviceInfo.Label)]" -Status "VM - $($vm.Name)"
$esx = Get-View $vm.Runtime.Host
$esxScsiLun = $esx.Config.StorageDevice.ScsiLun |? {$_.Uuid -eq $dev.Backing.LunUuid}
### Expand 'LUNID' from device runtime name (vmhba2:C0:T0:L12) ###
$lunCN = $esxScsiLun.CanonicalName
$Matches = $null
If ($lunCN) {
$null = (Get-ScsiLun -VmHost $esx.Name -CanonicalName $lunCN -ErrorAction SilentlyContinue).RuntimeName -match $regxLUNID
$lunID = $Matches.LUNID
} Else {$lunID = ''}
### Expand 'Datastore' and 'VMDK' from file path ###
$null = $dev.Backing.FileName -match $regxVMDK
$Properties = [ordered]@{
VM = $vm.Name
VMHost = $esx.Name
Datastore = $Matches.Datastore
VMDK = $Matches.Filename
HDLabel = $dev.DeviceInfo.Label
HDSizeGB = [math]::Round(($dev.CapacityInKB / 1MB), 3)
HDMode = $dev.Backing.CompatibilityMode
DeviceName = $dev.Backing.DeviceName
Vendor = $esxScsiLun.Vendor
CanonicalName = $lunCN
LUNID = $lunID
}
$Object = New-Object PSObject -Property $Properties
$Object
}
}
}
}
}
End {
Write-Progress -Completed $true -Status "Please wait"
}
} #EndFunction Get-RDM
New-Alias -Name Get-ViMRDM -Value Get-RDM -Force:$true
Function Convert-VmdkThin2EZThick {
<#
.SYNOPSIS
Inflate thin virtual disks.
.DESCRIPTION
This function converts all Thin Provisioned VM' disks to type 'Thick Provision Eager Zeroed'.
.PARAMETER VM
Virtual Machine(s).
.EXAMPLE
C:\PS> Get-VM VM1 |Convert-VmdkThin2EZThick
.EXAMPLE
C:\PS> Get-VM VM1,VM2 |Convert-VmdkThin2EZThick -Confirm:$false |sort-object VM,Datastore,VMDK |ft -au
.INPUTS
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]] Objects, returned by Get-VM cmdlet.
.OUTPUTS
[System.Management.Automation.PSCustomObject] PSObject collection.
.NOTES
Author: Roman Gelman.
Version 1.0 :: 05-Nov-2015 :: Release.
Version 1.1 :: 03-Aug-2016 :: Improvements ::
[1] GetType() method replaced by -is for type determine.
[2] Parameter 'VMs' renamed to 'VM', parameter alias renamed from 'VM' to 'VMs'.
.LINK
http://www.ps1code.com/single-post/2015/11/05/How-to-convert-Thin-Provision-VMDK-disks-to-Eager-Zeroed-Thick-using-PowerCLi
#>
[CmdletBinding(ConfirmImpact='High',SupportsShouldProcess=$true)]
Param (
[Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true,HelpMessage="VM's collection, returned by Get-VM cmdlet")]
[ValidateNotNullorEmpty()]
[Alias("VMs")]
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]]$VM
)
Begin {
$Object = @()
$regxVMDK = '^\[(?<Datastore>.+)\]\s(?<Filename>.+)$'
}
Process {
Foreach ($vmv in ($VM |Get-View)) {
### Ask confirmation to proceed if VM is PoweredOff ###
If ($vmv.Runtime.PowerState -eq 'poweredOff' -and $PSCmdlet.ShouldProcess("VM [$($vmv.Name)]","Convert all Thin Provisioned VMDK to Type: 'Thick Provision Eager Zeroed'")) {
### Get ESXi object where $vmv is registered ###
$esx = Get-View $vmv.Runtime.Host
### Get Datacenter object where $vmv is registered ###
$parentObj = Get-View $vmv.Parent
While ($parentObj -isnot [VMware.Vim.Datacenter]) {$parentObj = Get-View $parentObj.Parent}
$datacenter = New-Object VMware.Vim.ManagedObjectReference
$datacenter.Type = 'Datacenter'
$datacenter.Value = $parentObj.MoRef.Value
Foreach ($dev in $vmv.Config.Hardware.Device) {
If ($dev -is [VMware.Vim.VirtualDisk]) {
If ($dev.Backing.ThinProvisioned -and $dev.Backing.Parent -eq $null) {
$sizeGB = [math]::Round(($dev.CapacityInKB / 1MB), 1)
### Invoke 'Inflate virtual disk' task ###
$ViDM = Get-View -Id 'VirtualDiskManager-virtualDiskManager'
$taskMoRef = $ViDM.InflateVirtualDisk_Task($dev.Backing.FileName, $datacenter)
$task = Get-View $taskMoRef
### Show task progress ###
For ($i=1; $i -lt [int32]::MaxValue; $i++) {
If ("running","queued" -contains $task.Info.State) {
$task.UpdateViewData("Info")
If ($task.Info.Progress -ne $null) {
Write-Progress -Activity "Inflate virtual disk task is in progress ..." -Status "VM - $($vmv.Name)" `
-CurrentOperation "$($dev.DeviceInfo.Label) - $($dev.Backing.FileName) - $sizeGB GB" `
-PercentComplete $task.Info.Progress -ErrorAction SilentlyContinue
Start-Sleep -Seconds 3
}
}
Else {Break}
}
### Get task completion results ###
$tResult = $task.Info.State
$tStart = $task.Info.StartTime
$tEnd = $task.Info.CompleteTime
$tCompleteTime = [math]::Round((New-TimeSpan -Start $tStart -End $tEnd).TotalMinutes, 1)
### Expand 'Datastore' and 'VMDK' from file path ###
$null = $dev.Backing.FileName -match $regxVMDK
$Properties = [ordered]@{
VM = $vmv.Name
VMHost = $esx.Name
Datastore = $Matches.Datastore
VMDK = $Matches.Filename
HDLabel = $dev.DeviceInfo.Label
HDSizeGB = $sizeGB
Result = $tResult
StartTime = $tStart
CompleteTime = $tEnd
TimeMin = $tCompleteTime
}
$Object = New-Object PSObject -Property $Properties
$Object
}
}
}
$vmv.Reload()
}
}
}
End {
Write-Progress -Completed $true -Status "Please wait"
}
} #EndFunction Convert-VmdkThin2EZThick
New-Alias -Name Convert-ViMVmdkThin2EZThick -Value Convert-VmdkThin2EZThick -Force:$true
Function Find-VcVm {
<#
.SYNOPSIS
Search VC's VM throw direct connection to group of ESXi Hosts.
.DESCRIPTION
This script generates a list of ESXi Hosts with common suffix in a name,
e.g. (esxprod1,esxprod2, ...) or (esxdev01,esxdev02, ...) etc. and
searches VCenter's VM throw direct connection to this group of ESXi Hosts.
.PARAMETER VC
VC's VM Name.
.PARAMETER HostSuffix
ESXi Hosts' common suffix.
.PARAMETER PostfixStart
ESXi Hosts' postfix number start.
.PARAMETER PostfixEnd
ESXi Hosts' postfix number end.
.PARAMETER AddZero
Add ESXi Hosts' postfix leading zero to one-digit postfix (from 01 to 09).
.EXAMPLE
PS C:\> Find-VcVm vc1 esxprod 1 20 -AddZero
.EXAMPLE
PS C:\> Find-VcVm -VC vc1 -HostSuffix esxdev -PostfixEnd 6
.EXAMPLE
PS C:\> Find-VcVm vc1 esxprod |fl
.NOTES
Author :: Roman Gelman.
Limitation :: [1] The function uses common credentials for all ESXi hosts.
[2] The hosts' Lockdown mode should be disabled.
Version 1.0 :: 03-Sep-2015 :: Release.
Version 1.1 :: 03-Aug-2016 :: Improvement :: Returned object properties changed.
.OUTPUTS
[System.Management.Automation.PSCustomObject] PSObject collection.
.LINK
http://ps1code.com
#>
Param (
[Parameter(Mandatory=$true,Position=1,HelpMessage="vCenter's VM Name")]
[Alias("vCenter","VcVm")]
[string]$VC
,
[Parameter(Mandatory=$true,Position=2,HelpMessage="ESXi Hosts' common suffix")]
[Alias("VMHostSuffix","ESXiSuffix")]
[string]$HostSuffix
,
[Parameter(Mandatory=$false,Position=3,HelpMessage="ESXi Hosts' postfix number start")]
[ValidateRange(1,98)]
[Alias("PostfixFirst","Start")]
[int]$PostfixStart = 1
,
[Parameter(Mandatory=$false,Position=4,HelpMessage="ESXi Hosts' postfix number end")]
[ValidateRange(2,99)]
[Alias("PostfixLast","End")]
[int]$PostfixEnd = 9
,
[Parameter(Mandatory=$false,Position=5,HelpMessage="Add ESXi Hosts' postfix leading zero")]
[switch]$AddZero = $false
)
Begin {
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Scope Session -Confirm:$false |Out-Null
If ($PostfixEnd -le $PostfixStart) {Throw "PostfixEnd must be greater than PostfixStart"}
}
Process {
$cred = Get-Credential -UserName root -Message "Common VMHost Credentials"
If ($cred) {
$hosts = @()
For ($i=$PostfixStart; $i -le $PostfixEnd; $i++) {
If ($AddZero -and $i -match '^\d{1}$') {
$hosts += $HostSuffix + '0' + $i
} Else {
$hosts += $HostSuffix + $i
}
}
Connect-VIServer $hosts -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -Credential $cred `
|select @{N='VMHost';E={$_.Name}},IsConnected |ft -AutoSize
If ($global:DefaultVIServers.Length -ne 0) {
$TargetVM = Get-VM -ErrorAction SilentlyContinue |? {$_.Name -eq $VC}
$VCHostname = $TargetVM.Guest.HostName
$PowerState = $TargetVM.PowerState
$VMHostHostname = $TargetVM.VMHost.Name
Disconnect-VIServer -Server '*' -Force -Confirm:$false
}
}
}
End {
If ($TargetVM) {
$Properties = [ordered]@{
VC = $VC
Hostname = $VCHostname
PowerState = $PowerState
VMHost = $VMHostHostname
}
$Object = New-Object PSObject -Property $Properties
$Object
}
}
} #EndFunction Find-VcVm
New-Alias -Name Find-ViMVcVm -Value Find-VcVm -Force:$true
Function Set-PowerCLiTitle {
<#
.SYNOPSIS
Write connected VI servers info to PowerCLi window title bar.
.DESCRIPTION
This function write connected VI servers info to PowerCLi window/console title bar [Name :: Product (VCenter/ESXi) ProductVersion].
.EXAMPLE
C:\PS> Set-PowerCLiTitle
.NOTES
Author: Roman Gelman.
.LINK
http://www.ps1code.com/single-post/2015/11/17/ConnectVIServer-deep-dive-or-%C2%ABWhere-am-I-connected-%C2%BB
#>
$VIS = $global:DefaultVIServers |sort-object -Descending ProductLine,Name
If ($VIS) {
Foreach ($VIObj in $VIS) {
If ($VIObj.IsConnected) {
Switch -exact ($VIObj.ProductLine) {
vpx {$VIProduct = 'VCenter'; Break}
embeddedEsx {$VIProduct = 'ESXi'; Break}
Default {$VIProduct = $VIObj.ProductLine; Break}
}
$Header += "[$($VIObj.Name) :: $VIProduct$($VIObj.Version)] "
}
}
} Else {
$Header = ':: Not connected to Virtual Infra Services ::'
}
$Host.UI.RawUI.WindowTitle = $Header
} #EndFunction Set-PowerCLiTitle
New-Alias -Name Set-ViMPowerCLiTitle -Value Set-PowerCLiTitle -Force:$true
Filter Get-VMHostFirmwareVersion {
<#
.SYNOPSIS
Get ESXi host BIOS version.
.DESCRIPTION
This filter returns ESXi host BIOS/UEFI Version and Release Date as a single string.
.EXAMPLE
PS C:\> Get-VMHost 'esxprd1.*' |Get-VMHostFirmwareVersion
Get single ESXi host's Firmware version.
.EXAMPLE
PS C:\> Get-Cluster PROD |Get-VMHost |select Name,@{N='BIOS';E={$_ |Get-VMHostFirmwareVersion}}
Get ESXi Name and Firmware version for single cluster.
.EXAMPLE
PS C:\> Get-VMHost |sort Name |select Name,Version,Manufacturer,Model,@{N='BIOS';E={$_ |Get-VMHostFirmwareVersion}} |ft -au
Add calculated property, that will contain Firmware version for all registered ESXi hosts.
.EXAMPLE
PS C:\> Get-View -ViewType 'HostSystem' |select Name,@{N='BIOS';E={$_ |Get-VMHostFirmwareVersion}}
.EXAMPLE
PS C:\> 'esxprd1.domain.com','esxdev2' |Get-VMHostFirmwareVersion
.INPUTS
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost[]] Objects, returned by Get-VMHost cmdlet.
[VMware.Vim.HostSystem[]] Objects, returned by Get-View cmdlet.
[System.String[]] ESXi hostname or FQDN.
.OUTPUTS
[System.String[]] BIOS/UEFI version and release date.
.NOTES
Author: Roman Gelman.
Version 1.0 :: 09-Jan-2016 :: Release.
Version 1.1 :: 03-Aug-2016 :: Improvement :: GetType() method replaced by -is for type determine.
.LINK
http://www.ps1code.com/single-post/2016/1/9/How-to-know-ESXi-servers%E2%80%99-BIOSFirmware-version-using-PowerCLi
#>
Try
{
If ($_ -is [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]) {$BiosInfo = ($_ |Get-View).Hardware.BiosInfo}
ElseIf ($_ -is [VMware.Vim.HostSystem]) {$BiosInfo = $_.Hardware.BiosInfo}
ElseIf ($_ -is [string]) {$BiosInfo = (Get-View -ViewType HostSystem -Filter @{"Name" = $_}).Hardware.BiosInfo}
Else {Throw "Not supported data type as pipeline"}
$fVersion = $BiosInfo.BiosVersion -replace ('^-\[|\]-$', $null)
$fDate = [Regex]::Match($BiosInfo.ReleaseDate, '(\d{1,2}/){2}\d+').Value
If ($fVersion) {return "$fVersion [$fDate]"} Else {return $null}
}
Catch
{}
} #EndFilter Get-VMHostFirmwareVersion
New-Alias -Name Get-ViMVMHostFirmwareVersion -Value Get-VMHostFirmwareVersion -Force:$true
Function Compare-VMHostSoftwareVib {
<#
.SYNOPSIS
Compares the installed VIB packages between VMware ESXi Hosts.
.DESCRIPTION
This function compares the installed VIB packages between reference ESXi Host and
group of difference/target ESXi Hosts or single ESXi Host.
.PARAMETER ReferenceVMHost
Reference VMHost.
.PARAMETER DifferenceVMHosts
Target VMHosts to compare them with the reference VMHost.
.EXAMPLE
PS C:\> Compare-VMHostSoftwareVib -ReferenceVMHost (Get-VMHost 'esxprd1.*') -DifferenceVMHosts (Get-VMHost 'esxprd2.*')
Compare two ESXi hosts.
.EXAMPLE
PS C:\> Get-VMHost 'esxdev2.*','esxdev3.*' |Compare-VMHostSoftwareVib -ReferenceVMHost (Get-VMHost 'esxdev1.*')
Compare two target ESXi Hosts with the reference Host.
.EXAMPLE
PS C:\> Get-Cluster DEV |Get-VMHost |Compare-VMHostSoftwareVib -ReferenceVMHost (Get-VMHost 'esxdev1.*')
Compare all HA/DRS cluster members with the reference ESXi Host.
.EXAMPLE
PS C:\> Get-Cluster PRD |Get-VMHost |Compare-VMHostSoftwareVib -ReferenceVMHost (Get-VMHost 'esxhai1.*') |Export-Csv -NoTypeInformation -Path '.\VibCompare.csv'
Export the comparison report to the file.
.INPUTS
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost[]] Objects, returned by Get-VMHost cmdlet.
.OUTPUTS
[System.Management.Automation.PSCustomObject] PSObject collection.
.NOTES
Author :: Roman Gelman.
Dependencies :: ESXCLI V2 works on vCenter 5.0/ESXi 5.0 and later.
Version 1.0 :: 10-Jan-2016 :: Release.
Version 1.1 :: 01-May-2016 :: Improvement :: Added support for PowerCLi 6.3R1 and ESXCLI V2 interface.
.LINK
http://www.ps1code.com/single-post/2016/1/10/How-to-compare-installed-VIB-packages-between-two-or-more-ESXi-hosts
#>
Param (
[Parameter(Mandatory,Position=1,HelpMessage="Reference VMHost")]
[Alias("ReferenceESXi")]
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]$ReferenceVMHost
,
[Parameter(Mandatory,Position=2,ValueFromPipeline,HelpMessage="Difference VMHosts collection")]
[Alias("DifferenceESXi","DifferenceVMHosts")]
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost[]]$DifferenceVMHost
)
Begin {
$PcliVer = Get-PowerCLIVersion -ErrorAction SilentlyContinue
$PcliMM = ($PcliVer.Major.ToString() + $PcliVer.Minor.ToString()) -as [int]
}
Process {
Try
{
If ($PcliMM -ge 63) {
$esxcliRef = Get-EsxCli -V2 -VMHost $ReferenceVMHost -ErrorAction Stop
$refVibId = ($esxcliRef.software.vib.list.Invoke()).ID
}
Else {
$esxcliRef = Get-EsxCli -VMHost $ReferenceVMHost -ErrorAction Stop
$refVibId = ($esxcliRef.software.vib.list()).ID
}
}
Catch
{
"{0}" -f $Error.Exception.Message
}
Foreach ($esx in $DifferenceVMHosts) {
Try
{
If ($PcliMM -ge 63) {
$esxcliDif = Get-EsxCli -V2 -VMHost $esx -ErrorAction Stop
$difVibId = ($esxcliDif.software.vib.list.Invoke()).ID
}
Else {
$esxcliDif = Get-EsxCli -VMHost $esx -ErrorAction Stop
$difVibId = ($esxcliDif.software.vib.list()).ID
}
$diffObj = Compare-Object -ReferenceObject $refVibId -DifferenceObject $difVibId -IncludeEqual:$false
Foreach ($diff in $diffObj) {
If ($diff.SideIndicator -eq '=>') {$diffOwner = $esx} Else {$diffOwner = $ReferenceVMHost}
$Properties = [ordered]@{
VIB = $diff.InputObject
VMHost = $diffOwner
}
$Object = New-Object PSObject -Property $Properties
$Object
}
}
Catch
{
"{0}" -f $Error.Exception.Message
}
}
}
} #EndFunction Compare-VMHostSoftwareVib
New-Alias -Name Compare-ViMVMHostSoftwareVib -Value Compare-VMHostSoftwareVib -Force:$true
Filter Get-VMHostBirthday {
<#
.SYNOPSIS
Get ESXi host installation date (Birthday).
.DESCRIPTION
This filter returns ESXi host installation date.
.EXAMPLE
PS C:\> Get-VMHost 'esxprd1.*' |Get-VMHostBirthday
Get single ESXi host's Birthday.
.EXAMPLE
PS C:\> Get-Cluster DEV |Get-VMHost |select Name,Version,@{N='Birthday';E={$_ |Get-VMHostBirthday}} |sort Name
Get ESXi Name and Birthday for single cluster.
.EXAMPLE
PS C:\> 'esxprd1.domain.com','esxprd2' |select @{N='ESXi';E={$_}},@{N='Birthday';E={$_ |Get-VMHostBirthday}}
Pipe hostnames (strings) to the function.
.EXAMPLE
PS C:\> Get-VMHost |select Name,@{N='Birthday';E={($_ |Get-VMHostBirthday).ToString('yyyy-MM-dd HH:mm:ss')}} |sort Name |ft -au
Format output using ToString() method.
http://blogs.technet.com/b/heyscriptingguy/archive/2015/01/22/formatting-date-strings-with-powershell.aspx
.INPUTS
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost[]] Objects, returned by Get-VMHost cmdlet.
[System.String[]] ESXi hostname or FQDN.
.OUTPUTS
[System.DateTime[]] ESXi installation date/time.
.NOTES
Original idea: Magnus Andersson
Author: Roman Gelman
Requirements: vSphere 5.x or above
.LINK
http://vcdx56.com/2016/01/05/find-esxi-installation-date/
#>
Try
{
$EsxCli = Get-EsxCli -VMHost $_ -ErrorAction Stop
$Uuid = $EsxCli.system.uuid.get()
$bdHexa = [Regex]::Match($Uuid, '^(\w{8,})-').Groups[1].Value
$bdDeci = [Convert]::ToInt64($bdHexa, 16)
$bdDate = [TimeZone]::CurrentTimeZone.ToLocalTime(([DateTime]'1/1/1970').AddSeconds($bdDeci))
If ($bdDate) {return $bdDate} Else {return $null}
}
Catch
{ }
} #EndFilter Get-VMHostBirthday
New-Alias -Name Get-ViMVMHostBirthday -Value Get-VMHostBirthday -Force:$true
Function Enable-VMHostSSH {
<#
.SYNOPSIS
Enable SSH on all ESXi hosts in a cluster.
.DESCRIPTION
This function enables SSH on all ESXi hosts in a cluster.
It starts the SSH daemon and opens incoming TCP connections on port 22.
.EXAMPLE
PS C:\> Get-Cluster PROD |Enable-VMHostSSH
.EXAMPLE
PS C:\> Get-Cluster DEV,TEST |Enable-VMHostSSH |sort Cluster,VMHost |Format-Table -AutoSize
.INPUTS
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.ClusterImpl[]] Clusters collection, returtned by Get-Cluster cmdlet.
.OUTPUTS
[System.Management.Automation.PSCustomObject] PSObject collection.
.NOTES
Author :: Roman Gelman.
Version 1.0 :: 07-Feb-2016 :: Release.
Version 1.1 :: 02-Aug-2016 :: -Cluster parameter data type changed to the portable type.
.LINK
http://www.ps1code.com/single-post/2016/02/07/How-to-enabledisable-SSH-on-all-ESXi-hosts-in-a-cluster-using-PowerCLi
#>
Param (
[Parameter(Mandatory=$false,Position=0,ValueFromPipeline=$true)]
[ValidateNotNullorEmpty()]
[VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster[]]$Cluster = (Get-Cluster)
)
Process {
Foreach ($container in $Cluster) {
Foreach ($esx in Get-VMHost -Location $container) {
If ('Connected','Maintenance' -contains $esx.ConnectionState -and $esx.PowerState -eq 'PoweredOn') {
$sshSvc = Get-VMHostService -VMHost $esx |? {$_.Key -eq 'TSM-SSH'} |Start-VMHostService -Confirm:$false -ErrorAction Stop
If ($sshSvc.Running) {$sshStatus = 'Running'} Else {$sshStatus = 'NotRunning'}
$fwRule = Get-VMHostFirewallException -VMHost $esx -Name 'SSH Server' |Set-VMHostFirewallException -Enabled $true -ErrorAction Stop
$Properties = [ordered]@{
Cluster = $container.Name
VMHost = $esx.Name
State = $esx.ConnectionState
PowerState = $esx.PowerState
SSHDaemon = $sshStatus
SSHEnabled = $fwRule.Enabled
}
}
Else {
$Properties = [ordered]@{
Cluster = $container.Name
VMHost = $esx.Name
State = $esx.ConnectionState
PowerState = $esx.PowerState
SSHDaemon = 'Unknown'
SSHEnabled = 'Unknown'
}
}
$Object = New-Object PSObject -Property $Properties
$Object
}
}
}
} #EndFunction Enable-VMHostSSH
New-Alias -Name Enable-ViMVMHostSSH -Value Enable-VMHostSSH -Force:$true
Function Disable-VMHostSSH {
<#
.SYNOPSIS
Disable SSH on all ESXi hosts in a cluster.
.DESCRIPTION
This function disables SSH on all ESXi hosts in a cluster.
It stops the SSH daemon and (optionally) blocks incoming TCP connections on port 22.
.PARAMETER BlockFirewall
Try to disable "SSH Server" firewall exception rule.
It might fail if this rule categorized as "Required Services" (VMware KB2037544).
.EXAMPLE
PS C:\> Get-Cluster PROD |Disable-VMHostSSH -BlockFirewall
.EXAMPLE
PS C:\> Get-Cluster DEV,TEST |Disable-VMHostSSH |sort Cluster,VMHost |Format-Table -AutoSize
.INPUTS
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.ClusterImpl[]] Clusters collection, returtned by Get-Cluster cmdlet.
.OUTPUTS
[System.Management.Automation.PSCustomObject] PSObject collection.
.NOTES
Author :: Roman Gelman.
Version 1.0 :: 07-Feb-2016 :: Release.
Version 1.1 :: 02-Aug-2016 :: -Cluster parameter data type changed to the portable type.
.LINK
http://www.ps1code.com/single-post/2016/02/07/How-to-enabledisable-SSH-on-all-ESXi-hosts-in-a-cluster-using-PowerCLi
#>
Param (
[Parameter(Mandatory=$false,Position=0,ValueFromPipeline=$true)]
[ValidateNotNullorEmpty()]
[VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster[]]$Cluster = (Get-Cluster)
,
[Parameter(Mandatory=$false,Position=1)]
[Switch]$BlockFirewall
)
Process {
Foreach ($container in $Cluster) {
Foreach ($esx in Get-VMHost -Location $container) {
If ('Connected','Maintenance' -contains $esx.ConnectionState -and $esx.PowerState -eq 'PoweredOn') {
$sshSvc = Get-VMHostService -VMHost $esx |? {$_.Key -eq 'TSM-SSH'} |Stop-VMHostService -Confirm:$false -ErrorAction Stop
If ($sshSvc.Running) {$sshStatus = 'Running'} Else {$sshStatus = 'NotRunning'}
$fwRule = Get-VMHostFirewallException -VMHost $esx -Name 'SSH Server'
If ($BlockFirewall) {
Try {$fwRule = Set-VMHostFirewallException -Exception $fwRule -Enabled:$false -Confirm:$false -ErrorAction Stop}
Catch {}
}
$Properties = [ordered]@{
Cluster = $container.Name
VMHost = $esx.Name
State = $esx.ConnectionState
PowerState = $esx.PowerState
SSHDaemon = $sshStatus
SSHEnabled = $fwRule.Enabled
}
}
Else {
$Properties = [ordered]@{
Cluster = $container.Name
VMHost = $esx.Name
State = $esx.ConnectionState
PowerState = $esx.PowerState
SSHDaemon = 'Unknown'
SSHEnabled = 'Unknown'
}
}
$Object = New-Object PSObject -Property $Properties
$Object
}
}
}
} #EndFunction Disable-VMHostSSH
New-Alias -Name Disable-ViMVMHostSSH -Value Disable-VMHostSSH -Force:$true
Function Set-VMHostNtpServer {
<#
.SYNOPSIS
Set NTP server settings on a group of ESXi hosts.
.DESCRIPTION
This cmdlet sets NTP server settings on a group of ESXi hosts
and restarts the NTP daemon to apply these settings.
.PARAMETER VMHost
ESXi hosts.
.PARAMETER NewNtp
NTP servers (IP/Hostname).
.EXAMPLE
PS C:\> Set-VMHostNtpServer -NewNtp 'ntp1','ntp2'
Set two NTP servers to all hosts in inventory.
.EXAMPLE
PS C:\> Get-VMHost 'esx1.*','esx2.*' |Set-VMHostNtpServer -NewNtp 'ntp1','ntp2'
.EXAMPLE
PS C:\> Get-Cluster DEV,TEST |Get-VMHost |sort Parent,Name |Set-VMHostNtpServer -NewNtp 'ntp1','10.1.2.200' |ft -au
.EXAMPLE
PS C:\> Get-VMHost -Location Datacenter1 |sort Name |Set-VMHostNtpServer -NewNtp 'ntp1','ntp2' |epcsv -notype -Path '.\Ntp_report.csv'
Export the results to Excel.
.INPUTS
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost[]] VMHost collection returned by Get-VMHost cmdlet.
.OUTPUTS
[System.Management.Automation.PSCustomObject] PSObject collection.
.NOTES
Author :: Roman Gelman.
Version 1.0 :: 10-Mar-2016 :: Release.
.LINK
http://www.ps1code.com/single-post/2016/03/10/How-to-configure-NTP-servers-setting-on-ESXi-hosts-using-PowerCLi
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false,Position=1,ValueFromPipeline=$true)]
[ValidateNotNullorEmpty()]
[VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost[]]$VMHost = (Get-VMHost)
,
[Parameter(Mandatory,Position=2)]
[System.String[]]$NewNtp
)
Begin {
$ErrorActionPreference = 'Stop'
}
Process {
Foreach ($esx in $VMHost) {
If ('Connected','Maintenance' -contains $esx.ConnectionState -and $esx.PowerState -eq 'PoweredOn') {
### Get current Ntp ###
$Ntps = Get-VMHostNtpServer -VMHost $esx
### Remove previously configured Ntp ###
$removed = $false
Try
{
Remove-VMHostNtpServer -NtpServer $Ntps -VMHost $esx -Confirm:$false
$removed = $true
}
Catch { }
### Add new Ntp ###
$added = $null
Try
{
$added = Add-VMHostNtpServer -NtpServer $NewNtp -VMHost $esx -Confirm:$false
}
Catch { }
### Restart NTP Daemon ###
$restarted = $false
Try
{
If ($added) {Get-VMHostService -VMHost $esx |? {$_.Key -eq 'ntpd'} |Restart-VMHostService -Confirm:$false |Out-Null}
$restarted = $true
}
Catch {}
### Return results ###
$Properties = [ordered]@{
VMHost = $esx
OldNtp = $Ntps
IsOldRemoved = $removed
NewNtp = $added
IsDaemonRestarted = $restarted
}
$Object = New-Object PSObject -Property $Properties
$Object
}
Else {Write-Warning "VMHost '$($esx.Name)' is in unsupported state"}
}
}
} #EndFunction Set-VMHostNtpServer
New-Alias -Name Set-ViMVMHostNtpServer -Value Set-VMHostNtpServer -Force:$true
Function Get-Version {
<#
.SYNOPSIS
Get VMware Virtual Infrastructure objects' version info.
.DESCRIPTION
This cmdlet gets VMware Virtual Infrastructure objects' version info.
.PARAMETER VIObject
Vitual Infrastructure objects (VM, VMHosts, DVSwitches, Datastores).
.PARAMETER VCenter
Get versions for all connected VCenter servers/ESXi hosts and PowerCLi version on the localhost.
.PARAMETER LicenseKey
Get versions of license keys.
.EXAMPLE
PS C:\> Get-VMHost |Get-Version |? {$_.Version -ge 5.5 -and $_.Version.Revision -lt 2456374}
Get all ESXi v5.5 hosts that have Revision less than 2456374.
.EXAMPLE
PS C:\> Get-View -ViewType HostSystem |Get-Version |select ProductName,Version |sort Version |group Version |sort Count |select Count,@{N='Version';E={$_.Name}},@{N='VMHost';E={($_.Group |select -expand ProductName) -join ','}} |epcsv -notype 'C:\reports\ESXi_Version.csv'
Group all ESXi hosts by Version and export the list to CSV.
.EXAMPLE
PS C:\> Get-VM |Get-Version |? {$_.FullVersion -match 'v10' -and $_.Version -gt 9.1}
Get all VM with Virtual Hardware v10 and VMTools version above v9.1.0.
.EXAMPLE
PS C:\> Get-Version -VCenter |Format-Table -AutoSize
Get all connected VCenter servers/ESXi hosts versions and PowerCLi version.
.EXAMPLE
PS C:\> Get-VDSwitch |Get-Version |sort Version |? {$_.Version -lt 5.5}
Get all DVSwitches that have version below 5.5.
.EXAMPLE
PS C:\> Get-Datastore |Get-Version |? {$_.Version.Major -eq 3}
Get all VMFS3 datastores.
.EXAMPLE
PS C:\> Get-Version -LicenseKey
Get license keys version info.
.INPUTS
Output objects from the following cmdlets:
Get-VMHost, Get-VM, Get-DistributedSwitch, Get-Datastore and Get-View -ViewType HostSystem.
.OUTPUTS
[System.Management.Automation.PSCustomObject] PSObject collection.
.NOTES
Author :: Roman Gelman.
Version 1.0 :: 23-May-2016 :: Release.
Version 1.1 :: 03-Aug-2016 :: Bugfix ::
[1] VDSwitch data type changed from [VMware.Vim.VmwareDistributedVirtualSwitch] to [VMware.VimAutomation.Vds.Types.V1.VmwareVDSwitch].
[2] Function Get-VersionVDSwitch edited to support data type change.
.LINK
http://www.ps1code.com/single-post/2016/05/25/How-to-know-any-VMware-object%E2%80%99s-version-Use-GetVersion
#>
[CmdletBinding(DefaultParameterSetName='VIO')]
Param (
[Parameter(Mandatory,Position=1,ValueFromPipeline=$true,ParameterSetName='VIO')]
$VIObject
,
[Parameter(Mandatory,Position=1,ParameterSetName='VC')]
[switch]$VCenter
,
[Parameter(Mandatory,Position=1,ParameterSetName='LIC')]
[switch]$LicenseKey
)
Begin {
$ErrorActionPreference = 'SilentlyContinue'
Function Get-VersionVMHostImpl {
Param ([Parameter(Mandatory,Position=1)]$InputObject)
$ErrorActionPreference = 'Stop'
Try
{
If ('Connected','Maintenance' -contains $InputObject.ConnectionState -and $InputObject.PowerState -eq 'PoweredOn') {
$ProductInfo = $InputObject.ExtensionData.Config.Product
$ProductVersion = [version]($ProductInfo.Version + '.' + $ProductInfo.Build)
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $ProductInfo.Name
FullVersion = $ProductInfo.FullName
Version = $ProductVersion
}
}
Else {
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = 'VMware ESXi'
FullVersion = 'Unknown'
Version = [version]'0.0.0.0'
}
}
}
Catch
{
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = 'VMware ESXi'
FullVersion = 'Unknown'
Version = [version]'0.0.0.0'
}
}
Finally
{
$Object = New-Object PSObject -Property $Properties
$Object
}
} #EndFunction Get-VersionVMHostImpl
Function Get-VersionVMHostView {
Param ([Parameter(Mandatory,Position=1)]$InputObject)
$ErrorActionPreference = 'Stop'
Try
{
$ProductRuntime = $InputObject.Runtime
If ('connected','maintenance' -contains $ProductRuntime.ConnectionState -and $ProductRuntime.PowerState -eq 'poweredOn') {
$ProductInfo = $InputObject.Config.Product
$ProductVersion = [version]($ProductInfo.Version + '.' + $ProductInfo.Build)
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $ProductInfo.Name
FullVersion = $ProductInfo.FullName
Version = $ProductVersion
}
}
Else {
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = 'VMware ESXi'
FullVersion = 'Unknown'
Version = [version]'0.0.0.0'
}
}
}
Catch
{
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = 'VMware ESXi'
FullVersion = 'Unknown'
Version = [version]'0.0.0.0'
}
}
Finally
{
$Object = New-Object PSObject -Property $Properties
$Object
}
} #EndFunction Get-VersionVMHostView
Function Get-VersionVM {
Param ([Parameter(Mandatory,Position=1)]$InputObject)
$ErrorActionPreference = 'Stop'
Try
{
$ProductInfo = $InputObject.Guest
If ($InputObject.ExtensionData.Guest.ToolsStatus -ne 'toolsNotInstalled' -and $ProductInfo) {
$ProductVersion = [version]$ProductInfo.ToolsVersion
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $InputObject.ExtensionData.Config.GuestFullName #$ProductInfo.OSFullName
FullVersion = "VMware VM " + $InputObject.Version
Version = $ProductVersion
}
}
Else {
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $InputObject.ExtensionData.Config.GuestFullName
FullVersion = "VMware VM " + $InputObject.Version
Version = [version]'0.0.0'
}
}
}
Catch
{
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = 'Unknown'
FullVersion = 'VMware VM'
Version = [version]'0.0.0'
}
}
Finally
{
$Object = New-Object PSObject -Property $Properties
$Object
}
} #EndFunction Get-VersionVM
Function Get-VersionPowerCLi {
$ErrorActionPreference = 'Stop'
Try
{
$PCLi = Get-PowerCLIVersion
$PCLiVer = [string]$PCLi.Major + '.' + [string]$PCLi.Minor + '.' + [string]$PCLi.Revision + '.' + [string]$PCLi.Build
$Properties = [ordered]@{
ProductName = $env:COMPUTERNAME
ProductType = 'VMware vSphere PowerCLi'
FullVersion = $PCLi.UserFriendlyVersion
Version = [version]$PCLiVer
}
$Object = New-Object PSObject -Property $Properties
$Object
}
Catch {}
} #EndFunction Get-VersionPowerCLi
Function Get-VersionVCenter {
Param ([Parameter(Mandatory,Position=1)]$InputObject)
$ErrorActionPreference = 'Stop'
Try
{
If ($obj.IsConnected) {
$ProductInfo = $InputObject.ExtensionData.Content.About
$ProductVersion = [version]($ProductInfo.Version + '.' + $ProductInfo.Build)
Switch -regex ($ProductInfo.OsType) {
'^win' {$ProductFullName = $ProductInfo.Name + ' Windows' ;Break}
'^linux' {$ProductFullName = $ProductInfo.Name + ' Appliance' ;Break}
Default {$ProductFullName = $ProductInfo.Name ;Break}
}
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $ProductFullName
FullVersion = $ProductInfo.FullName
Version = $ProductVersion
}
}
Else {
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = 'VMware vCenter Server'
FullVersion = 'Unknown'
Version = [version]'0.0.0.0'
}
}
}
Catch
{
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = 'VMware vCenter Server'
FullVersion = 'Unknown'
Version = [version]'0.0.0.0'
}
}
Finally
{
$Object = New-Object PSObject -Property $Properties
$Object
}
} #EndFunction Get-VersionVCenter
Function Get-VersionVDSwitch {
Param ([Parameter(Mandatory,Position=1)]$InputObject)
$ErrorActionPreference = 'Stop'
$ProductTypeName = 'VMware DVSwitch'
Try
{
$ProductInfo = $InputObject.ExtensionData.Summary.ProductInfo
$ProductFullVersion = 'VMware Distributed Virtual Switch ' + $ProductInfo.Version + ' build-' + $ProductInfo.Build
$ProductVersion = [version]($ProductInfo.Version + '.' + $ProductInfo.Build)
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $ProductTypeName
FullVersion = $ProductFullVersion
Version = $ProductVersion
}
}
Catch
{
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $ProductTypeName
FullVersion = 'Unknown'
Version = [version]'0.0.0.0'
}
}
Finally
{
$Object = New-Object PSObject -Property $Properties
$Object
}
} #EndFunction Get-VersionVDSwitch
Function Get-VersionDatastore {
Param ([Parameter(Mandatory,Position=1)]$InputObject)
$ErrorActionPreference = 'Stop'
$ProductTypeName = 'VMware VMFS Datastore'
Try
{
$ProductVersionNumber = $InputObject.FileSystemVersion
$ProductFullVersion = 'VMware Datastore VMFS v' + $ProductVersionNumber
$ProductVersion = [version]$ProductVersionNumber
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $ProductTypeName
FullVersion = $ProductFullVersion
Version = $ProductVersion
}
}
Catch
{
$Properties = [ordered]@{
ProductName = $InputObject.Name
ProductType = $ProductTypeName
FullVersion = 'Unknown'
Version = [version]'0.0'
}
}
Finally
{
$Object = New-Object PSObject -Property $Properties
$Object
}
} #EndFunction Get-VersionDatastore
Function Get-VersionLicenseKey {
Param ([Parameter(Mandatory,Position=1)]$InputObject)
$ErrorActionPreference = 'Stop'
$ProductTypeName = 'License Key'
Try
{
$InputObjectProp = $InputObject |select -ExpandProperty Properties
Foreach ($prop in $InputObjectProp) {
If ($prop.Key -eq 'ProductName') {$ProductType = $prop.Value + ' ' + $ProductTypeName}
ElseIf ($prop.Key -eq 'ProductVersion') {$ProductVersion = [version]$prop.Value}
}
Switch -regex ($InputObject.CostUnit) {
'^cpu' {$LicCostUnit = 'CPU'; Break}
'^vm' {$LicCostUnit = 'VM'; Break}
'server' {$LicCostUnit = 'SRV'; Break}
Default {$LicCostUnit = $InputObject.CostUnit}
}
$ProductFullVersion = $InputObject.Name + ' [' + $InputObject.Used + '/' + $InputObject.Total + $LicCostUnit + ']'
$Properties = [ordered]@{
ProductName = $InputObject.LicenseKey
ProductType = $ProductType
FullVersion = $ProductFullVersion
Version = $ProductVersion
}
}
Catch
{
$Properties = [ordered]@{
ProductName = $InputObject.LicenseKey
ProductType = $ProductTypeName
FullVersion = 'Unknown'
Version = [version]'0.0'
}
}
Finally
{
$Object = New-Object PSObject -Property $Properties
If ($InputObject.EditionKey -ne 'eval') {$Object}
}
} #EndFunction Get-VersionLicenseKey
}
Process {
If ($PSCmdlet.ParameterSetName -eq 'VIO') {
Foreach ($obj in $VIObject) {
If ($obj -is [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost]) {Get-VersionVMHostImpl -InputObject $obj}
ElseIf ($obj -is [VMware.Vim.HostSystem]) {Get-VersionVMHostView -InputObject $obj}
ElseIf ($obj -is [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]) {Get-VersionVM -InputObject $obj}
ElseIf ($obj -is [VMware.VimAutomation.Vds.Types.V1.VmwareVDSwitch]) {Get-VersionVDSwitch -InputObject $obj}
ElseIf ($obj -is [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.VmfsDatastore]) {Get-VersionDatastore -InputObject $obj}
Else {Write-Warning "Not supported object type"}
}
}
ElseIf ($PSCmdlet.ParameterSetName -eq 'VC') {
If ($global:DefaultVIServers.Length) {Foreach ($obj in $global:DefaultVIServers) {Get-VersionVCenter -InputObject $obj}}
Else {Write-Warning "Please use 'Connect-VIServer' cmdlet to connect to VCenter servers or ESXi hosts."}
Get-VersionPowerCLi
}
ElseIf ($PSCmdlet.ParameterSetName -eq 'LIC') {
If ($global:DefaultVIServers.Length) {Foreach ($obj in ((Get-View (Get-View ServiceInstance).Content.LicenseManager).Licenses)) {Get-VersionLicenseKey -InputObject $obj}}
Else {Write-Warning "Please use 'Connect-VIServer' cmdlet to connect to VCenter servers or ESXi hosts."}
}
}
End {}
} #EndFunction Get-Version
New-Alias -Name Get-ViMVersion -Value Get-Version -Force:$true
Export-ModuleMember -Alias '*' -Function '*'