From 294863d49549bcfb1b97edb831529019704ae0df Mon Sep 17 00:00:00 2001 From: Rasmus Sjoerslev Date: Wed, 5 Apr 2017 21:06:18 +0200 Subject: [PATCH 1/5] Added Get-HVPodSessions function to VMware.Hv.Helper.psm1 which will show all connections across a Pod Federation. See Synopsis and Description for more details --- .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 7c06a99..9d7167f 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -5256,5 +5256,70 @@ function Get-HVMachineSummary { return $machineList } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool +function Get-HVPodSessions { +<# +.Synopsis + Gets the total amount of sessions for all Pods in a Federation + +.DESCRIPTION + Gets the total amout of current sessions (connected and disconnected) for all Pods in a Federation (CPA) + based on the global query service. + The default object response is used which contains both success and fault information as well as the + session count per pod and the ID of each pod. + +.PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer + +.EXAMPLE + Get-HVPodSessions + +.OUTPUTS + Returns list of objects of type GlobalSessionPodSessionCounter + +.NOTES + Author : Rasmus Sjoerslev + Author email : rasmus.sjorslev@vmware.com + Version : 1.0 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2 + PowerCLI Version : PowerCLI 6.5 + PowerShell Version : 5.0 +#> + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + $query_service_helper = New-Object VMware.Hv.GlobalSessionQueryServiceService + $count_spec = New-Object VMware.Hv.GlobalSessionQueryServiceCountSpec + $queryResults = @() + + foreach ($pod in $services.Pod.Pod_List()) { + $count_spec.Pod = $pod.Id + $info = $query_service_helper.GlobalSessionQueryService_GetCountWithSpec($services,$count_spec) + + foreach ($res in $info) { + if ($pod.Id.Id -eq $res.Id.Id) { + $queryResults += $res + } + } + } + return $queryResults +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,Get-HVPodSessions From d1fc624c57361b1f962ed2fa5254d117acd73bbd Mon Sep 17 00:00:00 2001 From: Rasmus Sjoerslev Date: Thu, 6 Apr 2017 11:47:20 +0200 Subject: [PATCH 2/5] Changed the name of the cmdlet from Get-HVPodSessions to Get-HVPodSession --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 9d7167f..7a3f909 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -5256,7 +5256,7 @@ function Get-HVMachineSummary { return $machineList } -function Get-HVPodSessions { +function Get-HVPodSession { <# .Synopsis Gets the total amount of sessions for all Pods in a Federation @@ -5272,7 +5272,7 @@ function Get-HVPodSessions { first element from global:DefaultHVServers would be considered inplace of hvServer .EXAMPLE - Get-HVPodSessions + Get-HVPodSession .OUTPUTS Returns list of objects of type GlobalSessionPodSessionCounter @@ -5321,5 +5321,5 @@ function Get-HVPodSessions { return $queryResults } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,Get-HVPodSessions +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,Get-HVPodSession From 1b4ca3fb2ed30e421ad99e7cea6abddf2ebdf1fc Mon Sep 17 00:00:00 2001 From: Alessio Rocchi Date: Fri, 7 Apr 2017 11:03:47 +0200 Subject: [PATCH 3/5] Create SetLunReservation.ps1 --- Scripts/SetLunReservation.ps1 | 103 ++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 Scripts/SetLunReservation.ps1 diff --git a/Scripts/SetLunReservation.ps1 b/Scripts/SetLunReservation.ps1 new file mode 100644 index 0000000..ae610a0 --- /dev/null +++ b/Scripts/SetLunReservation.ps1 @@ -0,0 +1,103 @@ +<# + .SYNOPSIS + Set a given LUN ID to Perennially Reserved. + + .DESCRIPTION + A description of the file. + + .PARAMETER vCenter + Set vCenter server to connect to + + .PARAMETER Username + Set username to use + + .PARAMETER Password + Set password to be used + + .PARAMETER VirtualMachine + Name of the virtual machine which has the RDM + + .NOTES + =========================================================================== + Created on: 20/03/2017 15:05 + Created by: Alessio Rocchi + Organization: VMware + Filename: SetLunReservation.ps1 + =========================================================================== +#> +param +( + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + Position = 0)] + [ValidateNotNullOrEmpty()] + [String]$vCenter, + [Parameter(Mandatory = $false, + ValueFromPipeline = $true, + HelpMessage = 'Set vCenter Username')] + [AllowNull()] + [String]$Username, + [Parameter(Mandatory = $false, + ValueFromPipeline = $true, + HelpMessage = 'Set vCenterPassword')] + [AllowNull()] + [String]$Password, + [Parameter(Mandatory = $true, + ValueFromPipeline = $true)] + [ValidateNotNullOrEmpty()] + [String]$VirtualMachine +) + +Import-Module -Name VMware.VimAutomation.Core -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Out-Null + +try +{ + if ([String]::IsNullOrEmpty($Username) -or [String]::IsNullOrEmpty($Password)) + { + $vcCredential = Get-Credential + Connect-VIServer -Server $vCenter -Credential $vcCredential -WarningAction SilentlyContinue -ErrorAction Stop | Out-Null + } + else + { + Connect-VIServer -Server $vCenter -User $Username -Password $Password -WarningAction SilentlyContinue -ErrorAction Stop | Out-Null + } +} +catch +{ + Write-Error("Error connecting to vCenter: {0}" -f $vCenter) + exit +} + + +$rDms = Get-HardDisk -DiskType rawPhysical -Vm (Get-VM -Name $VirtualMachine) +$clusterHosts = Get-Cluster -VM $VirtualMachine | Get-VMHost + +$menu = @{ } + +for ($i = 1; $i -le $rDms.count; $i++) +{ + Write-Host("{0}) {1}[{2}]: {3}" -f ($i, $rDms[$i - 1].Name, $rDms[$i - 1].CapacityGB, $rDms[$i - 1].ScsiCanonicalName)) + $menu.Add($i, ($rDms[$i - 1].ScsiCanonicalName)) +} + +[int]$ans = Read-Host 'Which Disk you want to configure?' +$selection = $menu.Item($ans) +write-host("Choosed Disk: {0}" -f $selection) + +$current = 0 +foreach ($vmHost in $clusterHosts) +{ + Write-Progress -Activity "Processing Cluster." -CurrentOperation $vmHost.Name -PercentComplete (($counter / $clusterHosts.count) * 100) + $esxcli = Get-EsxCli -V2 -VMHost $vmHost + $deviceListArgs = $esxcli.storage.core.device.list.CreateArgs() + $deviceListArgs.device = $selection + $esxcli.storage.core.device.list.Invoke($deviceListArgs) | Select-Object Device, IsPerenniallyReserved + $deviceSetArgs = $esxcli.storage.core.device.setconfig.CreateArgs() + $deviceSetArgs.device = $selection + $deviceSetArgs.perenniallyreserved = $true + $esxcli.storage.core.device.setconfig.Invoke($deviceSetArgs) + $counter++ +} + +Disconnect-VIServer -WarningAction SilentlyContinue -Server $vCenter -Force -Confirm:$false + From ae429792ed5b2e2f0855f8c70c428f4052449c1b Mon Sep 17 00:00:00 2001 From: Wouter Kursten Date: Wed, 26 Apr 2017 18:58:32 +0200 Subject: [PATCH 4/5] removed brake for issue #74 --- Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 7a3f909..c92eb14 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -5138,7 +5138,7 @@ function Get-HVMachine { $machineList = Find-HVMachine -Param $PSBoundParameters if (!$machineList) { Write-Host "No Virtual Machine(s) Found with given search parameters" - break + } $queryResults = @() $desktop_helper = New-Object VMware.Hv.MachineService From 70f7be027070edf229c4f7005ec94689c15da813 Mon Sep 17 00:00:00 2001 From: Alessio Rocchi Date: Wed, 3 May 2017 08:24:43 +0200 Subject: [PATCH 5/5] Add a script to set multiple datastore Tag. This example uses new powershell 5 features, classes and two different Design Patterns (Singleton and Disposable). --- SetDatastoreTag.ps1 | 198 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100755 SetDatastoreTag.ps1 diff --git a/SetDatastoreTag.ps1 b/SetDatastoreTag.ps1 new file mode 100755 index 0000000..23708e5 --- /dev/null +++ b/SetDatastoreTag.ps1 @@ -0,0 +1,198 @@ +<# + .SYNOPSIS + A brief description of the file. + + .DESCRIPTION + Given a list of Datastore Names, this script will assign a Tag to them + + .PARAMETER csvFile + String representing the full path of the file + The file must be structured like this: + ----------------------------- + Tag1,Tag2,Tag3,Tag4 + IPv4-iSCSI-SiteA,Tag1,Tag3 + IPv4-NFS-SiteA,Tag2,Tag4 + ... + ----------------------------- + + .NOTES + =========================================================================== + Created on: 31/03/2017 11:16 + Created by: Alessio Rocchi + Organization: VMware + Filename: SetDatastoreTag.ps1 + =========================================================================== +#> +[CmdletBinding()] +param +( + [Parameter(Mandatory = $true, + ValueFromPipeline = $true)] + [ValidateNotNullOrEmpty()] + [System.String]$csvFile, + [Parameter(Mandatory = $true, + ValueFromPipeline = $true)] + [ValidateNotNullOrEmpty()] + [String]$vCenter, + [Parameter(ValueFromPipeline = $true, + Position = 2)] + [AllowNull()] + [String]$Username, + [Parameter(Position = 3)] + [AllowNull()] + [String]$Password +) + +Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null + +class vcConnector : System.IDisposable +{ + [String]$Username + [String]$Password + [String]$vCenter + [PSObject]$server + + static [vcConnector]$instance + + vcConnector($Username, $Password, $vCenter) + { + Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null + + $this.Username = $Username + $this.Password = $Password + $this.vCenter = $vCenter + $this.connect() + } + + vcConnector($vcCredential, $vCenter) + { + Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null + + $this.vcCredential = $vcCredential + $this.vCenter = $vCenter + $this.connect() + } + + [void] hidden connect() + { + try + { + if ([String]::IsNullOrEmpty($this.Username) -or [String]::IsNullOrEmpty($this.Password)) + { + $vcCredential = Get-Credential + Connect-VIServer -Server $this.vCenter -Credential $this.vcCredential -WarningAction SilentlyContinue -ErrorAction Stop | Out-Null + } + else + { + Connect-VIServer -Server $this.vCenter -User $this.Username -Password $this.Password -WarningAction SilentlyContinue -ErrorAction Stop + } + Write-Debug("Connected to vCenter: {0}" -f $this.vCenter) + } + catch + { + Write-Error($Error[0].Exception.Message) + exit + } + } + + + [void] Dispose() + { + Write-Debug("Called Dispose Method of Instance: {0}" -f ($this)) + Disconnect-VIServer -WarningAction SilentlyContinue -Server $this.vCenter -Force -Confirm:$false | Out-Null + } + + static [vcConnector] GetInstance() + { + if ([vcConnector]::instance -eq $null) + { + [vcConnector]::instance = [vcConnector]::new() + } + + return [vcConnector]::instance + } +} + +class Content{ + [System.Collections.Generic.List[System.String]]$availableTags + [System.Collections.Generic.List[System.String]]$elements + + Content() + { + } + + Content([String]$filePath) + { + if ((Test-Path -Path $filePath) -eq $false) + { + throw ("Cannot find file: {0}" -f ($filePath)) + } + try + { + # Cast the Get-Content return type to Generic List of Strings in order to avoid fixed-size array + $this.elements = [System.Collections.Generic.List[System.String]](Get-Content -Path $filePath -ea SilentlyContinue -wa SilentlyContinue) + $this.availableTags = $this.elements[0].split(',') + # Delete the first element aka availableTags + $this.elements.RemoveAt(0) + } + catch + { + throw ("Error reading the file: {0}" -f ($filePath)) + } + } +} + +try +{ + $vc = [vcConnector]::new($Username, $Password, $vCenter) + $csvContent = [Content]::new($csvFile) + + Write-Host("Available Tags: {0}" -f ($csvContent.availableTags)) + + foreach ($element in $csvContent.elements) + { + [System.Collections.Generic.List[System.String]]$splittedList = $element.split(',') + # Get the Datastore Name + [System.String]$datastoreName = $splittedList[0] + # Removing Datastore Name + $splittedList.RemoveAt(0) + # Create a List of Tags which will be assigned to the Datastore + [System.Collections.Generic.List[PSObject]]$tagsToAssign = $splittedList | ForEach-Object { Get-Tag -Name $_ } + Write-Host("Tags to assign to Datastore: {0} are: {1}" -f ($datastoreName, $tagsToAssign)) + # Get Datastore object by the given Datastore Name, first field of the the line + $datastore = Get-Datastore -Name $datastoreName -ea Stop + # Iterate the assigned Datastore Tags + foreach ($tag in ($datastore | Get-TagAssignment)) + { + # Check if the current tag is one of the available ones. + if ($tag.Tag.Name -in $csvContent.availableTags) + { + # Remove the current assigned Tag + Write-Host("Removing Tag: {0}" -f ($tag)) + Remove-TagAssignment -TagAssignment $tag -Confirm:$false + } + } + # Finally add the new set of tags to the Datastore + foreach ($tag in $tagsToAssign) + { + Write-Host("Trying to assign Tag: {0} to Datastore: {1}" -f ($tag.Name, $datastoreName)) + # Assign the Tag + New-TagAssignment -Entity $datastore -Tag $tag + } + } +} +catch [VMware.VimAutomation.Sdk.Types.V1.ErrorHandling.VimException.VimException] +{ + Write-Error("VIException: {0}" -f ($Error[0].Exception.Message)) + exit +} +catch +{ + Write-Error $Error[0].Exception.Message + exit +} +finally +{ + # Let be assured that the vc connection will be disposed. + $vc.Dispose() +}