From 3403db0eadeb417246e3dce12cddc58c8b900a64 Mon Sep 17 00:00:00 2001 From: Alan Renouf Date: Fri, 15 Jul 2016 16:43:32 -0700 Subject: [PATCH 01/19] Pester VC Connection test Connection and modules tests for VC in pester --- Pester/Test Connection to VC.ps1 | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Pester/Test Connection to VC.ps1 diff --git a/Pester/Test Connection to VC.ps1 b/Pester/Test Connection to VC.ps1 new file mode 100644 index 0000000..cf017bc --- /dev/null +++ b/Pester/Test Connection to VC.ps1 @@ -0,0 +1,40 @@ +<# +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 +#> + +$VCNAME = "MyVC@Mydomain.local" +$VCUSER = "Administrator@vsphere.local" +$VCPASS = "Admin!23" + +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 From 99673b1dfa9791db6fda18f78f89ec94e45f6dbe Mon Sep 17 00:00:00 2001 From: Alan Renouf Date: Fri, 15 Jul 2016 16:45:03 -0700 Subject: [PATCH 02/19] removed pester test so it gets approval --- Pester/Test Connection to VC.ps1 | 40 -------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 Pester/Test Connection to VC.ps1 diff --git a/Pester/Test Connection to VC.ps1 b/Pester/Test Connection to VC.ps1 deleted file mode 100644 index cf017bc..0000000 --- a/Pester/Test Connection to VC.ps1 +++ /dev/null @@ -1,40 +0,0 @@ -<# -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 -#> - -$VCNAME = "MyVC@Mydomain.local" -$VCUSER = "Administrator@vsphere.local" -$VCPASS = "Admin!23" - -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 From e709f1fddea0bc133d33ff7d280b7226f1b8eb8b Mon Sep 17 00:00:00 2001 From: Alan Renouf Date: Fri, 15 Jul 2016 16:47:08 -0700 Subject: [PATCH 03/19] Pester Tests for VC Connection Pester Tests for VC Connection --- Pester/Test Connection to VC.ps1 | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Pester/Test Connection to VC.ps1 diff --git a/Pester/Test Connection to VC.ps1 b/Pester/Test Connection to VC.ps1 new file mode 100644 index 0000000..cf017bc --- /dev/null +++ b/Pester/Test Connection to VC.ps1 @@ -0,0 +1,40 @@ +<# +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 +#> + +$VCNAME = "MyVC@Mydomain.local" +$VCUSER = "Administrator@vsphere.local" +$VCPASS = "Admin!23" + +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 From 2e25d166a09b647bfc1cc8eec222ddc1f7778bfb Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Tue, 26 Jul 2016 09:04:38 -0400 Subject: [PATCH 04/19] Update README.md Updating the board members --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 9a369fa..28ccbcd 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,6 @@ Board members are voulenteers from the PowerCLI community and VMware staff membe Members: * Josh Atwell (Community Member) -* Mathieu Buisson (Community Member) * Luc Dekens (Community Member) * Jonathan Medd (Community Member) * Alan Renouf (VMware) From ca70d01e54cd30697faabd5fb66b47fe4c8e022e Mon Sep 17 00:00:00 2001 From: Alan Renouf Date: Tue, 26 Jul 2016 22:35:41 -0700 Subject: [PATCH 05/19] Update pester and add vrops script Updated Pester test so it can be called with parameters and included vROPS Maintenance Mode Script --- Pester/Test Connection to VC.ps1 | 10 +- .../vRealize Operations Maintenance Mode.ps1 | 116 ++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 Scripts/vRealize Operations Maintenance Mode.ps1 diff --git a/Pester/Test Connection to VC.ps1 b/Pester/Test Connection to VC.ps1 index cf017bc..006825a 100644 --- a/Pester/Test Connection to VC.ps1 +++ b/Pester/Test Connection to VC.ps1 @@ -4,11 +4,15 @@ 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"} } + #> -$VCNAME = "MyVC@Mydomain.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" { 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 + From e91b0c064913422ba6cd9aa70d7d4b02fbf203a2 Mon Sep 17 00:00:00 2001 From: mycloudrevolution Date: Wed, 27 Jul 2016 23:42:23 +0200 Subject: [PATCH 06/19] Get-VMID This will quickly return all IDs of VMs --- Scripts/Get-VMID.ps1 | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Scripts/Get-VMID.ps1 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 From e1937544fbbe1a7f5654aa0ba2d8451df91c9dfa Mon Sep 17 00:00:00 2001 From: brianbunke Date: Wed, 27 Jul 2016 23:32:28 -0700 Subject: [PATCH 07/19] Add Get-DatastoreProvisioned Script returns thin provisioned info on datastores. Pester file is a way to validate that future changes made to the script don't break existing functionality --- Pester/Get-DatastoreProvisioned.Tests.ps1 | 92 +++++++++++++++++++++++ Scripts/Get-DatastoreProvisioned.ps1 | 67 +++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 Pester/Get-DatastoreProvisioned.Tests.ps1 create mode 100644 Scripts/Get-DatastoreProvisioned.ps1 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/Scripts/Get-DatastoreProvisioned.ps1 b/Scripts/Get-DatastoreProvisioned.ps1 new file mode 100644 index 0000000..12a72b8 --- /dev/null +++ b/Scripts/Get-DatastoreProvisioned.ps1 @@ -0,0 +1,67 @@ +<# +Script name: Get-DatastoreProvisioned.ps1 +Created on: 2016/07/27 +Author: Brian Bunke, @brianbunke +Description: Augments Get-Datastore with thin provisioned info +Note to future contributors: Test changes with Pester file Get-DatastoreProvisioned.Tests.ps1 + +===Tested Against Environment==== +vSphere Version: 6.0 U1/U2 +PowerCLI Version: PowerCLI 6.3 R1 +PowerShell Version: 5.0 +OS Version: Windows 7/10 +#> + +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 From 06a3ea0210f3d6de6693bee216337c9dab812349 Mon Sep 17 00:00:00 2001 From: Chris Nakagaki Date: Thu, 28 Jul 2016 09:58:00 -0400 Subject: [PATCH 08/19] Update README.md Spelling correction. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 28ccbcd..ae27a3d 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ The VMware Technnology Preview License Agreement: Date: Fri, 29 Jul 2016 16:38:46 -0500 Subject: [PATCH 09/19] VM-CdDrive-Report 1.0 PowerActions report script for Cluster objects. Reports on status of all VM's CD-Drives, making it easy to find VMs connected to a given ISO or that might be using a physical ESXI host drive and unable to vMotion. --- PowerActions/VM-CdDrive-Report.ps1 | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 PowerActions/VM-CdDrive-Report.ps1 diff --git a/PowerActions/VM-CdDrive-Report.ps1 b/PowerActions/VM-CdDrive-Report.ps1 new file mode 100644 index 0000000..7fb3fd8 --- /dev/null +++ b/PowerActions/VM-CdDrive-Report.ps1 @@ -0,0 +1,52 @@ +<# +.MYNGC_REPORT +#> + +# AUTHOR: Aaron Smith (@awsmith99) +# VERSION: 1.0 +# PUBLISHED: 2016.07.29 +# ABOUT : 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. + +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 From 153275f51b4e84441d59bde593a051fd90c7f368 Mon Sep 17 00:00:00 2001 From: Roman Gelman Date: Mon, 1 Aug 2016 09:55:13 +0300 Subject: [PATCH 10/19] Vi-Module manifest The Vi-Module module manifest PSD1 file --- Modules/Vi-Module/Vi-Module.psd1 | 120 +++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 Modules/Vi-Module/Vi-Module.psd1 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 = '' + +} + From f40ca375a17c4e3c7f697e46f2dac286f6f2f1a7 Mon Sep 17 00:00:00 2001 From: Roman Gelman Date: Mon, 1 Aug 2016 10:00:54 +0300 Subject: [PATCH 11/19] 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 '*' From ea866993dfba819821e113610bd5d01a88f982a9 Mon Sep 17 00:00:00 2001 From: mycloudrevolution Date: Mon, 1 Aug 2016 23:04:48 +0200 Subject: [PATCH 12/19] Report-LUNPath-ESXCLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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! --- Scripts/Report-LUNPath-ESXCLI.ps1 | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Scripts/Report-LUNPath-ESXCLI.ps1 diff --git a/Scripts/Report-LUNPath-ESXCLI.ps1 b/Scripts/Report-LUNPath-ESXCLI.ps1 new file mode 100644 index 0000000..7d9fa79 --- /dev/null +++ b/Scripts/Report-LUNPath-ESXCLI.ps1 @@ -0,0 +1,50 @@ +<# + .NOTES + =========================================================================== + Created by: Markus Kraus + Organization: Private + Personal Blog: mycloudrevolution.com + Twitter: @vMarkus_K + =========================================================================== + .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 + +#> + +#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 From 37fb6e0d27ee21f23b8af495353f27fd0d454416 Mon Sep 17 00:00:00 2001 From: mycloudrevolution Date: Tue, 2 Aug 2016 22:47:23 +0200 Subject: [PATCH 13/19] Added #Requires -Modules and Test Environment --- Scripts/Report-LUNPath-ESXCLI.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Scripts/Report-LUNPath-ESXCLI.ps1 b/Scripts/Report-LUNPath-ESXCLI.ps1 index 7d9fa79..ec3b8ee 100644 --- a/Scripts/Report-LUNPath-ESXCLI.ps1 +++ b/Scripts/Report-LUNPath-ESXCLI.ps1 @@ -6,6 +6,16 @@ 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! @@ -15,6 +25,8 @@ #> +#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"} + #region 1: Global Definitions $MaxLUNPaths = 2 #endregion From c4d54cc42bc755f9e8ec01af147e34947c015d79 Mon Sep 17 00:00:00 2001 From: mycloudrevolution Date: Tue, 2 Aug 2016 23:04:54 +0200 Subject: [PATCH 14/19] Push-vLIMessage --- Modules/PSvLIMessage.psm1 | 122 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 Modules/PSvLIMessage.psm1 diff --git a/Modules/PSvLIMessage.psm1 b/Modules/PSvLIMessage.psm1 new file mode 100644 index 0000000..9752e16 --- /dev/null +++ b/Modules/PSvLIMessage.psm1 @@ -0,0 +1,122 @@ +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 + Push Messages to VMware vRealize Log Insight. + + .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 2.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 From 7f911cf268b90b8d5675f0357a7910ed40420fc7 Mon Sep 17 00:00:00 2001 From: mycloudrevolution Date: Tue, 2 Aug 2016 23:20:02 +0200 Subject: [PATCH 15/19] #Requires PS -Version 2.0 -> 3.0 --- Modules/PSvLIMessage.psm1 | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Modules/PSvLIMessage.psm1 b/Modules/PSvLIMessage.psm1 index 9752e16..9cab209 100644 --- a/Modules/PSvLIMessage.psm1 +++ b/Modules/PSvLIMessage.psm1 @@ -27,38 +27,39 @@ add-type @" Dependencies: PowerCLI Version: PowerCLI 6.3 R1 + .SYNOPSIS - Push Messages to VMware vRealize Log Insight. + Push Messages to VMware vRealize Log Insight. .DESCRIPTION - Push Messages to VMware vRealize Log Insight. + 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" + 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 + 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 + 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" + Specify the vRealize Log Insight Agent ID, e.g. "12862842-5A6D-679C-0E38-0E2BE888BB28" .PARAMETER Text - Specify the Event Text + Specify the Event Text .PARAMETER Hostname - Specify the Hostanme displayed in vRealize Log Insight + Specify the Hostanme displayed in vRealize Log Insight .PARAMETER FieldName - Specify the a Optional Field Name for vRealize Log Insight + 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 + 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 2.0 + #Requires PS -Version 3.0 #> function Push-vLIMessage { From 0b69b0dbe1d0453db4b5049cfb4c4ac1fe1cd250 Mon Sep 17 00:00:00 2001 From: Roman Gelman Date: Wed, 3 Aug 2016 16:28:49 +0300 Subject: [PATCH 16/19] Update Vi-Module.psm1 Hi Luc, I have fixed all your remarks. --- Modules/Vi-Module/Vi-Module.psm1 | 151 +++++++++++++++++-------------- 1 file changed, 85 insertions(+), 66 deletions(-) diff --git a/Modules/Vi-Module/Vi-Module.psm1 b/Modules/Vi-Module/Vi-Module.psm1 index b7739a6..cb1d252 100644 --- a/Modules/Vi-Module/Vi-Module.psm1 +++ b/Modules/Vi-Module/Vi-Module.psm1 @@ -27,8 +27,9 @@ Function Get-RDM { 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://goo.gl/3wO4pi + http://www.ps1code.com/single-post/2015/10/16/How-to-get-RDM-Raw-Device-Mappings-disks-using-PowerCLi #> [CmdletBinding()] @@ -53,7 +54,7 @@ Process { Foreach ($vm in ($VMs |Get-View)) { Foreach ($dev in $vm.Config.Hardware.Device) { - If (($dev.GetType()).Name -eq "VirtualDisk") { + 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)" @@ -106,22 +107,25 @@ Function Convert-VmdkThin2EZThick { .SYNOPSIS Inflate thin virtual disks. .DESCRIPTION - This function convert all Thin Provisioned VM's disks to type 'Thick Provision Eager Zeroed'. + This function converts all Thin Provisioned VM' disks to type 'Thick Provision Eager Zeroed'. .PARAMETER VM - VM's collection, returned by Get-VM cmdlet. + 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 - Get-VM collection. - [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]] + [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]] Objects, returned by Get-VM cmdlet. .OUTPUTS - PSObject collection. + [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://goo.gl/cVpTpO + 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)] @@ -130,8 +134,8 @@ 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 + [Alias("VMs")] + [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine[]]$VM ) @@ -144,23 +148,23 @@ Begin { Process { - Foreach ($vm in ($VMs |Get-View)) { + Foreach ($vmv in ($VM |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'")) { + 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 $vm is registered ### - $esx = Get-View $vm.Runtime.Host + ### Get ESXi object where $vmv is registered ### + $esx = Get-View $vmv.Runtime.Host - ### Get Datacenter object where $vm is registered ### - $parentObj = Get-View $vm.Parent + ### 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 $vm.Config.Hardware.Device) { - If (($dev.GetType()).Name -eq "VirtualDisk") { + 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) @@ -171,11 +175,11 @@ Process { $task = Get-View $taskMoRef ### Show task progress ### - For ($i=1;$i -lt [int32]::MaxValue;$i++) { + 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)" ` + 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 @@ -194,7 +198,7 @@ Process { $null = $dev.Backing.FileName -match $regxVMDK $Properties = [ordered]@{ - VM = $vm.Name + VM = $vmv.Name VMHost = $esx.Name Datastore = $Matches.Datastore VMDK = $Matches.Filename @@ -210,7 +214,7 @@ Process { } } } - $vm.Reload() + $vmv.Reload() } } } @@ -224,15 +228,13 @@ New-Alias -Name Convert-ViMVmdkThin2EZThick -Value Convert-VmdkThin2EZThick -For 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, + This script generates a list of ESXi Hosts with common suffix in a name, e.g. (esxprod1,esxprod2, ...) or (esxdev01,esxdev02, ...) etc. and - search VCenter's VM throw direct connection to this group of ESXi Hosts. + searches VCenter's VM throw direct connection to this group of ESXi Hosts. .PARAMETER VC VC's VM Name. .PARAMETER HostSuffix @@ -244,41 +246,45 @@ Function Find-VcVm { .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 + PS C:\> Find-VcVm vc1 esxprod 1 20 -AddZero .EXAMPLE - C:\PS> .\Find-VC.ps1 -VC vc1 -HostSuffix esxdev -PostfixEnd 6 + PS C:\> Find-VcVm -VC vc1 -HostSuffix esxdev -PostfixEnd 6 .EXAMPLE - C:\PS> .\Find-VC.ps1 vc1 esxprod |fl + PS C:\> Find-VcVm vc1 esxprod |fl .NOTES - Author: Roman Gelman. + 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 - PSCustomObject with two Properties: VC,VMHost or $null. + [System.Management.Automation.PSCustomObject] PSObject collection. .LINK - http://rgel75.wix.com/blog + http://ps1code.com #> Param ( [Parameter(Mandatory=$true,Position=1,HelpMessage="vCenter's VM Name")] [Alias("vCenter","VcVm")] - [System.String]$VC + [string]$VC , [Parameter(Mandatory=$true,Position=2,HelpMessage="ESXi Hosts' common suffix")] [Alias("VMHostSuffix","ESXiSuffix")] - [System.String]$HostSuffix + [string]$HostSuffix , [Parameter(Mandatory=$false,Position=3,HelpMessage="ESXi Hosts' postfix number start")] [ValidateRange(1,98)] [Alias("PostfixFirst","Start")] - [Int]$PostfixStart = 1 + [int]$PostfixStart = 1 , [Parameter(Mandatory=$false,Position=4,HelpMessage="ESXi Hosts' postfix number end")] [ValidateRange(2,99)] [Alias("PostfixLast","End")] - [Int]$PostfixEnd = 9 + [int]$PostfixEnd = 9 , [Parameter(Mandatory=$false,Position=5,HelpMessage="Add ESXi Hosts' postfix leading zero")] - [Switch]$AddZero = $false + [switch]$AddZero = $false ) Begin { @@ -289,7 +295,6 @@ Begin { Process { - $VMHostName = '' $cred = Get-Credential -UserName root -Message "Common VMHost Credentials" If ($cred) { $hosts = @() @@ -301,9 +306,15 @@ Process { $hosts += $HostSuffix + $i } } - Connect-VIServer $hosts -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -Credential $cred |select Name,IsConnected |ft -AutoSize + + Connect-VIServer $hosts -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -Credential $cred ` + |select @{N='VMHost';E={$_.Name}},IsConnected |ft -AutoSize + If ($global:DefaultVIServers.Length -ne 0) { - $VMHostName = (Get-VM -ErrorAction SilentlyContinue |? {$_.Name -eq $VC} |select -ExpandProperty VMHost).Name + $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 } } @@ -311,15 +322,16 @@ Process { End { - If ($VMHostName) { + If ($TargetVM) { $Properties = [ordered]@{ - VC = $VC - VMHost = $VMHostName + VC = $VC + Hostname = $VCHostname + PowerState = $PowerState + VMHost = $VMHostHostname } $Object = New-Object PSObject -Property $Properties - return $Object + $Object } - Else {return $null} } } #EndFunction Find-VcVm @@ -337,7 +349,7 @@ Function Set-PowerCLiTitle { .NOTES Author: Roman Gelman. .LINK - http://goo.gl/0h97C6 + 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 @@ -390,15 +402,17 @@ Filter Get-VMHostFirmwareVersion { [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 - https://goo.gl/Yg7mYp + http://www.ps1code.com/single-post/2016/1/9/How-to-know-ESXi-servers%E2%80%99-BIOSFirmware-version-using-PowerCLi #> 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} + 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) @@ -444,7 +458,7 @@ Function Compare-VMHostSoftwareVib { 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 + http://www.ps1code.com/single-post/2016/1/10/How-to-compare-installed-VIB-packages-between-two-or-more-ESXi-hosts #> Param ( @@ -454,8 +468,8 @@ Param ( [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 + [Alias("DifferenceESXi","DifferenceVMHosts")] + [VMware.VimAutomation.ViCore.Types.V1.Inventory.VMHost[]]$DifferenceVMHost ) Begin { @@ -580,15 +594,16 @@ Function Enable-VMHostSSH { .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 - https://goo.gl/Yg7mYp + 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.Impl.V1.Inventory.ClusterImpl[]]$Cluster = (Get-Cluster) + [VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster[]]$Cluster = (Get-Cluster) ) Process { @@ -654,15 +669,16 @@ Function Disable-VMHostSSH { .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 - https://goo.gl/Yg7mYp + 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.Impl.V1.Inventory.ClusterImpl[]]$Cluster = (Get-Cluster) + [VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster[]]$Cluster = (Get-Cluster) , [Parameter(Mandatory=$false,Position=1)] [Switch]$BlockFirewall @@ -743,7 +759,7 @@ Function Set-VMHostNtpServer { Author :: Roman Gelman. Version 1.0 :: 10-Mar-2016 :: Release. .LINK - http://goo.gl/Q4S6yc + http://www.ps1code.com/single-post/2016/03/10/How-to-configure-NTP-servers-setting-on-ESXi-hosts-using-PowerCLi #> [CmdletBinding()] @@ -842,7 +858,7 @@ Function Get-Version { 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} + 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} @@ -858,8 +874,11 @@ Function Get-Version { .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://goo.gl/Dd6Ilt + http://www.ps1code.com/single-post/2016/05/25/How-to-know-any-VMware-object%E2%80%99s-version-Use-GetVersion #> [CmdletBinding(DefaultParameterSetName='VIO')] @@ -1081,7 +1100,7 @@ Begin { $ProductTypeName = 'VMware DVSwitch' Try { - $ProductInfo = $InputObject.Summary.ProductInfo + $ProductInfo = $InputObject.ExtensionData.Summary.ProductInfo $ProductFullVersion = 'VMware Distributed Virtual Switch ' + $ProductInfo.Version + ' build-' + $ProductInfo.Build $ProductVersion = [version]($ProductInfo.Version + '.' + $ProductInfo.Build) @@ -1195,11 +1214,11 @@ 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} + 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"} } } From 3cf6bf5d973d4794ac327b2554a2319ac522b17a Mon Sep 17 00:00:00 2001 From: aaronwsmith Date: Wed, 3 Aug 2016 14:29:19 -0500 Subject: [PATCH 17/19] VM-CdDrive-Report.ps1 -- Minor revision to metadata to confirm to PowerActions standards. Added .LABEL and .DESCRIPTION fields in place of the custom comments that documented the script. Tried to specify KEY(VM) under .MYNGC_REPORT section but that triggered validation errors for me in PowerActions. --- PowerActions/VM-CdDrive-Report.ps1 | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/PowerActions/VM-CdDrive-Report.ps1 b/PowerActions/VM-CdDrive-Report.ps1 index 7fb3fd8..5778bc3 100644 --- a/PowerActions/VM-CdDrive-Report.ps1 +++ b/PowerActions/VM-CdDrive-Report.ps1 @@ -1,17 +1,15 @@ <# .MYNGC_REPORT +.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. #> -# AUTHOR: Aaron Smith (@awsmith99) -# VERSION: 1.0 -# PUBLISHED: 2016.07.29 -# ABOUT : 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. - param ( [Parameter(Mandatory=$true)] From 002bf2b97ade522a7161b58a7a905280c4e3d5f2 Mon Sep 17 00:00:00 2001 From: aaronwsmith Date: Wed, 3 Aug 2016 15:08:05 -0500 Subject: [PATCH 18/19] VM-CdDrive-Report.ps1 - Final revision to metadata Figured out you have to explicitly escape the () characters when editing a PowerActions script within the Web Client. Added in KEY(VM) to tell PowerActions which column to use for Context Menu support within Web Client. Also seemed to speed up execution of the script! --- PowerActions/VM-CdDrive-Report.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/PowerActions/VM-CdDrive-Report.ps1 b/PowerActions/VM-CdDrive-Report.ps1 index 5778bc3..584484d 100644 --- a/PowerActions/VM-CdDrive-Report.ps1 +++ b/PowerActions/VM-CdDrive-Report.ps1 @@ -1,5 +1,6 @@ <# .MYNGC_REPORT +KEY\(VM\) .LABEL VM CD-Drive Report .DESCRIPTION From 02a7183d3ae74788e40c33ca309b20b30789397f Mon Sep 17 00:00:00 2001 From: Roman Gelman Date: Thu, 11 Aug 2016 10:19:26 +0300 Subject: [PATCH 19/19] Create README.md Hi Luc, Can you please approve the README.md file, it contains the links to the articles about every function and little help about module usage. --- Modules/Vi-Module/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Modules/Vi-Module/README.md 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`|