diff --git a/Modules/PSvLIMessage.psm1 b/Modules/PSvLIMessage.psm1 new file mode 100644 index 0000000..9cab209 --- /dev/null +++ b/Modules/PSvLIMessage.psm1 @@ -0,0 +1,123 @@ +add-type @" + using System.Net; + using System.Security.Cryptography.X509Certificates; + public class TrustAllCertsPolicy : ICertificatePolicy { + public bool CheckValidationResult( + ServicePoint srvPoint, X509Certificate certificate, + WebRequest request, int certificateProblem) { + return true; + } + } +"@ +[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy + +<# + .NOTES + =========================================================================== + Created by: Markus Kraus + Organization: Private + Personal Blog: mycloudrevolution.com + Twitter: @vMarkus_K + =========================================================================== + Tested Against Environment: + vRealize Log Insight 3.3.1 + PowerShell Version: 4.0, 5.0 + OS Version: Windows 8.1, Server 2012 R2 + Keyword: vRealize, RestAPI + + Dependencies: + PowerCLI Version: PowerCLI 6.3 R1 + + .SYNOPSIS + Push Messages to VMware vRealize Log Insight. + + .DESCRIPTION + Creates a Messages in VMware vRealize Log Insight via the Ingestion API + + .EXAMPLE + Push-vLIMessage -vLIServer "loginsight.lan.local" -vLIAgentID "12862842-5A6D-679C-0E38-0E2BE888BB28" -Text "My Test" + + .EXAMPLE + Push-vLIMessage -vLIServer "loginsight.lan.local" -vLIAgentID "12862842-5A6D-679C-0E38-0E2BE888BB28" -Text "My Test" -Hostname MyTEST -FieldName myTest -FieldContent myTest + + .PARAMETER vLIServer + Specify the FQDN of your vRealize Log Insight Appliance + + .PARAMETER vLIAgentID + Specify the vRealize Log Insight Agent ID, e.g. "12862842-5A6D-679C-0E38-0E2BE888BB28" + + .PARAMETER Text + Specify the Event Text + + .PARAMETER Hostname + Specify the Hostanme displayed in vRealize Log Insight + + .PARAMETER FieldName + Specify the a Optional Field Name for vRealize Log Insight + + .PARAMETER FieldContent + Specify the a Optional FieldContent for the Field in -FieldName for vRealize Log Insight + If FielName is missing and FieldContent is given, it will be ignored + + #Requires PS -Version 3.0 + + #> +function Push-vLIMessage { + + [cmdletbinding()] + param ( + [parameter(Mandatory=$true)] + [string]$Text, + [parameter(Mandatory=$true)] + [string]$vLIServer, + [parameter(Mandatory=$true)] + [string]$vLIAgentID, + [parameter(Mandatory=$false)] + [string]$Hostname = $env:computername, + [parameter(Mandatory=$false)] + [string]$FieldName, + [parameter(Mandatory=$false)] + [string]$FieldContent = "" + ) + Process { + $Field_vLI = [ordered]@{ + name = "PS_vLIMessage" + content = "true" + } + $Field_HostName = [ordered]@{ + name = "hostname" + content = $Hostname + } + + $Fields = @($Field_vLI, $Field_HostName) + + if ($FieldName) { + $Field_Custom = [ordered]@{ + name = $FieldName + content = $FieldContent + } + $Fields += @($Field_Custom) + } + + $Restcall = @{ + messages = ([Object[]]([ordered]@{ + text = ($Text) + fields = ([Object[]]$Fields) + })) + } | convertto-json -Depth 4 + + $Resturl = ("http://" + $vLIServer + ":9000/api/v1/messages/ingest/" + $vLIAgentID) + try + { + $Response = Invoke-RestMethod $Resturl -Method Post -Body $Restcall -ContentType 'application/json' -ErrorAction stop + Write-Information "REST Call to Log Insight server successful" + Write-Verbose $Response + } + catch + { + Write-Error "REST Call failed to Log Insight server" + Write-Verbose $error[0] + Write-Verbose $Resturl + } + } +} \ No newline at end of file diff --git a/Modules/Vi-Module/README.md b/Modules/Vi-Module/README.md new file mode 100644 index 0000000..f7a1f2f --- /dev/null +++ b/Modules/Vi-Module/README.md @@ -0,0 +1,34 @@ +## ![powerclilogo](https://cloud.githubusercontent.com/assets/6964549/17082247/44e1392e-517f-11e6-9cbe-9efa0277deaa.png) VMware infrastructure Module + +### [Vi-Module.psm1] (https://github.com/vmware/PowerCLI-Example-Scripts/tree/master/Modules/Vi-Module) + +To install this module, drop the entire 'Vi-Module' folder into one of your module directories. + +The default PowerShell module paths are listed in the `$env:PSModulePath` environment variable. + +To make it look better, split the paths in this manner `$env:PSModulePath -split ';'` + +The default per-user module path is: `"$env:HOMEDRIVE$env:HOMEPATH\Documents\WindowsPowerShell\Modules"`. + +The default computer-level module path is: `"$env:windir\System32\WindowsPowerShell\v1.0\Modules"`. + +To use the module, type following command: `Import-Module Vi-Module -Force -Verbose`. + +To see the commands imported, type `Get-Command -Module Vi-Module`. + +For help on each individual cmdlet or function, run `Get-Help CmdletName -Full [-Online][-Examples]`. + +#### Vi-Module Cmdlets: + +|No|Cmdlet|Description| +|----|----|----| +|1|[Get-RDM] (http://www.ps1code.com/single-post/2015/10/16/How-to-get-RDM-Raw-Device-Mappings-disks-using-PowerCLi)|Report all VM with their RDM disks| +|2|[Convert-VmdkThin2EZThick] (http://www.ps1code.com/single-post/2015/11/05/How-to-convert-Thin-Provision-VMDK-disks-to-Eager-Zeroed-Thick-using-PowerCLi)|Inflate thin virtual disks| +|3|[Find-VcVm] (https://cloud.githubusercontent.com/assets/6964549/17361776/d5dff80e-597a-11e6-85a2-a782db875f78.png)|Search VCenter VM throw direct connection to group of ESXi hosts. Thanks to VMGU.ru for the [article] (http://www.vmgu.ru/news/vmware-vcenter-how-to-find-powered-off)| +|4|[Set-PowerCLiTitle] (http://www.ps1code.com/single-post/2015/11/17/ConnectVIServer-deep-dive-or-%C2%ABWhere-am-I-connected-%C2%BB)|Write connected VI servers info to PowerCLi window title bar| +|5|[Get-VMHostFirmwareVersion] (http://www.ps1code.com/single-post/2016/1/9/How-to-know-ESXi-servers%E2%80%99-BIOSFirmware-version-using-PowerCLi)|Get a Firmware version and release date of your ESXi hosts| +|6|[Compare-VMHostSoftwareVib] (http://www.ps1code.com/single-post/2016/1/10/How-to-compare-installed-VIB-packages-between-two-or-more-ESXi-hosts)|Compare installed VIB packages between two or more ESXi hosts| +|7|[Get-VMHostBirthday] (https://cloud.githubusercontent.com/assets/6964549/12399803/c8439dfa-be24-11e5-8141-09199caa301e.png)|Get ESXi hosts' installation date. Thanks to Magnus Andersson for his [idea] (http://vcdx56.com/2016/01/05/find-esxi-installation-date/)| +|8|[Enable-VMHostSSH/Disable-VMHostSSH] (http://www.ps1code.com/single-post/2016/02/07/How-to-enabledisable-SSH-on-all-ESXi-hosts-in-a-cluster-using-PowerCLi)|Enable/Disable SSH on all ESXi hosts in a cluster| +|9|[Set-VMHostNtpServer] (http://www.ps1code.com/single-post/2016/03/10/How-to-configure-NTP-servers-setting-on-ESXi-hosts-using-PowerCLi)|Set `NTP Servers` setting on ESXi hosts| +|10|[Get-Version] (http://www.ps1code.com/single-post/2016/05/25/How-to-know-any-VMware-object%E2%80%99s-version-Use-GetVersion)|Get VMware Virtual Infrastructure objects' version info: `VM`, `ESXi Hosts`, `VDSwitches`, `Datastores`, `VCenters`, `PowerCLi`, `License Keys`| diff --git a/Modules/Vi-Module/Vi-Module.psd1 b/Modules/Vi-Module/Vi-Module.psd1 new file mode 100644 index 0000000..70a5df1 --- /dev/null +++ b/Modules/Vi-Module/Vi-Module.psd1 @@ -0,0 +1,120 @@ +# +# Module manifest for module 'Vi-Module' +# +# Generated by: Roman Gelman @rgelman75 +# +# Generated on: 8/1/2016 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'Vi-Module' + +# Version number of this module. +ModuleVersion = '1.0' + +# ID used to uniquely identify this module +GUID = 'a5ad4817-fbef-41b9-b5e2-714a7a16fb26' + +# Author of this module +Author = 'Roman Gelman @rgelman75' + +# Company or vendor of this module +CompanyName = 'Taldor Israel' + +# Copyright statement for this module +Copyright = '(c) 2016 Roman Gelman @rgelman75. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'VMware Virtual Infrastructure Management functions' + +# Minimum version of the Windows PowerShell engine required by this module +PowerShellVersion = '3.0' + +# Name of the Windows PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the Windows PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module +# CLRVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module +FunctionsToExport = '*' + +# Cmdlets to export from this module +CmdletsToExport = '*' + +# Variables to export from this module +VariablesToExport = '*' + +# Aliases to export from this module +AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/rgel/PowerCLi' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/Modules/Vi-Module/Vi-Module.psm1 b/Modules/Vi-Module/Vi-Module.psm1 new file mode 100644 index 0000000..cb1d252 --- /dev/null +++ b/Modules/Vi-Module/Vi-Module.psm1 @@ -0,0 +1,1241 @@ +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]. + 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 = '^\[(?.+)\]\s(?.+)$' + $regxLUNID = ':L(?\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 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 = '^\[(?.+)\]\s(?.+)$' + +} + +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 -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 '*' diff --git a/Pester/Get-DatastoreProvisioned.Tests.ps1 b/Pester/Get-DatastoreProvisioned.Tests.ps1 new file mode 100644 index 0000000..2e0dded --- /dev/null +++ b/Pester/Get-DatastoreProvisioned.Tests.ps1 @@ -0,0 +1,92 @@ +# To run: "Invoke-Pester \Get-DatastoreProvisioned.Tests.ps1" + +<# +Script name: Get-DatastoreProvisioned.Tests.ps1 +Created on: 2016/07/27 +Author: Brian Bunke, @brianbunke +Description: Help validate that any changes to Get-DatastoreProvisioned.ps1 do not break existing functionality +Dependencies: Pester + +===Tested Against Environment==== +vSphere Version: 6.0 U1/U2 +PowerCLI Version: PowerCLI 6.3 R1 +PowerShell Version: 5.0 +OS Version: Windows 7/10 +#> + +# Tests file stored separately from actual script +# Find where this file is running from, replace parent folder 'Pester' with 'Scripts' +$Path = (Split-Path -Parent $MyInvocation.MyCommand.Path).Replace("Pester","Scripts") +# Remove the '.Tests.' from the file name +$File = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".") +# With changes made to the path, dot-source the function for testing +. "$Path\$File" + +Describe 'Get-DatastoreProvisioned' { + # Need to create a few example objects to proxy Get-Datastore pipeline input + $1 = [PSCustomObject]@{ + Name = 'iSCSI-spin' + CapacityGB = 38.40 + FreeSpaceGB = 15.55 + ExtensionData = @{ + Summary = @{ + Capacity = 41234567890 + FreeSpace = 16696685366 + Uncommitted = 12345678999 + }}} + $2 = [PSCustomObject]@{ + Name = 'iSCSI-ssd' + CapacityGB = 51.74 + FreeSpaceGB = 10.35 + ExtensionData = @{ + Summary = @{ + Capacity = 55555555555 + FreeSpace = 11111111111 + Uncommitted = 23456765432 + }}} + $3 = [PSCustomObject]@{ + Name = 'FC-ssd' + CapacityGB = 10.35 + FreeSpaceGB = 4.14 + ExtensionData = @{ + Summary = @{ + Capacity = 11111111111 + FreeSpace = 4444444444 + Uncommitted = 2222222222 + }}} + + It "Doesn't change existing functionality" { + $StillWorks = $1,$2,$3 | Get-DatastoreProvisioned + $StillWorks | Should Not BeNullOrEmpty + ($StillWorks | Measure-Object).Count | Should Be 3 + ($StillWorks | Get-Member -MemberType NoteProperty).Count | Should Be 6 + 'Name','FreeSpaceGB','CapacityGB','ProvisionedGB','UsedPct','ProvisionedPct' | ForEach-Object { + ($StillWorks | Get-Member -MemberType NoteProperty).Name -contains $_ | Should Be $true + } + } + + It 'Still calculates correctly' { + $calc = $1 | Get-DatastoreProvisioned + $calc | Should Not BeNullOrEmpty + $calc.ProvisionedGB | Should Be 34.35 + $calc.UsedPct | Should Be 59.51 + $calc.ProvisionedPct | Should Be 89.45 + } + + # Get-Datastore | Get-DatastoreProvisioned | Format-Table -AutoSize + It 'Follows Help Example 1' { + $Help1 = $1,$2,$3 | Get-DatastoreProvisioned + $Help1 | Should Not BeNullOrEmpty + ($Help1 | Measure-Object).Count | Should Be 3 + # not testing Format-Table + } + + # Get-Datastore -Name '*ssd' | Get-DatastoreProvisioned | Where-Object ProvisionedPct -ge 100 + It 'Follows Help Example 2' { + $Help2 = $1,$2,$3 | Where Name -like '*ssd' | Get-DatastoreProvisioned | Where ProvisionedPct -ge 100 + $Help2 | Should Not BeNullOrEmpty + ($Help2 | Measure-Object).Count | Should Be 1 + $Help2.Name | Should BeExactly 'iSCSI-ssd' + $Help2.ProvisionedPct | Should BeGreaterThan 100 + } +} diff --git a/Pester/Test Connection to VC.ps1 b/Pester/Test Connection to VC.ps1 new file mode 100644 index 0000000..006825a --- /dev/null +++ b/Pester/Test Connection to VC.ps1 @@ -0,0 +1,44 @@ +<# +Script name: Test Connection to VC.ps1 +Created on: 07/15/2016 +Author: Alan Renouf, @alanrenouf +Description: The purpose of this pester test is to ensure the PowerCLI modules are imported and a connection and disconnection can be made to a vCenter +Dependencies: Pester Module +Example run: + +Invoke-Pester -Script @{ Path = '.\Test Connection to VC.ps1'; Parameters = @{ VCNAME="VC01.local"; VCUSER="Administrator@vsphere.local"; VCPASS="Admin!23"} } + +#> + +$VCUSER = $Parameters.Get_Item("VCUSER") +$VCPASS = $Parameters.Get_Item("VCPASS") +$VCNAME = $Parameters.Get_Item("VCNAME") + +Describe "PowerCLI Tests" { + It "Importing PowerCLI Modules" { + Get-Module VMware* | Foreach { + Write-Host "Importing Module $($_.name) Version $($_.Version)" + $_ | Import-Module + Get-Module $_ | Should Be $true + } + } +} + +Describe "Connect-VIServer Tests" { + + $connection = Connect-VIServer $VCName -User $VCUser -password $VCPass + It "Connection is active" { + $Global:DefaultVIServer[0].isconnected | Should Be $true + } + + It "Checking connected server name is $VCName" { + $Global:DefaultVIServer[0].name | Should Be $VCName + } +} + +Describe "Disconnect-VIServer Tests" { + It "Disconnect from $VCName" { + Disconnect-VIServer $VCName -confirm:$false + $Global:DefaultVIServer | Should Be $null + } +} \ No newline at end of file diff --git a/PowerActions/VM-CdDrive-Report.ps1 b/PowerActions/VM-CdDrive-Report.ps1 new file mode 100644 index 0000000..584484d --- /dev/null +++ b/PowerActions/VM-CdDrive-Report.ps1 @@ -0,0 +1,51 @@ +<# +.MYNGC_REPORT +KEY\(VM\) +.LABEL +VM CD-Drive Report +.DESCRIPTION +PowerActions Report Script that reports on VMs CD-Drive configuration, making it easy to find VMs holding onto ISOs that you +need to update, or VMs that can't vMotion because they are tied into a physical resource from the ESXi host that is running it. +VM object is key (as it's the first managed object in the output), enabling you the ability to right-click an entry in the +report to edit the target VM. Script is able to report on VMs with multiple CD-Drives as well. Version 1.0, written by +Aaron Smith (@awsmith99), published 07/29/2016. +#> + +param +( + [Parameter(Mandatory=$true)] + [VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster] + $vParam +); + +[Array] $vmList = @( Get-VM -Location $vParam | Sort Name ); + +foreach ( $vmItem in $vmList ) +{ + [Array] $vmCdDriveList = @( Get-CDDrive -VM $vmItem ); + + foreach ( $vmCdDriveItem in $vmCdDriveList ) + { + [String] $insertedElement = ""; + [String] $connectionType = ""; + + switch ( $vmCdDriveItem ) + { + { $_.IsoPath } { $insertedElement = $_.IsoPath; $connectionType = "ISO"; break; } + { $_.HostDevice } { $insertedElement = $_.HostDevice; $connectionType = "Host Device"; break; } + { $_.RemoteDevice } { $insertedElement = $_.RemoteDevice; $connectionType = "Remote Device"; break; } + default { $insertedElement = "None"; $connectionType = "Client Device"; break; } + } + + $output = New-Object -TypeName PSObject; + + $output | Add-Member -MemberType NoteProperty -Name "VM" -Value $vmItem + $output | Add-Member -MemberType NoteProperty -Name "CD-Drive" -Value $vmCdDriveItem.Name; + $output | Add-Member -MemberType NoteProperty -Name "Connection" -Value $connectionType; + $output | Add-Member -MemberType NoteProperty -Name "Inserted" -Value $insertedElement; + $output | Add-Member -MemberType NoteProperty -Name "Connected" -Value $vmCdDriveItem.ConnectionState.Connected; + $output | Add-Member -MemberType NoteProperty -Name "StartConnected" -Value $vmCdDriveItem.ConnectionState.StartConnected; + $output | Add-Member -MemberType NoteProperty -Name "AllowGuestControl" -Value $vmCdDriveItem.ConnectionState.AllowGuestControl; + $output; + } +} \ No newline at end of file diff --git a/README.md b/README.md index 9a369fa..ae27a3d 100644 --- a/README.md +++ b/README.md @@ -178,11 +178,10 @@ The VMware Technnology Preview License Agreement: + +function Get-DatastoreProvisioned { +<# +.SYNOPSIS +Retrieve the total thin provisioned space on each datastore. + +.DESCRIPTION +Intended to reveal provisioned space alongside total/free space, to assist with svMotion decisions. +-Name should be supplied from the pipeline via Get-Datastore. + +.EXAMPLE +Get-Datastore | Get-DatastoreProvisioned | Format-Table -AutoSize +View all datastores and view their capacity statistics in the current console. + +.EXAMPLE +Get-Datastore -Name '*ssd' | Get-DatastoreProvisioned | Where-Object -Property ProvisionedPct -ge 100 +For all datastores ending in 'ssd', return the capacity stats of those at least 100% provisioned. + +.INPUTS +[VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.VmfsDatastoreImpl] +Object type supplied by PowerCLI function Get-Datastore + +.LINK +https://github.com/vmware/PowerCLI-Example-Scripts + +.LINK +https://twitter.com/brianbunke +#> + [CmdletBinding()] + param ( + # Specifies the datastore names to check. Tested only with pipeline input (see examples). + [Parameter(ValueFromPipeline = $true)] + $Name + ) + + PROCESS { + ForEach ($DS in $Name) { + # Calculate total provisioned space from the exposed properties + $Provisioned = ($DS.ExtensionData.Summary.Capacity - + $DS.ExtensionData.Summary.FreeSpace + + $DS.ExtensionData.Summary.Uncommitted) / 1GB + + # Return info, wrapping it in the Math.Round method to trim to two decimal places + [PSCustomObject]@{ + Name = $DS.Name + FreeSpaceGB = [math]::Round($DS.FreeSpaceGB, 2) + CapacityGB = [math]::Round($DS.CapacityGB, 2) + ProvisionedGB = [math]::Round($Provisioned, 2) + UsedPct = [math]::Round((($DS.CapacityGB - $DS.FreeSpaceGB) / $DS.CapacityGB) * 100, 2) + ProvisionedPct = [math]::Round(($Provisioned / $DS.CapacityGB) * 100, 2) + } #pscustomobject + } #foreach + } #process +} #function diff --git a/Scripts/Get-VMID.ps1 b/Scripts/Get-VMID.ps1 new file mode 100644 index 0000000..a081bb3 --- /dev/null +++ b/Scripts/Get-VMID.ps1 @@ -0,0 +1,41 @@ +function Get-VMID { +<# + .NOTES + =========================================================================== + Created by: Markus Kraus + Organization: Private + Personal Blog: mycloudrevolution.com + Twitter: @vMarkus_K + =========================================================================== + .DESCRIPTION + This will quickly return all IDs of VMs + .Example + Get-VMID -myVMs (Get-VM) | ft + .Example + $SampleVMs = Get-VM "tst*" + Get-VMID -myVMs $SampleVMs +#> + [CmdletBinding()] + param( + [Parameter(Mandatory=$true, + ValueFromPipeline=$True, + Position=0)] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] + $myVMs + ) +Process { + + $MyView = @() + ForEach ($myVM in $myVMs){ + $UUIDReport = [PSCustomObject] @{ + Name = $myVM.name + UUID = $myVM.extensiondata.Config.UUID + InstanceUUID = $myVM.extensiondata.config.InstanceUUID + LocationID = $myVM.extensiondata.config.LocationId + MoRef = $myVM.extensiondata.Moref.Value + } + $MyView += $UUIDReport + } + $MyView + } +} \ No newline at end of file diff --git a/Scripts/Report-LUNPath-ESXCLI.ps1 b/Scripts/Report-LUNPath-ESXCLI.ps1 new file mode 100644 index 0000000..ec3b8ee --- /dev/null +++ b/Scripts/Report-LUNPath-ESXCLI.ps1 @@ -0,0 +1,62 @@ +<# + .NOTES + =========================================================================== + Created by: Markus Kraus + Organization: Private + Personal Blog: mycloudrevolution.com + Twitter: @vMarkus_K + =========================================================================== + Tested Against Environment: + vSphere Version: 6.0 U1, 5.5 U2 + PowerCLI Version: PowerCLI 6.3 R1 + PowerShell Version: 5.0 + OS Version: Windows 8.1, Server 2012 R2 + Keyword: ESXi, LUN, Path, Storage + + Dependencies: + PowerCLI Version: PowerCLI 6.3 R1 + + .DESCRIPTION + This script will create a Report of LUNs with Paths that have more than one unique LUN ID or have more than the defined Paths. + Information’s will be gathered via ESXCLI. This is necessary to report also hidden Paths! + + .Example + ./Report-LUNPath-ESXCLI.ps1 + +#> + +#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"} + +#region 1: Global Definitions +$MaxLUNPaths = 2 +#endregion + +#region 2: Get all Connected Hosts +$myHosts = Get-VMHost | where {$_.ConnectionState -eq "Connected" -and $_.PowerState -eq "PoweredOn"} +#endregion + +#region 3: Create Report +$Report = @() +foreach ($myHost in $myHosts) { + $esxcli2 = Get-ESXCLI -VMHost $myHost -V2 + $devices = $esxcli2.storage.core.path.list.invoke() | select Device -Unique + + foreach ($device in $devices) { + $arguments = $esxcli2.storage.core.path.list.CreateArgs() + $arguments.device = $device.Device + $LUNs = $esxcli2.storage.core.path.list.Invoke($arguments) + + $LUNReport = [PSCustomObject] @{ + HostName = $myHost.Name + Device = $device.Device + LUNPaths = $LUNs.Length + LUNIDs = $LUNs.LUN | Select-Object -Unique + } + $Report += $LUNReport + } + } +#endregion + +#region 4: Output Report +$Report | where {$_.LUNPaths -gt $MaxLUNPaths -or ($_.LUNIDs | measure).count -gt 1 } | ft -AutoSize +#endregion \ No newline at end of file diff --git a/Scripts/vRealize Operations Maintenance Mode.ps1 b/Scripts/vRealize Operations Maintenance Mode.ps1 new file mode 100644 index 0000000..a6ff9e5 --- /dev/null +++ b/Scripts/vRealize Operations Maintenance Mode.ps1 @@ -0,0 +1,116 @@ +Connect-VIServer vc-l-01a.corp.local -User administrator@vsphere.local -Password VMware1! +Connect-OMServer vrops.corp1.local -User admin -Password VMware1! + +function Enable-OMMaintenance { + <# + .NOTES + Script name: vRealize Operations Maintenance Mode.ps1 + Created on: 07/26/2016 + Author: Alan Renouf, @alanrenouf + Dependencies: PowerCLI 6.0 R2 or later + .DESCRIPTION + Places a vSphere Inventory object into maintenance mode in vRealize Operations + .Example + Set All VMs with a name as backup as being in maintenance mode for 20 minutes: + + Get-VM backup* | Enable-OMMaintenance -MaintenanceTime 20 + + Name Health ResourceKind Description + ---- ------ ------------ ----------- + backup-089e13fd-7d7a-0 Grey VirtualMachine + backup-d90e0b39-2618-0 Grey VirtualMachine + backup-e48ca842-316a-0 Grey VirtualMachine + backup-77da3713-919a-0 Grey VirtualMachine + backup-c32f4da8-86c4-0 Grey VirtualMachine + backup-c3fcb95c-cfe2-0 Grey VirtualMachine + backup-4318bb1e-614a-0 Grey VirtualMachine + + #> + [CmdletBinding()] + param( + [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Resource, + + [Parameter(Position=1, Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [Int] + $MaintenanceTime + ) + process { + Foreach ($Entry in $resource) { + $Item = Get-Inventory -Name $Entry | Get-OMResource + if (-not $Item) { + throw "$Entry not found" + } Else { + $Item.ExtensionData.MarkResourceAsBeingMaintained($MaintenanceTime) + Get-Inventory -Name $Entry | Get-OMResource + } + } + } +} + +function Disable-OMMaintenance { + <# + .NOTES + Script name: vRealize Operations Maintenance Mode.ps1 + Created on: 07/26/2016 + Author: Alan Renouf, @alanrenouf + Dependencies: PowerCLI 6.0 R2 or later + .DESCRIPTION + Removes a vSphere Inventory object from maintenance mode in vRealize Operations + .Example + Disable maintenance mode for all VMs with a name of backup + + Get-VM backup* | Disable-OMMaintenance + + Name Health ResourceKind Description + ---- ------ ------------ ----------- + backup-089e13fd-7d7a-0 Grey VirtualMachine + backup-d90e0b39-2618-0 Grey VirtualMachine + backup-e48ca842-316a-0 Grey VirtualMachine + backup-77da3713-919a-0 Grey VirtualMachine + backup-c32f4da8-86c4-0 Yellow VirtualMachine + backup-c3fcb95c-cfe2-0 Yellow VirtualMachine + backup-4318bb1e-614a-0 Yellow VirtualMachine + + #> + [CmdletBinding()] + param( + [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Resource + ) + process { + Foreach ($Entry in $resource) { + $Item = Get-Inventory -Name $Entry | Get-OMResource + if (-not $Item) { + throw "$Entry not found" + } Else { + $Item.ExtensionData.UnmarkResourceAsBeingMaintained() + Get-Inventory -Name $Entry | Get-OMResource + } + } + } +} + +Write-Host "Enable a single host as being in maintenance mode for 1 minute" +Enable-OMMaintenance -Resource ESX-01a* -MaintenanceTime 1 + +Write-Host "List All Host Resources and their state" +Get-OMResource ESX-* | Select Name, State | FT + +Write-Host "Set All VMs with a name as backup as being in maintenance mode for 20 minutes" +Get-VM backup* | Enable-OMMaintenance -MaintenanceTime 20 + +Write-Host "List All Backup VM Resources and their state" +Get-VM backup* | Get-OMResource | Select Name, State | FT + +Write-Host "Disable maintenance mode for all VMs with a name as backup as we have completed our scheduled work" +Get-VM backup* | Disable-OMMaintenance + +Write-Host "List All VM Resources and their state" +Get-VM backup* | Get-OMResource | Select Name, State | FT +