From f40ca375a17c4e3c7f697e46f2dac286f6f2f1a7 Mon Sep 17 00:00:00 2001 From: Roman Gelman Date: Mon, 1 Aug 2016 10:00:54 +0300 Subject: [PATCH] Vi-Module module The Vi-Module module PSM1 file --- Modules/Vi-Module/Vi-Module.psm1 | 1222 ++++++++++++++++++++++++++++++ 1 file changed, 1222 insertions(+) create mode 100644 Modules/Vi-Module/Vi-Module.psm1 diff --git a/Modules/Vi-Module/Vi-Module.psm1 b/Modules/Vi-Module/Vi-Module.psm1 new file mode 100644 index 0000000..b7739a6 --- /dev/null +++ b/Modules/Vi-Module/Vi-Module.psm1 @@ -0,0 +1,1222 @@ +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 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]. +.LINK + http://goo.gl/3wO4pi +#> + +[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 = '^\[(?.+)\]\s(?.+)$' + $regxLUNID = ':L(?\d+)$' +} + +Process { + + Foreach ($vm in ($VMs |Get-View)) { + Foreach ($dev in $vm.Config.Hardware.Device) { + If (($dev.GetType()).Name -eq "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 convert all Thin Provisioned VM's disks to type 'Thick Provision Eager Zeroed'. +.PARAMETER VM + VM's collection, returned by Get-VM cmdlet. +.EXAMPLE + C:\PS> Get-VM VM1 |Convert-VmdkThin2EZThick +.EXAMPLE + C:\PS> Get-VM VM1,VM2 |Convert-VmdkThin2EZThick -Confirm:$false |sort VM,Datastore,VMDK |ft -au +.INPUTS + Get-VM collection. + [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]] +.OUTPUTS + PSObject collection. +.NOTES + Author: Roman Gelman. +.LINK + http://goo.gl/cVpTpO +#> + +[CmdletBinding(ConfirmImpact='High',SupportsShouldProcess=$true)] + +Param ( + + [Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true,HelpMessage="VM's collection, returned by Get-VM cmdlet")] + [ValidateNotNullorEmpty()] + [Alias("VM")] + [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]]$VMs + +) + +Begin { + + $Object = @() + $regxVMDK = '^\[(?.+)\]\s(?.+)$' + +} + +Process { + + Foreach ($vm in ($VMs |Get-View)) { + + ### Ask confirmation to proceed if VM is PoweredOff ### + If ($vm.Runtime.PowerState -eq 'poweredOff' -and $PSCmdlet.ShouldProcess("VM [$($vm.Name)]","Convert all Thin Provisioned VMDK to Type: 'Thick Provision Eager Zeroed'")) { + + ### Get ESXi object where $vm is registered ### + $esx = Get-View $vm.Runtime.Host + + ### Get Datacenter object where $vm is registered ### + $parentObj = Get-View $vm.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 $vm.Config.Hardware.Device) { + If (($dev.GetType()).Name -eq "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 - $($vm.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 = $vm.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 + } + } + } + $vm.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 { + +#requires -version 3.0 + +<# +.SYNOPSIS + Search VC's VM throw direct connection to group of ESXi Hosts. +.DESCRIPTION + This script generate list of ESXi Hosts with common suffix in name, + e.g. (esxprod1,esxprod2, ...) or (esxdev01,esxdev02, ...) etc. and + search 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 + C:\PS> .\Find-VC.ps1 vc1 esxprod 1 20 -AddZero +.EXAMPLE + C:\PS> .\Find-VC.ps1 -VC vc1 -HostSuffix esxdev -PostfixEnd 6 +.EXAMPLE + C:\PS> .\Find-VC.ps1 vc1 esxprod |fl +.NOTES + Author: Roman Gelman. +.OUTPUTS + PSCustomObject with two Properties: VC,VMHost or $null. +.LINK + http://rgel75.wix.com/blog +#> + +Param ( + + [Parameter(Mandatory=$true,Position=1,HelpMessage="vCenter's VM Name")] + [Alias("vCenter","VcVm")] + [System.String]$VC + , + [Parameter(Mandatory=$true,Position=2,HelpMessage="ESXi Hosts' common suffix")] + [Alias("VMHostSuffix","ESXiSuffix")] + [System.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 { + + $VMHostName = '' + $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 Name,IsConnected |ft -AutoSize + If ($global:DefaultVIServers.Length -ne 0) { + $VMHostName = (Get-VM -ErrorAction SilentlyContinue |? {$_.Name -eq $VC} |select -ExpandProperty VMHost).Name + Disconnect-VIServer -Server '*' -Force -Confirm:$false + } + } +} + +End { + + If ($VMHostName) { + $Properties = [ordered]@{ + VC = $VC + VMHost = $VMHostName + } + $Object = New-Object PSObject -Property $Properties + return $Object + } + Else {return $null} +} + +} #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://goo.gl/0h97C6 +#> + +$VIS = $global:DefaultVIServers |sort -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. +.LINK + https://goo.gl/Yg7mYp +#> + +Try + { + If ($_.GetType().Name -eq 'VMHostImpl') {$BiosInfo = ($_ |Get-View).Hardware.BiosInfo} + ElseIf ($_.GetType().Name -eq 'HostSystem') {$BiosInfo = $_.Hardware.BiosInfo} + ElseIf ($_.GetType().Name -eq '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 + https://goo.gl/Yg7mYp +#> + +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")] + [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost[]]$DifferenceVMHosts +) + +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. +.LINK + https://goo.gl/Yg7mYp +#> + +Param ( + + [Parameter(Mandatory=$false,Position=0,ValueFromPipeline=$true)] + [ValidateNotNullorEmpty()] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ClusterImpl[]]$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. +.LINK + https://goo.gl/Yg7mYp +#> + +Param ( + + [Parameter(Mandatory=$false,Position=0,ValueFromPipeline=$true)] + [ValidateNotNullorEmpty()] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ClusterImpl[]]$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://goo.gl/Q4S6yc +#> + +[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-DistributedSwitch |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. +.LINK + http://goo.gl/Dd6Ilt +#> + +[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.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.Vim.VmwareDistributedVirtualSwitch') {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 '*'