From 7a38462f1a7bb90591825fd0bcf25df6d2f52ecb Mon Sep 17 00:00:00 2001 From: lucdekens Date: Fri, 29 Jul 2016 15:34:15 +0200 Subject: [PATCH 01/20] Create VMFSIncrease.psd1 --- Modules/VMFSIncrease/VMFSIncrease.psd1 | 1 + 1 file changed, 1 insertion(+) create mode 100644 Modules/VMFSIncrease/VMFSIncrease.psd1 diff --git a/Modules/VMFSIncrease/VMFSIncrease.psd1 b/Modules/VMFSIncrease/VMFSIncrease.psd1 new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Modules/VMFSIncrease/VMFSIncrease.psd1 @@ -0,0 +1 @@ + From 1489e86b669e9ab790a1dfa265d52464db0a3ab8 Mon Sep 17 00:00:00 2001 From: lucdekens Date: Fri, 29 Jul 2016 15:37:11 +0200 Subject: [PATCH 02/20] Add files via upload --- Modules/VMFSIncrease/LICENSE.txt.URL | 6 + Modules/VMFSIncrease/VMFSIncrease.psd1 | 19 +- Modules/VMFSIncrease/VMFSIncrease.psm1 | 247 +++++++++++++++++++++++++ 3 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 Modules/VMFSIncrease/LICENSE.txt.URL create mode 100644 Modules/VMFSIncrease/VMFSIncrease.psm1 diff --git a/Modules/VMFSIncrease/LICENSE.txt.URL b/Modules/VMFSIncrease/LICENSE.txt.URL new file mode 100644 index 0000000..5ac2446 --- /dev/null +++ b/Modules/VMFSIncrease/LICENSE.txt.URL @@ -0,0 +1,6 @@ +[InternetShortcut] +URL=https://github.com/lucdekens/LogInsight/blob/v1.0/LICENSE.txt +IDList= +HotKey=0 +IconFile=C:\Users\ldekens\AppData\Local\Mozilla\Firefox\Profiles\2ahnnh1i.default\shortcutCache\ec4nFcIEAQBPFmSiPtTJ2w==.ico +IconIndex=0 diff --git a/Modules/VMFSIncrease/VMFSIncrease.psd1 b/Modules/VMFSIncrease/VMFSIncrease.psd1 index 8b13789..d87ad53 100644 --- a/Modules/VMFSIncrease/VMFSIncrease.psd1 +++ b/Modules/VMFSIncrease/VMFSIncrease.psd1 @@ -1 +1,18 @@ - +@{ + ModuleToProcess = 'VMFSIncrease.psm1' + ModuleVersion = '1.0.0.0' + GUID = '9f167385-c5c6-4a65-ac14-949c67519001' + Author = 'Luc Dekens ' + CompanyName = 'Community' + Copyright = '(c) 2016. All rights reserved.' + Description = 'Expand and Extend VMFS DatastoresModule description' + PowerShellVersion = '3.0' + FunctionsToExport = 'Get-VmfsDatastoreInfo','Get-VmfsDatastoreIncrease','New-VmfsDatastoreIncrease' + PrivateData = @{ + PSData = @{ + Tags = @('VMFS','Expand','Extend','vSphere') + LicenseUri = 'https://www.tldrlegal.com/l/mit' + ProjectUri = 'https://github.com/lucdekens/VMFSIncrease' + } + } +} diff --git a/Modules/VMFSIncrease/VMFSIncrease.psm1 b/Modules/VMFSIncrease/VMFSIncrease.psm1 new file mode 100644 index 0000000..ec0fa2b --- /dev/null +++ b/Modules/VMFSIncrease/VMFSIncrease.psm1 @@ -0,0 +1,247 @@ +function Get-VmfsDatastoreInfo +{ + [CmdletBinding(SupportsShouldProcess = $True)] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)] + [PSObject]$Datastore + ) + + Process + { + if ($Datastore -is [String]) + { + $Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue + } + if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]) + { + Write-Error 'Invalid value for Datastore.' + return + } + if ($Datastore.Type -ne 'VMFS') + { + Write-Error "$($Datastore.Name) is not a VMFS datastore" + return + } + + # Get the Datastore System Manager from an ESXi that has the Datastore + $esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key) + $hsSys = Get-View -Id $esx.ConfigManager.StorageSystem + + foreach ($extent in $Datastore.ExtensionData.Info.Vmfs.Extent) + { + $lun = $esx.Config.StorageDevice.ScsiLun | where{ $_.CanonicalName -eq $extent.DiskName } + + $hdPartInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName) + $hdPartInfo[0].Layout.Partition | %{ + New-Object PSObject -Property ([ordered]@{ + Datastore = $Datastore.Name + CanonicalName = $lun.CanonicalName + Model = "$($lun.Vendor.TrimEnd(' ')).$($lun.Model.TrimEnd(' ')).$($lun.Revision.TrimEnd(' '))" + DiskSizeGB = $hdPartInfo[0].Layout.Total.BlockSize * $hdPartInfo[0].Layout.Total.Block / 1GB + DiskBlocks = $hdPartInfo[0].Layout.Total.Block + DiskBlockMB = $hdPartInfo[0].Layout.Total.BlockSize/1MB + PartitionFormat = $hdPartInfo[0].Spec.PartitionFormat + Partition = if ($_.Partition -eq '') { '' }else{ $_.Partition } + Used = $extent.Partition -eq $_.Partition + Type = $_.Type + PartitionSizeGB = [math]::Round(($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize / 1GB, 1) + PartitionBlocks = $_.End.Block - $_.Start.Block + 1 + PartitionBlockMB = $_.Start.BlockSize/1MB + Start = $_.Start.Block + End = $_.End.Block + }) + } + } + } +} + +function Get-VmfsDatastoreIncrease +{ + [CmdletBinding(SupportsShouldProcess = $True)] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)] + [PSObject]$Datastore + ) + + Process + { + if ($Datastore -is [String]) + { + $Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue + } + if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]) + { + Write-Error 'Invalid value for Datastore.' + return + } + + if ($Datastore.Type -ne 'VMFS') + { + Write-Error "$($Datastore.Name) is not a VMFS datastore" + return + } + + # Get the Datastore System Manager from an ESXi that has the Datastore + $esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key) + $hsSys = Get-View -Id $esx.ConfigManager.StorageSystem + $hdSys = Get-View -Id $esx.ConfigManager.DatastoreSystem + + $extents = $Datastore.ExtensionData.Info.Vmfs.Extent | Select -ExpandProperty DiskName + + $hScsiDisk = $hdSys.QueryAvailableDisksForVmfs($Datastore.ExtensionData.MoRef) + foreach ($disk in $hScsiDisk) + { + $partInfo = $hsSys.RetrieveDiskPartitionInfo($disk.DeviceName) + $partUsed = ($partInfo[0].Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | + Measure-Object -Sum | select -ExpandProperty Sum)/1GB + if ($extents -contains $disk.CanonicalName) + { + $incType = 'Expand' + $vmfsExpOpt = $hdSys.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef) + $PartMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | + Measure-Object -Sum | select -ExpandProperty Sum)/1GB + } + else + { + $incType = 'Extend' + $vmfsExtOpt = $hdSys.QueryVmfsDatastoreExtendOptions($Datastore.ExtensionData.MoRef, $disk.DevicePath, $null) + $partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | + Measure-Object -Sum | select -ExpandProperty Sum)/1GB + } + New-Object PSObject -Property ([ordered]@{ + Datastore = $Datastore.Name + CanonicalName = $disk.CanonicalName + Model = "$($disk.Vendor.TrimEnd(' ')).$($disk.Model.TrimEnd(' ')).$($disk.Revision.TrimEnd(' '))" + DiskSizeGB = $partInfo[0].Layout.Total.BlockSize * $hdPartInfo[0].Layout.Total.Block / 1GB + DiskBlocks = $partInfo[0].Layout.Total.Block + DiskBlockMB = $partInfo[0].Layout.Total.BlockSize/1MB + AvailableGB = [math]::Round($partMax - $partUsed, 2) + Type = $incType + }) + } + } +} + +function New-VmfsDatastoreIncrease +{ + [CmdletBinding(SupportsShouldProcess = $True)] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)] + [PSObject]$Datastore, + [int]$IncreaseSizeGB, + [Parameter(Position = 1)] + [string]$CanonicalName, + [Parameter(Mandatory = $true, ParameterSetName = 'Expand')] + [switch]$Expand, + [Parameter(Mandatory = $true, ParameterSetName = 'ExTend')] + [switch]$Extend + ) + + Process + { + if ($Datastore -is [String]) + { + $Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue + } + if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore]) + { + Write-Error 'Invalid value for Datastore.' + return + } + + if ($Datastore.Type -ne 'VMFS') + { + Write-Error "$($Datastore.Name) is not a VMFS datastore" + return + } + + # Get the Datastore System Manager from an ESXi that has the Datastore + $esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key) + $hsSys = Get-View -Id $esx.ConfigManager.StorageSystem + $hdSys = Get-View -Id $esx.ConfigManager.DatastoreSystem + + $extents = $Datastore.ExtensionData.Info.Vmfs.Extent | Select -ExpandProperty DiskName + + $hScsiDisk = $hdSys.QueryAvailableDisksForVmfs($Datastore.ExtensionData.MoRef) + + # Expand or Extend + switch ($PSCmdlet.ParameterSetName) + { + 'Expand' { + $expOpt = $hdSys.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef) + if ($CanonicalName) + { + $dsOpt = $expOpt | where{ $_.Spec.Extent.DiskName -eq $CanonicalName } + } + else + { + $dsOpt = $expOpt | Sort-Object -Property { $_.Spec.Extent.Diskname } | select -first 1 + } + if ($IncreaseSizeGB -ne 0) + { + $lun = $hScsiDisk | where{ $_.CanonicalName -eq $dsOpt.Spec.Extent.DiskName } + $partInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName) + $partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | + Measure-Object -Sum | select -ExpandProperty Sum)/1GB + $partUsed = ($partInfo[0].Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | + Measure-Object -Sum | select -ExpandProperty Sum)/1GB + if (($partMax - $partUsed) -ge $IncreaseSizeGB) + { + $spec = $dsOpt.Spec + $spec.Partition.Partition[0].EndSector -= ([math]::Floor(($partMax - $partUsed - $IncreaseSizeGB) * 1GB/512)) + } + else + { + Write-Error "Requested expand size $($IncreaseSizeGB)GB not available on $($lun.CanonicalName)" + return + } + } + else + { + $spec = $dsOpt.Spec + } + $hdSys.ExpandVmfsDatastore($Datastore.ExtensionData.MoRef, $spec) + } + 'Extend' { + if ($CanonicalName) + { + $lun = $hScsiDisk | where{ $extents -notcontains $_.CanonicalName -and $_.CanonicalName -eq $CanonicalName } + } + else + { + $lun = $hScsiDisk | where{ $extents -notcontains $_.CanonicalName } | Sort-Object -Property CanonicalName | select -First 1 + } + if (!$lun) + { + Write-Error "No valid LUN provided or found for extent" + return + } + $vmfsExtOpt = $hdSys.QueryVmfsDatastoreExtendOptions($Datastore.ExtensionData.MoRef, $lun.DevicePath, $null) + if ($IncreaseSizeGB -ne 0) + { + $partInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName) + $partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } | + Measure-Object -Sum | select -ExpandProperty Sum)/1GB + if ($partMax -ge $IncreaseSizeGB) + { + $spec = $vmfsExtOpt[0].Spec + $spec.Partition.Partition[0].EndSector = $spec.Partition.Partition[0].StartSector + [math]::Floor($IncreaseSizeGB * 1GB / 512) + } + else + { + Write-Error "No valid LUN for extent with $($IncreaseSizeGB)GB space found" + return + } + } + else + { + $spec = $vmfsExtOpt.Spec + } + + $hdSys.ExtendVmfsDatastore($Datastore.ExtensionData.MoRef, $spec) + } + } + } +} + +Export-ModuleMember -Function Get-VmfsDatastoreInfo,Get-VmfsDatastoreIncrease,New-VmfsDatastoreIncrease From 7392e451c5d528fd2a44d9ca243441ff375f983e Mon Sep 17 00:00:00 2001 From: lucdekens Date: Fri, 29 Jul 2016 15:37:35 +0200 Subject: [PATCH 03/20] Create en-US --- Modules/VMFSIncrease/en-US | 1 + 1 file changed, 1 insertion(+) create mode 100644 Modules/VMFSIncrease/en-US diff --git a/Modules/VMFSIncrease/en-US b/Modules/VMFSIncrease/en-US new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Modules/VMFSIncrease/en-US @@ -0,0 +1 @@ + From b2ba87db865ead8f404af051ab7526cd4c8d828c Mon Sep 17 00:00:00 2001 From: lucdekens Date: Fri, 29 Jul 2016 15:38:13 +0200 Subject: [PATCH 04/20] Delete en-US --- Modules/VMFSIncrease/en-US | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Modules/VMFSIncrease/en-US diff --git a/Modules/VMFSIncrease/en-US b/Modules/VMFSIncrease/en-US deleted file mode 100644 index 8b13789..0000000 --- a/Modules/VMFSIncrease/en-US +++ /dev/null @@ -1 +0,0 @@ - From 7bbec511cbaf3d969450ce05f7e0e6ec64f11bbd Mon Sep 17 00:00:00 2001 From: lucdekens Date: Fri, 29 Jul 2016 15:38:56 +0200 Subject: [PATCH 05/20] Create about_VMFSIncrease.help.txt --- .../VMFSIncrease/en-US/about_VMFSIncrease.help.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Modules/VMFSIncrease/en-US/about_VMFSIncrease.help.txt diff --git a/Modules/VMFSIncrease/en-US/about_VMFSIncrease.help.txt b/Modules/VMFSIncrease/en-US/about_VMFSIncrease.help.txt new file mode 100644 index 0000000..55f3c0a --- /dev/null +++ b/Modules/VMFSIncrease/en-US/about_VMFSIncrease.help.txt @@ -0,0 +1,13 @@ +TOPIC + VMFSIncrease + +SYNOPSIS + The VMFSIncrease module offers the same functionality that is available +through the Increase button in the vSphere Web Client. + +DESCRIPTION + The VMFSIncrease offers functionality that allows to Expand or Extend + VMFS Datastores. The module uses the vSphere API to implement this functionality. + + SEE ALSO +http://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend From 99250732fb33773e67cc909c42ba45188200b03c Mon Sep 17 00:00:00 2001 From: lucdekens Date: Fri, 29 Jul 2016 15:39:10 +0200 Subject: [PATCH 06/20] Add files via upload --- .../en-US/VMFSIncrease.psm1-Help.xml | 473 ++++++++++++++++++ 1 file changed, 473 insertions(+) create mode 100644 Modules/VMFSIncrease/en-US/VMFSIncrease.psm1-Help.xml diff --git a/Modules/VMFSIncrease/en-US/VMFSIncrease.psm1-Help.xml b/Modules/VMFSIncrease/en-US/VMFSIncrease.psm1-Help.xml new file mode 100644 index 0000000..2ff4f26 --- /dev/null +++ b/Modules/VMFSIncrease/en-US/VMFSIncrease.psm1-Help.xml @@ -0,0 +1,473 @@ + + + + + + + + + + Get-VmfsDatastoreInfo + + Provides partition information for all the extents in the datastore. + + + + + Get + VmfsDatastoreInfo + + + + The function will display partition information for all the extents used by the datastore. + + + + + Get-VmfsDatastoreInfo + + Datastore + + The name of the Datastore or a PowerCLI Datastore object + + PSObject + + + + + + + + + Datastore + + The name of the Datastore or a PowerCLI Datastore object + + PSObject + + PSObject + + + + + + + + + + + System.Management.Automation.PSObject + + + + + + + + + + + + + System.Object + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + + PS C:\> + + Get-VmfsDatastoreInfo -Datastore MyDS + + Will return partition information for the Datastore named MyDS + + + + -------------------------- EXAMPLE 2 -------------------------- + + PS C:\> + + Get-Datastore -Name My* | Get-VmfsDatastoreInfo + + This example will return partition information for all the Datastore objects that are returned by the Get-Datastore PowerCLI cmdlet + + + + + + + + Get-VmfsDatastoreIncrease + + Displays the increase options for a datastore + + + + + Get + VmfsDatastoreIncrease + + + + The function will provide all the Expand and Extend options for a specific datastore + + + + + Get-VmfsDatastoreIncrease + + Datastore + + The name of the Datastore or a PowerCLI Datastore object + + PSObject + + + + + + + + + Datastore + + The name of the Datastore or a PowerCLI Datastore object + + PSObject + + PSObject + + + + + + + + + + + System.Management.Automation.PSObject + + + + + + + + + + + + + System.Object + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + + PS C:\> + + Get-VmfsDatastoreIncrease -Datastore MyDS + + The exmaple will list all Expand and Extend options available for the Datastore, named MyDS + + + + -------------------------- EXAMPLE 2 -------------------------- + + PS C:\> + + Get-Datastore -Name MyDS* | Get-VmfsDatastoreIncrease + + The Expand and Extend options for all Datastore retruned by the PowerCLI Get-Datastore will be returned. + + + + + + + + New-VmfsDatastoreIncrease + + Increase the capacity of a Datastore + + + + + New + VmfsDatastoreIncrease + + + + The capacity of the Datastore in increased through an Expand or an Extend. +To allow successful completion there shall be free capacity on one of the Extents, or there shall be free LUNs available. +With the Expand or Extend switches the caller selects which type of capacity increase is used. + + + + + New-VmfsDatastoreIncrease + + Datastore + + The name of the Datastore or a PowerCLI Datastore object + + PSObject + + + + + CanonicalName + + The Canonical name of the LUN on which to create a new Extent, or the name of the LUN on which to apply the Expansion. +If this parameter is not provided, the function will sort the available LUN alphanumerically on the Canonical names and slect the first one. + + String + + + + + IncreaseSizeGB + + The amount of GB by which to increase the size of the Datastore. +If this parameter is not used, all of the available Expand or Extend diskspace will be used. + + Int32 + + + + + Expand + + A switch to indicate if the Datastore shall be Expanded + + SwitchParameter + + + + + + New-VmfsDatastoreIncrease + + Datastore + + The name of the Datastore or a PowerCLI Datastore object + + PSObject + + + + + CanonicalName + + The Canonical name of the LUN on which to create a new Extent, or the name of the LUN on which to apply the Expansion. +If this parameter is not provided, the function will sort the available LUN alphanumerically on the Canonical names and slect the first one. + + String + + + + + IncreaseSizeGB + + The amount of GB by which to increase the size of the Datastore. +If this parameter is not used, all of the available Expand or Extend diskspace will be used. + + Int32 + + + + + Extend + + A switch to indicate if the Datastore shall be Extended + + SwitchParameter + + + + + + + + + Datastore + + The name of the Datastore or a PowerCLI Datastore object + + PSObject + + PSObject + + + + + + + IncreaseSizeGB + + The amount of GB by which to increase the size of the Datastore. +If this parameter is not used, all of the available Expand or Extend diskspace will be used. + + Int32 + + Int32 + + + + + + + CanonicalName + + The Canonical name of the LUN on which to create a new Extent, or the name of the LUN on which to apply the Expansion. +If this parameter is not provided, the function will sort the available LUN alphanumerically on the Canonical names and slect the first one. + + String + + String + + + + + + + Expand + + A switch to indicate if the Datastore shall be Expanded + + SwitchParameter + + SwitchParameter + + + + + + + Extend + + A switch to indicate if the Datastore shall be Extended + + SwitchParameter + + SwitchParameter + + + + + + + + + + + System.Management.Automation.PSObject + + + + + + + + + + + + + System.Object + + + + + + + + + + + -------------------------- EXAMPLE 1 -------------------------- + + PS C:\> + + New-VmfsDatastoreIncrease -Datastore MyDS -Expand + + The capacity of the Datastore, named MyDS, will be Expanded with all available free space on the first extent of the Datastore. + + + + -------------------------- EXAMPLE 2 -------------------------- + + PS C:\> + + New-VmfsDatastoreIncrease -Name MyDS -Expand -IncreaseSizeGB 25 + + The capacity of the Datastore, named MyDS, will be Expanded with 25GB on the first extent of the Datastore. +Provided if course, this amount of free space is available. + + + + -------------------------- EXAMPLE 3 -------------------------- + + PS C:\> + + New-VmfsDatastoreIncrease -Datastore 'TestDS' -Expand -IncreaseSizeGB 15 -CanonicalName 'naa.600507680180732f1800000000000011' + + The capacity of the Datastore MyDS will be increased with 15GB on the extent with the Canonicalname naa.600507680180732f1800000000000011 + + + + -------------------------- EXAMPLE 4 -------------------------- + + PS C:\> + + New-VmfsDatastoreIncrease -Datastore MyDS -Expand -CanonicalName 'naa.600507680180732f1800000000000012' + + The capacity of the Datastore MyDS will be increased with all available free space on the extent with the Canonicalname naa.600507680180732f1800000000000012 + + + + -------------------------- EXAMPLE 5 -------------------------- + + PS C:\> + + New-VmfsDatastoreIncrease -Datastore MyDS -Extend + + A new Extent will be added to Datastore MyDS. +All available free space of the LUN will be allocated. +The available LUNs are ordered alphanumerically by their Canonicalname, and the first LUN is used. + + + + -------------------------- EXAMPLE 6 -------------------------- + + PS C:\> + + Get-Datastore -Name MyDS | New-VmfsDatastoreIncrease -Extend -IncreaseSizeGB 50 + + The capacity of the Datastore returned by the PowerCLI Get-Datastore cmdlet will be increased by 50GB. +This is done by adding a new Extent to the Datastore. +The available LUNs are ordered alphanumerically by their Canonicalname, and the first LUN is used. + + + + + + \ No newline at end of file From 48c4839be314f9c138d2e369b08c850afbafe736 Mon Sep 17 00:00:00 2001 From: aaronwsmith Date: Wed, 10 Aug 2016 14:43:20 -0500 Subject: [PATCH 07/20] VM-Snapshot-Report.ps1, Version 1.0 Ready for merge if accepted. PowerActions Report Script that reports on VMs with snapshots along with their description, size of the snapshot in GB, the VM's provisioned vs. used space in GB, if the snapshot is the current one being used, its parent snapshot (if there is one), and the Power state of the VM itself. 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. --- PowerActions/VM-Snapshot-Report.ps1 | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 PowerActions/VM-Snapshot-Report.ps1 diff --git a/PowerActions/VM-Snapshot-Report.ps1 b/PowerActions/VM-Snapshot-Report.ps1 new file mode 100644 index 0000000..89f5453 --- /dev/null +++ b/PowerActions/VM-Snapshot-Report.ps1 @@ -0,0 +1,46 @@ +<# +.MYNGC_REPORT +KEY\(VM\) +.LABEL +VM Snapshot Report +.DESCRIPTION +PowerActions Report Script that reports on VMs with snapshots along with their description, size of the snapshot in GB, the VM's provisioned vs. used space in GB, +if the snapshot is the current one being used, its parent snapshot (if there is one), and the Power state of the VM itself. 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. Version 1.0, written by Aaron Smith (@awsmith99), +published 08/10/2016. +#> + +param +( + [Parameter(Mandatory=$true)] + [VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster] + $vParam +); + +[Array] $vmList = @( Get-VM -Location $vParam | Sort Name ); + +foreach ( $vmItem in $vmList ) +{ + [Array] $vmSnapshotList = @( Get-Snapshot -VM $vmItem ); + + foreach ( $snapshotItem in $vmSnapshotList ) + { + $vmProvisionedSpaceGB = [Math]::Round( $vmItem.ProvisionedSpaceGB, 2 ); + $vmUsedSpaceGB = [Math]::Round( $vmItem.UsedSpaceGB, 2 ); + $snapshotSizeGB = [Math]::Round( $snapshotItem.SizeGB, 2 ); + + $output = New-Object -TypeName PSObject; + + $output | Add-Member -MemberType NoteProperty -Name "VM" -Value $vmItem; + $output | Add-Member -MemberType NoteProperty -Name "Name" -Value $snapshotItem.Name; + $output | Add-Member -MemberType NoteProperty -Name "Description" -Value $snapshotItem.Description; + $output | Add-Member -MemberType NoteProperty -Name "ParentSnapshot" -Value $snapshotItem.ParentSnapshot.Name; + $output | Add-Member -MemberType NoteProperty -Name "IsCurrentSnapshot" -Value $snapshotItem.IsCurrent; + $output | Add-Member -MemberType NoteProperty -Name "SnapshotSizeGB" -Value $snapshotSizeGB; + $output | Add-Member -MemberType NoteProperty -Name "ProvisionedSpaceGB" -Value $vmProvisionedSpaceGB; + $output | Add-Member -MemberType NoteProperty -Name "UsedSpaceGB" -Value $vmUsedSpaceGB; + $output | Add-Member -MemberType NoteProperty -Name "PowerState" -Value $snapshotItem.PowerState; + + $output; + } +} \ No newline at end of file From 067de29b3054eda53eeab61ae73ba00897ee5263 Mon Sep 17 00:00:00 2001 From: aaronwsmith Date: Wed, 10 Aug 2016 15:06:27 -0500 Subject: [PATCH 08/20] VM-Snapshot-Report.ps1 Ready for merge if approved ... added date created and calculated age in days for the snapshot as additional columns in the report. --- PowerActions/VM-Snapshot-Report.ps1 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/PowerActions/VM-Snapshot-Report.ps1 b/PowerActions/VM-Snapshot-Report.ps1 index 89f5453..cad9312 100644 --- a/PowerActions/VM-Snapshot-Report.ps1 +++ b/PowerActions/VM-Snapshot-Report.ps1 @@ -4,10 +4,10 @@ KEY\(VM\) .LABEL VM Snapshot Report .DESCRIPTION -PowerActions Report Script that reports on VMs with snapshots along with their description, size of the snapshot in GB, the VM's provisioned vs. used space in GB, -if the snapshot is the current one being used, its parent snapshot (if there is one), and the Power state of the VM itself. 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. Version 1.0, written by Aaron Smith (@awsmith99), -published 08/10/2016. +PowerActions Report Script that reports on VMs with snapshots along with their description, date of the snapshot, age in days of the snapshot, size of the snapshot in GB, +the VM's provisioned vs. used space in GB, if the snapshot is the current one being used, its parent snapshot (if there is one), and the Power state of the VM itself. 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. Version 1.0, written +by Aaron Smith (@awsmith99), published 08/10/2016. #> param @@ -28,12 +28,15 @@ foreach ( $vmItem in $vmList ) $vmProvisionedSpaceGB = [Math]::Round( $vmItem.ProvisionedSpaceGB, 2 ); $vmUsedSpaceGB = [Math]::Round( $vmItem.UsedSpaceGB, 2 ); $snapshotSizeGB = [Math]::Round( $snapshotItem.SizeGB, 2 ); + $snapshotAgeDays = ((Get-Date) - $snapshotItem.Created).Days; $output = New-Object -TypeName PSObject; $output | Add-Member -MemberType NoteProperty -Name "VM" -Value $vmItem; $output | Add-Member -MemberType NoteProperty -Name "Name" -Value $snapshotItem.Name; $output | Add-Member -MemberType NoteProperty -Name "Description" -Value $snapshotItem.Description; + $output | Add-Member -MemberType NoteProperty -Name "Created" -Value $snapshotItem.Created; + $output | Add-Member -MemberType NoteProperty -Name "AgeDays" -Value $snapshotAgeDays; $output | Add-Member -MemberType NoteProperty -Name "ParentSnapshot" -Value $snapshotItem.ParentSnapshot.Name; $output | Add-Member -MemberType NoteProperty -Name "IsCurrentSnapshot" -Value $snapshotItem.IsCurrent; $output | Add-Member -MemberType NoteProperty -Name "SnapshotSizeGB" -Value $snapshotSizeGB; From 19ff0ea26ac8513b1582dcb5b7fd4ff0fd5ca877 Mon Sep 17 00:00:00 2001 From: equelin Date: Tue, 11 Oct 2016 16:50:15 +0200 Subject: [PATCH 09/20] Add enhancements to module VMCPFunctions --- Modules/VMCPFunctions.psm1 | 400 +++++++++++++++++++++---------------- 1 file changed, 233 insertions(+), 167 deletions(-) diff --git a/Modules/VMCPFunctions.psm1 b/Modules/VMCPFunctions.psm1 index ada8b23..e90174f 100644 --- a/Modules/VMCPFunctions.psm1 +++ b/Modules/VMCPFunctions.psm1 @@ -7,58 +7,90 @@ Twitter: @vBrianGraf VMware Blog: blogs.vmware.com/powercli Personal Blog: www.vtagion.com + + Modified on: 10/11/2016 + Modified by: Erwan Quélin + Twitter: @erwanquelin + Github: https://github.com/equelin =========================================================================== .DESCRIPTION - This function will allow users to view the VMCP settings for their clusters + This function will allow users to view the VMCP settings for their clusters - .Example - # This will show you the VMCP settings of your cluster + .PARAMETER Cluster + Cluster Name or Object + + .PARAMETER Server + vCenter server object + + .EXAMPLE + Get-VMCPSettings + + This will show you the VMCP settings for all the clusters + + .EXAMPLE Get-VMCPSettings -cluster LAB-CL - .Example - # This will show you the VMCP settings of your cluster - Get-VMCPSettings -cluster (Get-Cluster Lab-CL) + This will show you the VMCP settings of your cluster + + .EXAMPLE + Get-VMCPSettings -cluster (Get-Cluster Lab-CL) + + This will show you the VMCP settings of your cluster + + .EXAMPLE + Get-Cluster | Get-VMCPSettings + + This will show you the VMCP settings for all the clusters #> -[CmdletBinding()] - param - ( - [Parameter(Mandatory=$True, - ValueFromPipeline=$True, - ValueFromPipelineByPropertyName=$True, - HelpMessage='What is the Cluster Name?')] - $cluster - ) - Begin { - # Determine input and convert to ClusterImpl object - Switch ($cluster.GetType().Name) - { - "string" {$CL = Get-Cluster $cluster} - "ClusterImpl" {$CL = $cluster} + [CmdletBinding()] + param + ( + [Parameter(Mandatory=$False, + ValueFromPipeline=$True, + ValueFromPipelineByPropertyName=$True, + HelpMessage='What is the Cluster Name?')] + $cluster = (Get-Cluster -Server $Server), + + [Parameter(Mandatory=$False)] + [VMware.VimAutomation.Types.VIServer[]]$Server = $global:DefaultVIServers + ) + + Process { + + Foreach ($Clus in $Cluster) { + + Write-Verbose "Processing Cluster $($Clus.Name)" + + # Determine input and convert to ClusterImpl object + Switch ($Clus.GetType().Name) + { + "string" {$CL = Get-Cluster $Clus -Server $Server -ErrorAction SilentlyContinue} + "ClusterImpl" {$CL = $Clus} + } + + If ($CL) { + # Work with the Cluster View + $ClusterMod = Get-View -Id "ClusterComputeResource-$($CL.ExtensionData.MoRef.Value)" -Server $Server + + # Create Hashtable with desired properties to return + $properties = [ordered]@{ + 'Cluster' = $ClusterMod.Name; + 'VMCP Status' = $clustermod.Configuration.DasConfig.VmComponentProtecting; + 'Protection For APD' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForAPD; + 'APD Timeout Enabled' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.EnableAPDTimeoutForHosts; + 'APD Timeout (Seconds)' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmTerminateDelayForAPDSec; + 'Reaction on APD Cleared' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmReactionOnAPDCleared; + 'Protection For PDL' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForPDL + } + + # Create PSObject with the Hashtable + $object = New-Object -TypeName PSObject -Prop $properties + + # Show object + $object + } } - } - Process { - # Work with the Cluster View - $ClusterMod = Get-View -Id "ClusterComputeResource-$($cl.ExtensionData.MoRef.Value)" - - # Create Hashtable with desired properties to return - $properties = [ordered]@{ - 'Cluster' = $ClusterMod.Name; - 'VMCP Status' = $clustermod.Configuration.DasConfig.VmComponentProtecting; - 'Protection For APD' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForAPD; - 'APD Timeout Enabled' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.EnableAPDTimeoutForHosts; - 'APD Timeout (Seconds)' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmTerminateDelayForAPDSec; - 'Reaction on APD Cleared' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmReactionOnAPDCleared; - 'Protection For PDL' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForPDL - } - - # Create PSObject with the Hashtable - $object = New-Object -TypeName PSObject -Prop $properties - - # Show object - return $object - } - End {} - + } } function Set-VMCPSettings { @@ -70,151 +102,185 @@ function Set-VMCPSettings { Twitter: @vBrianGraf VMware Blog: blogs.vmware.com/powercli Personal Blog: www.vtagion.com + + Modified on: 10/11/2016 + Modified by: Erwan Quélin + Twitter: @erwanquelin + Github: https://github.com/equelin =========================================================================== .DESCRIPTION - This function will allow users to enable/disable VMCP and also allow + This function will allow users to enable/disable VMCP and also allow them to configure the additional VMCP settings For each parameter, users should use the 'Tab' button to auto-fill the possible values. - .Example - # This will enable VMCP and configure the Settings + .PARAMETER Cluster + Cluster Name or Object + + .PARAMETER enableVMCP + Enable or disable VMCP + + .PARAMETER VmStorageProtectionForPDL + VM Storage Protection for PDL settings. Might be: + - disabled + - warning + - restartAggressive + + .PARAMETER VmStorageProtectionForAPD + VM Storage Protection for APD settings. Might be: + - disabled + - restartConservative + - restartAggressive + - warning + + .PARAMETER VmTerminateDelayForAPDSec + VM Terminate Delay for APD (seconds). + + .PARAMETER VmReactionOnAPDCleared + VM reaction on APD Cleared. Might be: + - reset + - none + + .PARAMETER Server + vCenter server object + + .EXAMPLE Set-VMCPSettings -cluster LAB-CL -enableVMCP:$True -VmStorageProtectionForPDL ` restartAggressive -VmStorageProtectionForAPD restartAggressive ` -VmTerminateDelayForAPDSec 2000 -VmReactionOnAPDCleared reset - .Example - # This will disable VMCP and configure the Settings + This will enable VMCP and configure the Settings on cluster LAB-CL + + .EXAMPLE Set-VMCPSettings -cluster LAB-CL -enableVMCP:$False -VmStorageProtectionForPDL ` disabled -VmStorageProtectionForAPD disabled ` -VmTerminateDelayForAPDSec 600 -VmReactionOnAPDCleared none + + This will disable VMCP and configure the Settings on cluster LAB-CL + + .EXAMPLE + Set-VMCPSettings -enableVMCP:$False -VmStorageProtectionForPDL ` + disabled -VmStorageProtectionForAPD disabled ` + -VmTerminateDelayForAPDSec 600 -VmReactionOnAPDCleared none + + This will disable VMCP and configure the Settings on all clusters available #> - [CmdletBinding()] - param - ( - [Parameter(Mandatory=$True, - ValueFromPipeline=$True, - ValueFromPipelineByPropertyName=$True, - HelpMessage='What is the Cluster Name?')] - $cluster, - - [Parameter(Mandatory=$True, - ValueFromPipeline=$False, - HelpMessage='True=Enabled False=Disabled')] - [switch]$enableVMCP, + [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High")] + param + ( + [Parameter(Mandatory=$True, + ValueFromPipeline=$True, + ValueFromPipelineByPropertyName=$True, + HelpMessage='What is the Cluster Name?')] + $cluster= (Get-Cluster -Server $Server), + + [Parameter(Mandatory=$True, + ValueFromPipeline=$False, + HelpMessage='True=Enabled False=Disabled')] + [switch]$enableVMCP, - [Parameter(Mandatory=$True, - ValueFromPipeline=$False, - HelpMessage='Actions that can be taken in response to a PDL event')] - [ValidateSet("disabled","warning","restartAggressive")] - [string]$VmStorageProtectionForPDL, - - [Parameter(Mandatory=$True, - ValueFromPipeline=$False, - HelpMessage='Options available for an APD response')] - [ValidateSet("disabled","restartConservative","restartAggressive","warning")] - [string]$VmStorageProtectionForAPD, - - [Parameter(Mandatory=$True, - ValueFromPipeline=$False, - HelpMessage='Value in seconds')] - [Int]$VmTerminateDelayForAPDSec, - - [Parameter(Mandatory=$True, - ValueFromPipeline=$False, - HelpMessage='This setting will instruct vSphere HA to take a certain action if an APD event is cleared')] - [ValidateSet("reset","none")] - [string]$VmReactionOnAPDCleared + [Parameter(Mandatory=$True, + ValueFromPipeline=$False, + HelpMessage='Actions that can be taken in response to a PDL event')] + [ValidateSet("disabled","warning","restartAggressive")] + [string]$VmStorageProtectionForPDL, + + [Parameter(Mandatory=$True, + ValueFromPipeline=$False, + HelpMessage='Options available for an APD response')] + [ValidateSet("disabled","restartConservative","restartAggressive","warning")] + [string]$VmStorageProtectionForAPD, + + [Parameter(Mandatory=$True, + ValueFromPipeline=$False, + HelpMessage='Value in seconds')] + [Int]$VmTerminateDelayForAPDSec, + + [Parameter(Mandatory=$True, + ValueFromPipeline=$False, + HelpMessage='This setting will instruct vSphere HA to take a certain action if an APD event is cleared')] + [ValidateSet("reset","none")] + [string]$VmReactionOnAPDCleared, + + [Parameter(Mandatory=$False)] + [VMware.VimAutomation.Types.VIServer[]]$Server = $global:DefaultVIServers + ) - ) -Begin{ + Process { - # Determine input and convert to ClusterImpl object - Switch ($cluster.GetType().Name) - { - "string" {$CL = Get-Cluster $cluster} - "ClusterImpl" {$CL = $cluster} - } -} -Process{ - # Create the object we will configure - $settings = New-Object VMware.Vim.ClusterConfigSpecEx - $settings.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo - - # Based on $enableVMCP switch - if ($enableVMCP -eq $false) { - $settings.dasConfig.vmComponentProtecting = "disabled" - } - elseif ($enableVMCP -eq $true) { - $settings.dasConfig.vmComponentProtecting = "enabled" - } + Foreach ($Clus in $Cluster) { - #Create the VMCP object to work with - $settings.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings - - #Storage Protection For PDL - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = "$VmStorageProtectionForPDL" - - #Storage Protection for APD - switch ($VmStorageProtectionForAPD) { - "disabled" { - # If Disabled, there is no need to set the Timeout Value - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'disabled' - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false - } - - "restartConservative" { - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartConservative' - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec - } - - "restartAggressive" { - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartAggressive' - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec - } - - "warning" { - # If Warning, there is no need to set the Timeout Value - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'warning' - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false - } + Write-Verbose "Processing Cluster $Clus" + # Determine input and convert to ClusterImpl object + Switch ($Clus.GetType().Name) + { + "string" {$CL = Get-Cluster $Clus -Server $Server -ErrorAction SilentlyContinue} + "ClusterImpl" {$CL = $Clus} } - - # Reaction On APD Cleared - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = "$VmReactionOnAPDCleared" - # Execute API Call - $modify = $true - $ClusterMod = Get-View -Id "ClusterComputeResource-$($cl.ExtensionData.MoRef.Value)" - $ClusterMod.ReconfigureComputeResource_Task($settings, $modify) | out-null - + If ($CL) { + # Create the object we will configure + $settings = New-Object VMware.Vim.ClusterConfigSpecEx + $settings.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo + + # Based on $enableVMCP switch + if ($enableVMCP -eq $false) { + $settings.dasConfig.vmComponentProtecting = "disabled" + } + elseif ($enableVMCP -eq $true) { + $settings.dasConfig.vmComponentProtecting = "enabled" + } + #Create the VMCP object to work with + $settings.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings -} -End{ - # Update variable data after API call - $ClusterMod.updateViewData() + #Storage Protection For PDL + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = "$VmStorageProtectionForPDL" - # Create Hashtable with desired properties to return - $properties = [ordered]@{ - 'Cluster' = $ClusterMod.Name; - 'VMCP Status' = $clustermod.Configuration.DasConfig.VmComponentProtecting; - 'Protection For APD' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForAPD; - 'APD Timeout Enabled' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.EnableAPDTimeoutForHosts; - 'APD Timeout (Seconds)' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmTerminateDelayForAPDSec; - 'Reaction on APD Cleared' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmReactionOnAPDCleared; - 'Protection For PDL' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForPDL + #Storage Protection for APD + switch ($VmStorageProtectionForAPD) { + "disabled" { + # If Disabled, there is no need to set the Timeout Value + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'disabled' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false + } + + "restartConservative" { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartConservative' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec + } + + "restartAggressive" { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartAggressive' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec + } + + "warning" { + # If Warning, there is no need to set the Timeout Value + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'warning' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false + } + + } + + # Reaction On APD Cleared + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = "$VmReactionOnAPDCleared" + + # Execute API Call + $modify = $true + $ClusterMod = Get-View -Id "ClusterComputeResource-$($CL.ExtensionData.MoRef.Value)" -Server $Server + + If ($pscmdlet.ShouldProcess($CL.Name,"Modify VMCP configuration")) { + $ClusterMod.ReconfigureComputeResource_Task($settings, $modify) | out-null + } + + # Show result + Get-VMCPSettings -Cluster $CL -Server $Server + } + } } - - # Create PSObject with the Hashtable - $object = New-Object -TypeName PSObject -Prop $properties - - # Show object - return $object - -} } From 4b8e5dc46ff6c1171ed761a898cce14392cf42c3 Mon Sep 17 00:00:00 2001 From: equelin Date: Tue, 11 Oct 2016 16:56:31 +0200 Subject: [PATCH 10/20] Fix bug in Set-VMCPSettings --- Modules/VMCPFunctions.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMCPFunctions.psm1 b/Modules/VMCPFunctions.psm1 index e90174f..34382e2 100644 --- a/Modules/VMCPFunctions.psm1 +++ b/Modules/VMCPFunctions.psm1 @@ -168,7 +168,7 @@ function Set-VMCPSettings { [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High")] param ( - [Parameter(Mandatory=$True, + [Parameter(Mandatory=$false, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='What is the Cluster Name?')] From 2a96855d030efdb3ce5ddd12e5133305af776fe2 Mon Sep 17 00:00:00 2001 From: equelin Date: Mon, 14 Nov 2016 17:22:13 +0100 Subject: [PATCH 11/20] Cluster need to be provided by the user + No need anymore to provide all parameters + Add timer to wait the end of the execution of the reconfiguration task before showing the result --- Modules/VMCPFunctions.psm1 | 120 ++++++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 42 deletions(-) diff --git a/Modules/VMCPFunctions.psm1 b/Modules/VMCPFunctions.psm1 index 34382e2..921e8e4 100644 --- a/Modules/VMCPFunctions.psm1 +++ b/Modules/VMCPFunctions.psm1 @@ -168,35 +168,35 @@ function Set-VMCPSettings { [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High")] param ( - [Parameter(Mandatory=$false, + [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='What is the Cluster Name?')] - $cluster= (Get-Cluster -Server $Server), + $cluster, - [Parameter(Mandatory=$True, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, - HelpMessage='True=Enabled False=Disabled')] - [switch]$enableVMCP, + HelpMessage='$True=Enabled $False=Disabled')] + [bool]$enableVMCP, - [Parameter(Mandatory=$True, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='Actions that can be taken in response to a PDL event')] [ValidateSet("disabled","warning","restartAggressive")] [string]$VmStorageProtectionForPDL, - [Parameter(Mandatory=$True, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='Options available for an APD response')] [ValidateSet("disabled","restartConservative","restartAggressive","warning")] [string]$VmStorageProtectionForAPD, - [Parameter(Mandatory=$True, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='Value in seconds')] [Int]$VmTerminateDelayForAPDSec, - [Parameter(Mandatory=$True, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, HelpMessage='This setting will instruct vSphere HA to take a certain action if an APD event is cleared')] [ValidateSet("reset","none")] @@ -217,9 +217,18 @@ function Set-VMCPSettings { { "string" {$CL = Get-Cluster $Clus -Server $Server -ErrorAction SilentlyContinue} "ClusterImpl" {$CL = $Clus} + default {Throw 'Please provide a cluster name or object'} } If ($CL) { + + # Get the actual configuration of the Cluster + $ActualSettings = Get-VMCPSettings -Cluster $CL -Server $Server + + # Show actual settings in the verbose mode + Write-Verbose "[$($CL.Name)] Actual VMCP settings " + Write-Verbose $ActualSettings + # Create the object we will configure $settings = New-Object VMware.Vim.ClusterConfigSpecEx $settings.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo @@ -237,49 +246,76 @@ function Set-VMCPSettings { $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings #Storage Protection For PDL - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = "$VmStorageProtectionForPDL" + If ($PSBoundParameters.ContainsKey('VmStorageProtectionForPDL')) { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = $VmStorageProtectionForPDL + } else { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = $ActualSettings.'Protection For PDL' + } #Storage Protection for APD - switch ($VmStorageProtectionForAPD) { - "disabled" { - # If Disabled, there is no need to set the Timeout Value - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'disabled' - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false - } - - "restartConservative" { - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartConservative' - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec - } - - "restartAggressive" { - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartAggressive' - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec - } - - "warning" { - # If Warning, there is no need to set the Timeout Value - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'warning' - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false - } - + If ($PSBoundParameters.ContainsKey('VmStorageProtectionForAPD')) { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $VmStorageProtectionForAPD + } else { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $ActualSettings.'Protection For APD' } + #Storage Protection for APD + If ($PSBoundParameters.ContainsKey('VmStorageProtectionForAPD')) { + switch ($VmStorageProtectionForAPD) { + "disabled" { + # If Disabled, there is no need to set enable Timeout Value + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'disabled' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false + } + + "restartConservative" { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartConservative' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true + } + + "restartAggressive" { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartAggressive' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true + } + + "warning" { + # If Warning, there is no need to enable the Timeout Value + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'warning' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false + } + } + } else { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $ActualSettings.'Protection For APD' + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $ActualSettings.'APD Timeout Enabled' + } + + #APD Timeout Enabled + If ($PSBoundParameters.ContainsKey('VmTerminateDelayForAPDSec')) { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec + } else { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $ActualSettings.'APD Timeout (Seconds)' + } + # Reaction On APD Cleared - $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = "$VmReactionOnAPDCleared" + If ($PSBoundParameters.ContainsKey('VmReactionOnAPDCleared')) { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = "$VmReactionOnAPDCleared" + } else { + $settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = $ActualSettings.'Reaction on APD Cleared' + } # Execute API Call - $modify = $true - $ClusterMod = Get-View -Id "ClusterComputeResource-$($CL.ExtensionData.MoRef.Value)" -Server $Server - If ($pscmdlet.ShouldProcess($CL.Name,"Modify VMCP configuration")) { - $ClusterMod.ReconfigureComputeResource_Task($settings, $modify) | out-null + $modify = $true + $ClusterMod = Get-View -Id "ClusterComputeResource-$($CL.ExtensionData.MoRef.Value)" -Server $Server + $Task = $ClusterMod.ReconfigureComputeResource_Task($settings, $modify) } - # Show result - Get-VMCPSettings -Cluster $CL -Server $Server + # Wait for the reconfiguration task to finish to show the result + If ($Task) { + $TaskID = "Task-" + $($Task.Value) + Get-Task -Id $TaskID | Wait-Task | Out-Null + Get-VMCPSettings -Cluster $CL -Server $Server + } } } } From 758b80f6b8f3eaefe2522b4775d1e07782ded7b2 Mon Sep 17 00:00:00 2001 From: equelin Date: Mon, 14 Nov 2016 17:39:32 +0100 Subject: [PATCH 12/20] -server parameter was missing for the wait-task function --- Modules/VMCPFunctions.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/VMCPFunctions.psm1 b/Modules/VMCPFunctions.psm1 index 921e8e4..4f9b16e 100644 --- a/Modules/VMCPFunctions.psm1 +++ b/Modules/VMCPFunctions.psm1 @@ -313,7 +313,7 @@ function Set-VMCPSettings { # Wait for the reconfiguration task to finish to show the result If ($Task) { $TaskID = "Task-" + $($Task.Value) - Get-Task -Id $TaskID | Wait-Task | Out-Null + Get-Task -Id $TaskID -Server $Server | Wait-Task | Out-Null Get-VMCPSettings -Cluster $CL -Server $Server } } From 3c686ecaba0b778caeeaeab349437477ca00f1be Mon Sep 17 00:00:00 2001 From: praveenmathamsetty Date: Tue, 15 Nov 2016 11:25:50 +0530 Subject: [PATCH 13/20] temp temp --- .../New-HVFarm/AutomatedLinkedCloneFarm.json | 80 + .../New-HVFarm/ManualFarm.json | 24 + .../New-HVPool/FullClone.json | 82 + .../New-HVPool/InstantClone.json | 105 + .../New-HVPool/LinkedClone.json | 105 + .../New-HVPool/ManualSpec.json | 35 + .../VMware.Hv.Helper/New-HVPool/RdsSpec.json | 16 + .../Set-HVFarm/AutomatedEditFarm.json | 6 + .../Set-HVFarm/ManualEditFarm.json | 5 + .../Set-HVPool/AutomatedEditPool.Json | 8 + .../Set-HVPool/ManualEditPool.json | 8 + .../Set-HVPool/RdsEditPool.json | 6 + .../VMware.Hv.Helper/VMware.HV.Helper.psd1 | 95 + .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 4743 +++++++++++++++++ 14 files changed, 5318 insertions(+) create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/ManualFarm.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/FullClone.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/InstantClone.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/LinkedClone.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/ManualSpec.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/RdsSpec.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psd1 create mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psm1 diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json new file mode 100644 index 0000000..3706374 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json @@ -0,0 +1,80 @@ +{ + "Type": "AUTOMATED", + "Data": { + "Name": "LCFarmTest", + "DisplayName": "Ankit LC Farm Test", + "AccessGroup": "Root", + "Description": "created LC Farm from PS", + "Enabled": null, + "Deleting": false, + "Settings": null, + "Desktop": null, + "DisplayProtocolSettings": null, + "ServerErrorThreshold": null, + "MirageConfigurationOverrides": null + }, + "AutomatedFarmSpec": { + "ProvisioningType": "VIEW_COMPOSER", + "VirtualCenter": null, + "RdsServerNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "LCFarmVM_PS", + "MaxNumberOfRDSServers": 1 + } + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "ParentVm": "Win_Server_2012_R2", + "Snapshot": "Snap_RDS", + "Datacenter": null, + "VmFolder": "AnkitPoolVM", + "HostOrCluster": "cls", + "ResourcePool": "cls" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "datastore1 (5)", + "StorageOvercommit": "UNBOUNDED" + } + ], + "UseVSan": false, + "ViewComposerStorageSettings": { + "UseSeparateDatastoresReplicaAndOSDisks": false, + "ReplicaDiskDatastore": null, + "UseNativeSnapshots": false, + "SpaceReclamationSettings": { + "ReclaimVmDiskSpace": false, + "ReclamationThresholdGB": null, + "BlackoutTimes": null + } + } + }, + "VirtualCenterNetworkingSettings": { + "Nics": null + } + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + }, + "CustomizationSettings": { + "CustomizationType": "SYS_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "SysprepCustomizationSettings": { + "CustomizationSpec": "RDSH_Cust2" + } + }, + "RdsServerMaxSessionsData": { + "MaxSessionsType": "UNLIMITED", + "MaxSessions": null + } + }, + "ManualFarmSpec": null, + "NetBiosName" : "adankit" +} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/ManualFarm.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/ManualFarm.json new file mode 100644 index 0000000..cf674c1 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/ManualFarm.json @@ -0,0 +1,24 @@ +{ + "Type": "MANUAL", + "Data": { + "Name": "manualFarmTest", + "DisplayName": "manualFarmTest", + "AccessGroup": "Root", + "Description": "Manual PS Test", + "Enabled": null, + "Deleting": false, + "Settings": null, + "Desktop": null, + "DisplayProtocolSettings": null, + "ServerErrorThreshold": null, + "MirageConfigurationOverrides": null + }, + "AutomatedFarmSpec": null, + "ManualFarmSpec": { + "RdsServers": [ + { + "rdsServer": "WIN-ORKA1Q8B0P7" + } + ] + } +} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/FullClone.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/FullClone.json new file mode 100644 index 0000000..2ae9539 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/FullClone.json @@ -0,0 +1,82 @@ +{ + "Base": { + "Name" : "FulClnJSON", + "DisplayName": "FullClonePraJSON", + "AccessGroup": "Root", + "Description": "create full clone via JSON" + }, + "DesktopSettings": null, + "Type": "AUTOMATED", + "AutomatedDesktopSpec": { + "ProvisioningType": "VIRTUAL_CENTER", + "VirtualCenter": null, + "UserAssignment": { + "UserAssignment": "DEDICATED", + "AutomaticAssignment": true + }, + "VmNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "FullClnJson1", + "MaxNumberOfMachines": 1, + "NumberOfSpareMachines": 1, + "ProvisioningTime": "UP_FRONT", + "MinNumberOfMachines": null + }, + "SpecificNamingSpec": null + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "Template": "powerCLI-VM-TEMPLATE", + "ParentVm": null, + "Snapshot": null, + "Datacenter": null, + "VmFolder": "Praveen", + "HostOrCluster": "CS-1", + "ResourcePool": "CS-1" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "datastore1", + "StorageOvercommit": "UNBOUNDED" + } + ], + "UseVSan": false, + "ViewComposerStorageSettings": null, + "ViewStorageAcceleratorSettings": { + "UseViewStorageAccelerator": false, + "ViewComposerDiskTypes": null, + "RegenerateViewStorageAcceleratorDays": null, + "BlackoutTimes": null + } + }, + "VirtualCenterNetworkingSettings": { + "Nics": null + } + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + }, + "CustomizationSettings": { + "CustomizationType": "SYS_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "NoCustomizationSettings": { + "DoNotPowerOnVMsAfterCreation": false + }, + "SysprepCustomizationSettings": null, + "QuickprepCustomizationSettings": null, + "CloneprepCustomizationSettings": null + } + }, + "ManualDesktopSpec": null, + "RdsDesktopSpec": null, + "GlobalEntitlementData": null, + "NetBiosName" : "adviewdev", + "SysPrepName" : "praveencust" +} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/InstantClone.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/InstantClone.json new file mode 100644 index 0000000..a8da482 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/InstantClone.json @@ -0,0 +1,105 @@ +{ + "Base": { + "Name" : "InsClnJSON", + "DisplayName": "insPoolPr", + "AccessGroup": "ROOT", + "Description": "create instant pool" + }, + "DesktopSettings": null, + "Type": "AUTOMATED", + "AutomatedDesktopSpec": { + "ProvisioningType": "INSTANT_CLONE_ENGINE", + "VirtualCenter": null, + "UserAssignment": { + "UserAssignment": "FLOATING", + "AutomaticAssignment": true + }, + "VmNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "inspoolJson1", + "MaxNumberOfMachines": 1, + "NumberOfSpareMachines": 1, + "ProvisioningTime": "UP_FRONT", + "MinNumberOfMachines": null + }, + "SpecificNamingSpec": null + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "Template": null, + "ParentVm": "Agent_pra", + "Snapshot": "kb-hotfix", + "Datacenter": null, + "VmFolder": "Praveen", + "HostOrCluster": "CS-1", + "ResourcePool": "CS-1" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "datastore1", + "StorageOvercommit": "UNBOUNDED" + } + ], + "UseVSan": false, + "ViewComposerStorageSettings": { + "UseSeparateDatastoresReplicaAndOSDisks": false, + "ReplicaDiskDatastore": null, + "UseNativeSnapshots": false, + "SpaceReclamationSettings": { + "ReclaimVmDiskSpace": false, + "ReclamationThresholdGB": null + }, + "PersistentDiskSettings": { + "RedirectWindowsProfile": false, + "UseSeparateDatastoresPersistentAndOSDisks": null, + "PersistentDiskDatastores": null, + "DiskSizeMB": null, + "DiskDriveLetter": null + }, + "NonPersistentDiskSettings": { + "RedirectDisposableFiles": false, + "DiskSizeMB": null, + "DiskDriveLetter": null + } + }, + "ViewStorageAcceleratorSettings": { + "UseViewStorageAccelerator": false, + "ViewComposerDiskTypes": null, + "RegenerateViewStorageAcceleratorDays": null, + "BlackoutTimes": null + } + }, + "VirtualCenterNetworkingSettings": { + "Nics": null + } + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + }, + "CustomizationSettings": { + "CustomizationType": "CLONE_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "NoCustomizationSettings": null, + "SysprepCustomizationSettings": null, + "QuickprepCustomizationSettings": null, + "CloneprepCustomizationSettings": { + "InstantCloneEngineDomainAdministrator": null, + "PowerOffScriptName": null, + "PowerOffScriptParameters": null, + "PostSynchronizationScriptName": null, + "PostSynchronizationScriptParameters": null + } + } + }, + "ManualDesktopSpec": null, + "RdsDesktopSpec": null, + "GlobalEntitlementData": null, + "NetBiosName" : "adviewdev" +} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/LinkedClone.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/LinkedClone.json new file mode 100644 index 0000000..53171a6 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/LinkedClone.json @@ -0,0 +1,105 @@ +{ + "Base": { + "Name" : "LnkClnJSon", + "DisplayName": "praveen linkedclone pool", + "AccessGroup": "Root", + "Description": "created linkedclone pool from ps" + }, + "DesktopSettings": null, + "Type": "AUTOMATED", + "AutomatedDesktopSpec": { + "ProvisioningType": "VIEW_COMPOSER", + "VirtualCenter": null, + "UserAssignment": { + "UserAssignment": "FLOATING", + "AutomaticAssignment": true + }, + "VmNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "patternPra1", + "MaxNumberOfMachines": 1, + "NumberOfSpareMachines": 1, + "ProvisioningTime": "UP_FRONT", + "MinNumberOfMachines": null + }, + "SpecificNamingSpec": null + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "Template": null, + "ParentVm": "Agent_pra", + "Snapshot": "kb-hotfix", + "Datacenter": null, + "VmFolder": "Praveen", + "HostOrCluster": "CS-1", + "ResourcePool": "CS-1" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "datastore1", + "StorageOvercommit": "UNBOUNDED" + } + ], + "UseVSan": false, + "ViewComposerStorageSettings": { + "UseSeparateDatastoresReplicaAndOSDisks": false, + "ReplicaDiskDatastore": null, + "UseNativeSnapshots": false, + "SpaceReclamationSettings": { + "ReclaimVmDiskSpace": false, + "ReclamationThresholdGB": null + }, + "PersistentDiskSettings": { + "RedirectWindowsProfile": false, + "UseSeparateDatastoresPersistentAndOSDisks": null, + "PersistentDiskDatastores": null, + "DiskSizeMB": null, + "DiskDriveLetter": null + }, + "NonPersistentDiskSettings": { + "RedirectDisposableFiles": false, + "DiskSizeMB": null, + "DiskDriveLetter": null + } + }, + "ViewStorageAcceleratorSettings": { + "UseViewStorageAccelerator": false, + "ViewComposerDiskTypes": null, + "RegenerateViewStorageAcceleratorDays": null, + "BlackoutTimes": null + } + }, + "VirtualCenterNetworkingSettings": { + "Nics": null + } + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + }, + "CustomizationSettings": { + "CustomizationType": "QUICK_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "NoCustomizationSettings": null, + "SysprepCustomizationSettings": null, + "QuickprepCustomizationSettings": { + "PowerOffScriptName": null, + "PowerOffScriptParameters": null, + "PostSynchronizationScriptName": null, + "PostSynchronizationScriptParameters": null + }, + "CloneprepCustomizationSettings": null + } + }, + "ManualDesktopSpec": null, + "RdsDesktopSpec": null, + "GlobalEntitlementData": null, + "NetBiosName" : "adviewdev", + "SysPrepName" : "praveencust" +} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/ManualSpec.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/ManualSpec.json new file mode 100644 index 0000000..b302bba --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/ManualSpec.json @@ -0,0 +1,35 @@ +{ + "Base": { + "Name" : "MnlJson", + "DisplayName": "MNLPUL", + "AccessGroup": "ROOT", + "Description": "Manual pool creation" + }, + "DesktopSettings": null, + "Type": "MANUAL", + "AutomatedDesktopSpec": null, + "ManualDesktopSpec": { + "UserAssignment": { + "UserAssignment": "FLOATING", + "AutomaticAssignment": true + }, + "Source": "VIRTUAL_CENTER", + "Machines": [ + { + "Machine" : "PowerCLI-VM" + } + ], + "VirtualCenter": null, + "ViewStorageAcceleratorSettings": { + "UseViewStorageAccelerator": false, + "ViewComposerDiskTypes": null, + "RegenerateViewStorageAcceleratorDays": null, + "BlackoutTimes": null + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + } + }, + "RdsDesktopSpec": null, + "GlobalEntitlementData": null +} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/RdsSpec.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/RdsSpec.json new file mode 100644 index 0000000..86b3571 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/RdsSpec.json @@ -0,0 +1,16 @@ +{ + "Base": { + "Name" : "RdsJson", + "DisplayName": "TestRDSPS", + "AccessGroup": "Root", + "Description": "Testing PS" + }, + "DesktopSettings": null, + "Type": "RDS", + "AutomatedDesktopSpec": null, + "ManualDesktopSpec": null, + "RdsDesktopSpec": { + "Farm": "Farm2" + }, + "GlobalEntitlementData": null +} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json new file mode 100644 index 0000000..cad9343 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json @@ -0,0 +1,6 @@ +{ + "data.description" : "update through edit farm function", + "data.displayName" : "LCFarmTestUpdated1", + "data.displayProtocolSettings.defaultDisplayProtocol" : "PCOIP", + "automatedFarmData.virtualCenterManagedCommonSettings.transparentPageSharingScope" : "FARM" +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json new file mode 100644 index 0000000..533c39f --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json @@ -0,0 +1,5 @@ +{ + "data.description" : "update through edit farm function", + "data.displayName" : "ManualFarmTestUpdated1", + "data.displayProtocolSettings.defaultDisplayProtocol" : "PCOIP" +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json new file mode 100644 index 0000000..9654b14 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json @@ -0,0 +1,8 @@ +{ + "base.description" : "update through edit pool function", + "base.displayName" : "Henry2DspNm", + "desktopSettings.displayProtocolSettings.defaultDisplayProtocol" : "BLAST", + "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.useViewStorageAccelerator" : true, + "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.viewComposerDiskTypes" : "OS_DISKS", + "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.regenerateViewStorageAcceleratorDays" : 8 +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json new file mode 100644 index 0000000..6fc8adc --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json @@ -0,0 +1,8 @@ +{ + "base.description" : "update through edit pool", + "base.displayName" : "pooldisp", + "desktopSettings.displayProtocolSettings.defaultDisplayProtocol" : "BLAST", + "manualDesktopData.viewStorageAcceleratorSettings.useViewStorageAccelerator" : true, + "manualDesktopData.viewStorageAcceleratorSettings.viewComposerDiskTypes" : "OS_DISKS", + "manualDesktopData.viewStorageAcceleratorSettings.regenerateViewStorageAcceleratorDays" : 8 +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json new file mode 100644 index 0000000..58bf859 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json @@ -0,0 +1,6 @@ +{ + "base.description" : "update through edit pool function", + "base.displayName" : "RDS2DspNm", + "desktopSettings.flashSettings.quality" : "LOW", + "desktopSettings.flashSettings.throttling" : "CONSERVATIVE" +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psd1 b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psd1 new file mode 100644 index 0000000..7d9e262 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psd1 @@ -0,0 +1,95 @@ +# +# Module manifest for module 'VMware.HV' +# +# Generated by: "VMware" +# +# Generated on: 9/20/2016 +# + +@{ + +# Script module or binary module file associated with this manifest. +# RootModule = '' + +# Version number of this module. +ModuleVersion = '1.0' + +# ID used to uniquely identify this module +GUID = '6d3f7fb5-4e52-43d8-91e1-f65f72532a1d' + +# Author of this module +Author = 'VMware' + +# Company or vendor of this module +CompanyName = 'VMware, Inc.' + +# Copyright statement for this module +Copyright = 'Copyright (c) 2016 VMware, Inc. All rights reserved.' + +# Description of the functionality provided by this module +# Description = 'This Windows PowerShell script module contains Advanced functions of VIEW API Service.' + +# Minimum version of the Windows PowerShell engine required by this module +# PowerShellVersion = '' + +# 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 the .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 = @('VMware.VimAutomation.HorizonView') + +# 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 = @('VMware.HV.Helper.psm1') + +# 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 = '*' + +# 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 +# PrivateData = '' + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psm1 new file mode 100644 index 0000000..3d533f5 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -0,0 +1,4743 @@ +#Script Module : VMware.Hv.Helper +#Version : 1.0 + +#Copyright 2016 VMware, Inc. All Rights Reserved. + +#Permission is hereby granted, free of charge, to any person obtaining a copy of +#this software and associated documentation files (the "Software"), to deal in +#the Software without restriction, including without limitation the rights to +#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +#of the Software, and to permit persons to whom the Software is furnished to do +#so, subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in all +#copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +#SOFTWARE. + + +function Get_New_Object { + param( + [Parameter(Mandatory = $true)] + [string]$TypeName, + + [Parameter(Mandatory = $false)] + [System.Collections.Hashtable]$PropertyName + ) + $objStr = 'VMware.Hv.' + $typeName + return New-Object $objStr -Property $propertyName +} + +function Get_ViewAPI_Service { + param( + [Parameter(Mandatory = $false)] + $HvServer + ) + if ($null -ne $hvServer) { + if ($hvServer.GetType().name -ne 'ViewServerImpl') { + $type = $hvServer.GetType().name + Write-Error "Expected hvServer type is ViewServerImpl, but received: [$type]" + return $null + } + elseif ($hvServer.IsConnected) { + return $hvServer.ExtensionData + } + } elseif ($global:DefaultHVServers.Length -gt 0) { + if ($pscmdlet.ShouldProcess($global:DefaultHVServers[0].uid,'hvServer not specified, use default hvServer connection?')) { + $hvServer = $global:DefaultHVServers[0] + return $hvServer.ExtensionData + } + } + return $null +} + +function Get_Vcenter_ID { + param( + [Parameter(Mandatory = $true)] + $Services, + + [Parameter(Mandatory = $false)] + [string] + $Vcenter + ) + $vc_service_helper = New-Object VMware.Hv.VirtualCenterService + $vcList = $vc_service_helper.VirtualCenter_List($services) + if ($vCenter) { + #ServerSpec.ServerName is IP/FQDN of the vCenter server. Input vCenter will be IP/FQDN of the vcenter server + $virtualCenterId = ($vcList | Where-Object { $_.ServerSpec.ServerName -eq $vCenter }).id + if ($virtualCenterId.Count -ne 1) { + Write-Error "vCenter Server not found: [$vCenter], please make sure vCenter is added in Connection Server" + return $null + } + } + else { + if ($vcList.Count -ne 1) { + Write-Error "Multiple Vcenter servers found, please specify the vCenter Name" + return $null + } + else { $virtualCenterId = $vcList.id } + } + return $virtualCenterId +} + +function Get_Json_Object { + param( + [Parameter(Mandatory = $true)] + [string]$SpecFile + ) + try { + return Get-Content -Raw $specFile | ConvertFrom-Json + } catch { + throw "Failed to read json file [$specFile], $_" + } +} + +function Get_MapEntry { + param( + [Parameter(Mandatory = $true)] + $Key, + + [Parameter(Mandatory = $true)] + $Value + ) + + $update = New-Object VMware.Hv.MapEntry + $update.key = $key + $update.value = $value + return $update +} + +function Get-RegisteredPhysicalMachines ($Services,$MachinesList) { + [VMware.Hv.MachineId[]]$machines = $null + $query_service_helper = New-Object VMware.Hv.QueryServiceService + foreach ($machineName in $machinesList) { + $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals + $QueryFilterEquals.memberName = 'machineBase.name' + $QueryFilterEquals.value = $machineName + + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'RegisteredPhysicalMachineInfo' + $defn.Filter = $QueryFilterEquals + + $queryResults = $query_service_helper.QueryService_Query($services,$defn) + $res = $queryResults.results + $machines += $res.id + } + return $machines +} + +function Get-RegisteredRDSServers ($Services,$ServerList) { + [VMware.Hv.RDSServerId[]]$servers = $null + $query_service_helper = New-Object VMware.Hv.QueryServiceService + foreach ($serverName in $serverList) { + $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals + $QueryFilterEquals.memberName = 'base.name' + $QueryFilterEquals.value = $serverName + + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'RDSServerInfo' + $defn.Filter = $QueryFilterEquals + + $queryResults = $query_service_helper.QueryService_Query($services,$defn) + + $servers += $queryResults.results.id + } + if ($null -eq $servers) { + throw "No Registered RDS server found with name: [$serverList]" + } + return $servers +} +function Add-HVDesktop { +<# +.SYNOPSIS +Adds virtual machine to existing pool + +.DESCRIPTION +The Add-HVDesktop adds virtual machines to already exiting pools by using view API service object(hvServer) of Connect-HVServer cmdlet. VMs can be added to any of unmanaged manual, managed manual or Specified name. This advanced function do basic checks for pool and view API service connection existance, hvServer object is bound to specific connection server. + +.PARAMETER PoolName + Pool name to which new VMs are to be added. + +.PARAMETER Machines + List of virtual machine names which need to be added to the given pool. + +.PARAMETER Users + List of virtual machine users for given machines. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) of the given pool. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.EXAMPLE + Add managed manual VMs to existing manual pool + Add-HVDesktop -PoolName 'ManualPool' -Machines 'manualPool1', 'manualPool2'. + +.EXAMPLE + Add virtual machines to automated specific named dedicated pool + Add-HVDesktop -PoolName 'SpecificNamed' -Machines 'vm-01', 'vm-02' -Users 'user1', 'user2' + +.EXAMPLE + Add machines to automated specific named Floating pool + Add-HVDesktop -PoolName 'SpecificNamed' -Machines 'vm-03', 'vm-04' + +.EXAMPLE + Add machines to unmanged manual pool + Add-HVDesktop -PoolName 'Unmanaged' -Machines 'desktop-1.eng.vmware.com' + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.0 + Dependencies : Make sure pool already exists before adding VMs to it. + + ===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 = $true)] + [string] + $PoolName, + + [Parameter(Mandatory = $true)] + [string[]] + $Machines, + + [Parameter(Mandatory = $false)] + [string[]] + $Users, + + [Parameter(Mandatory = $false)] + [string] + $Vcenter, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + try { + $desktopPool = Get-HVPool -poolName $poolName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($desktopPool) { + $id = $desktopPool.id + $type = $desktopPool.desktopsummarydata.type + $source = $desktopPool.desktopsummarydata.source + $userAssignment = $desktopPool.desktopsummarydata.userAssignment + } else { + Write-Error "Unable to retrieve DesktopSummaryView with given poolName: [$poolName]" + break + } + + $desktop_service_helper = New-Object VMware.Hv.DesktopService + $user_assignement_helper = $desktop_service_helper.getDesktopUserAssignmentHelper() + switch ($type) { + 'AUTOMATED' { + if (($userAssignment -eq $user_assignement_helper.USER_ASSIGNMENT_DEDICATED) -and ($machines.Length -ne $users.Length)) { + Write-Error "Parameters machines length: [$machines.Length] and users length: [$users.Length] should be of same size" + return + } + [VMware.Hv.DesktopSpecifiedName[]]$desktopSpecifiedNameArray = @() + $cnt = 0 + foreach ($machine in $machines) { + $specifiedNames = New-Object VMware.Hv.DesktopSpecifiedName + $specifiedNames.vmName = $machine + if ($userAssignment -eq $user_assignement_helper.USER_ASSIGNMENT_DEDICATED -and $users) { + try { + $specifiedNames.user = Get_UserId -user $users[$cnt] + } catch { + Write-Error "Unable to retrieve UserOrGroupId for user: [$users[$cnt]], $_" + return + } + } + $desktopSpecifiedNameArray += $specifiedNames + $cnt += 1 + } + $desktop_service_helper.Desktop_AddMachinesToSpecifiedNamingDesktop($services,$id,$desktopSpecifiedNameArray) + } + 'MANUAL' { + if ($source -eq 'UNMANAGED') { + $machineList = Get-RegisteredPhysicalMachines -services $services -machinesList $machines + if ($machineList.Length -eq 0) { + Write-Error "Failed to retrieve registerd physical machines with the given machines parameter" + return + } + } else { + $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter + $machineList = Get-MachinesByVCenter -machineList $machines -vcId $vcId + if ($machineList.Length -eq 0) { + Write-Error "Failed to get any Virtual Center machines with the given machines parameter" + return + } + } + $desktop_service_helper.Desktop_AddMachinesToManualDesktop($services,$id,$machineList) + } + default { + Write-Error "Only Automated/Manual pool types support this add operation" + break + } + } + } + + end { + [System.gc]::collect() + } +} + +function Get_UserId ($User) { + + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'ADUserOrGroupSummaryView' + [VMware.Hv.QueryFilter[]]$filters = $null + $groupfilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.group'; 'value' = $false } + $userNameFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $user } + $treeList = @() + $treeList += $userNameFilter + $treelist += $groupfilter + $filterAnd = New-Object VMware.Hv.QueryFilterAnd + $filterAnd.Filters = $treelist + $defn.Filter = $filterAnd + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $res = $query_service_helper.QueryService_Query($services,$defn) + if ($null -eq $res.results) { + throw "Query service did not return any users with given user name: [$user]" + } + return $res.results.id +} + +function Get-MachinesByVCenter ($MachineList,$VcId) { + + [VMware.Hv.MachineId[]]$machines = $null + $virtualMachine_helper = New-Object VMware.Hv.VirtualMachineService + $vcMachines = $virtualMachine_helper.VirtualMachine_List($services,$vcId) + $machineDict = @{} + foreach ($vMachine in $vcMachines) { + $machineDict.Add($vMachine.name,$vMachine.id) + } + foreach ($machineName in $machineList) { + if ($machineDict.Contains($machineName)) { + $machines += $machineDict.$machineName + } + } + return $machines +} +function Add-HVRDSServer { +<# +.SYNOPSIS + Add RDS Servers to an existing farm. + +.DESCRIPTION + The Add-HVRDSServer adds RDS Servers to already exiting farms by using view API service object(hvServer) of Connect-HVServer cmdlet. We can add RDSServers to manual farm type only. This advanced function do basic checks for farm and view API service connection existance. This hvServer is bound to specific connection server. + +.PARAMETER FarmName + farm name to which new RDSServers are to be added. + +.PARAMETER RdsServers + RDS servers names which need to be added to the given farm. Provide a comma separated list for multiple names. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.EXAMPLE + Add RDSServers to manual farm + Add-HVRDSServer -Farm "manualFarmTest" -RdsServers "vm-for-rds","vm-for-rds-2" + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@vmware.com + Version : 1.0 + Dependencies : Make sure farm already exists before adding RDSServers to it. + + ===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 = $true,ValueFromPipeline = $true)] + $FarmName, + + [Parameter(Mandatory = $true)] + [string[]] + $RdsServers, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + try { + $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($farmSpecObj) { + $id = $farmSpecObj.id + $type = $farmSpecObj.data.type + + } else { + Write-Error "Unable to retrieve FarmSummaryView with given farmName: [$farmName]" + break + } + $farm_service_helper = New-Object VMware.Hv.FarmService + switch ($type) { + 'AUTOMATED' { + Write-Error "Only Manual farm types supported for this add operation" + break + } + 'MANUAL' { + try { + $serverList = Get-RegisteredRDSServers -services $services -serverList $rdsServers + $farm_service_helper.Farm_AddRDSServers($services, $id, $serverList) + } catch { + Write-Error "Failed to Add RDS Server to Farm with error: $_" + break + } + } + } + } + + end { + [System.gc]::collect() + } +} +[System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient") | Out-Null + +function Connect-HVEvent { +<# +.SYNOPSIS + This function is used to connect to the event database configured on Connection Server. + +.DESCRIPTION + This function queries the specified Connection Server for event database configuration and returns the connection object to it. If event database is not configured on specified connection server, it will return null. + Currently, Horizon 7 is supporting SQL server and Oracle 12c as event database servers. To configure event database, goto 'Event Database Configuration' tab in Horizon admin UI. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER DbUserName + User name to be used in database connection. If not passed, default database user name on the Connection Server will be used. + +.PARAMETER DbPassword + Password corresponds to 'dbUserName' user. + +.EXAMPLE + Connecting to the database with default username configured on Connection Server $hvServer. + Connect-HVEvent -HvServer $hvServer + +.EXAMPLE + Connecting to the database configured on Connection Server $hvServer with customised user name 'system'. + $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' + +.EXAMPLE + Connecting to the database with customised user name and password. + $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' -DbPassword 'censored' + +.EXAMPLE + Connecting to the database with customised user name and password, with password being a SecureString. + $password = Read-Host 'Database Password' -AsSecureString + $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' -DbPassword $password + +.OUTPUTS + Returns a custom object that has database connection as 'dbConnection' property. + +.NOTES + Author : Paramesh Oddepally. + Author email : poddepally@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()] + param( + [Parameter(Mandatory = $false)] + $DbPassword = $null, + + [Parameter(Mandatory = $false)] + $HvServer = $null, + + [Parameter(Mandatory = $false)] + [string]$DbUserName = $null + ) + + begin { + # Connect to Connection Server and call the View API service + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + $EventDatabaseHelper = New-Object VMware.Hv.EventDatabaseService + $EventDatabaseInfo = $EventDatabaseHelper.EventDatabase_Get($services) + + # Check whether event database is configured on the connection server + # If not, return empty + if (!$EventDatabaseInfo.EventDatabaseSet) { + Write-Error "Event Database is not configured on Connection Server. To configure Event DB, go to 'Events Configuration' Tab in Horizon Admin UI" + break + } + + $dbServer = $EventDatabaseInfo.Database.server + $dbType = $EventDatabaseInfo.Database.type + $dbPort = $EventDatabaseInfo.Database.port + $dbName = $EventDatabaseInfo.Database.name + if (!$dbUserName) { $dbUserName = $EventDatabaseInfo.Database.userName } + $dbTablePrefix = $EventDatabaseInfo.Database.tablePrefix + + if (!$dbPassword) { $dbPassword = Read-Host 'Database Password for' $dbUserName@$dbServer -AsSecureString } + + if ($dbType -eq "SQLSERVER") { + if ($dbPassword.GetType().name -eq 'String'){ + $password = ConvertTo-SecureString $dbPassword -AsPlainText -Force + } elseif ($dbPassword.GetType().name -eq 'SecureString') { + $password = $dbPassword + } else { + Write-Error "Unsupported type recieved for dbPassword: [$dbPassword]. dbpassword should either be String or SecureString type. " + break + } + $connectionString = "Data Source=$dbServer, $dbPort; Initial Catalog=$dbName;" + $connection = New-Object System.Data.SqlClient.SqlConnection ($connectionString) + $password.MakeReadOnly() + $connection.Credential = New-Object System.Data.SqlClient.SqlCredential($dbUserName, $password); + } elseif ($dbType -eq "ORACLE") { + if ($dbPassword.GetType().name -eq 'SecureString'){ + $password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($dbPassword)) + } elseif ($dbPassword.GetType().name -eq 'String') { + $password = $dbPassword + } else { + Write-Error "Unsupported type recieved for dbPassword: [$dbPassword]. dbpassword should either be String or SecureString type. " + break + } + $dataSource = "(DESCRIPTION = " + + "(ADDRESS = (PROTOCOL = TCP)(HOST = $dbServer)(PORT = $dbPort))" + + "(CONNECT_DATA =" + + "(SERVICE_NAME = $dbName))" + + ");" + $connectionString = "Data Source=$dataSource;User Id=$dbUserName;Password=$password;" + $connection = New-Object System.Data.OracleClient.OracleConnection ($connectionString) + } else { + Write-Error "Unsupported DB type received: [$dbType]" + break + } + } + + process { + try { + $connection.Open() + } catch { + Write-Error "Failed to connect to database server: [$dbServer], $_" + break + } + Write-Host "Successfully connected to $dbType database: [$dbServer]" + return New-Object pscustomobject -Property @{ dbConnection = $connection; dbTablePrefix = $dbTablePrefix; } + } + + end { + [System.gc]::collect() + } +} + +function Disconnect-HVEvent { +<# +.SYNOPSIS + This function is used to disconnect the database connection. + +.DESCRIPTION + This function will disconnect the database connection made earlier during Connect-HVEvent function. + +.PARAMETER HvDbServer + Connection object returned by Connect-HVEvent advanced function. This is a mandatory input. + +.EXAMPLE + Disconnecting the database connection on $hvDbServer. + Disconnect-HVEvent -HvDbServer $hvDbServer + +.OUTPUTS + None + +.NOTES + Author : Paramesh Oddepally. + Author email : poddepally@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()] + param( + [Parameter(Mandatory = $true)] + [pscustomobject]$HvDbServer + ) + + begin { + $dbConnection = $hvDbServer.dbConnection + + # Validate the hvDbServer type. If not of expected type, dbConnection will be null. + if ($null -eq $dbConnection) { + Write-Error "No valid connection object found on hvDbServer parameter: [$hvDbServer]" + break + } + + # validate the user connection type of dbConnection + if (!$dbConnection.GetType().name.Equals("SqlConnection") -and !$dbConnection.GetType().name.Equals("OracleConnection")) { + Write-Error "The dbConnection object in hvDbServer parameter is not an SQL/Oracle DB connection: [$hvDbServer.GetType().Name]" + break + } + } + + process { + $dbConnection.Close() + Write-Host "Successfully closed the database connection" + } + + end { + [System.gc]::collect() + } +} + +function Get-HVEvent { +<# +.SYNOPSIS + Queries the events from event database configured on Connection Server. + +.DESCRIPTION + This function is used to query the events information from event database. It returns the object that has events in five columns as UserName, Severity, EventTime, Module and Message. EventTime will show the exact time when the event got registered in the database and it follows timezone on database server. + User can apply different filters on the event columns using the filter parameters userFilter, severityFilter, timeFilter, moduleFilter, messageFilter. Mention that when multiple filters are provided then rows which satisify all the filters will be returned. + +.PARAMETER HvDbServer + Connection object returned by Connect-HVEvent advanced function. + +.PARAMETER TimePeriod + Timeperiod of the events that user is interested in. It can take following four values: + 'day' - Lists last one day events from database + 'week' - Lists last 7 days events from database + 'month' - Lists last 30 days events from database + 'all' - Lists all the events stored in database + +.PARAMETER FilterType + Type of filter action to be applied. The parameters userfilter, severityfilter, timefilter, modulefilter, messagefilter can be used along with this. It can take following values: + 'contains' - Retrieves the events that contains the string specified in filter parameters + 'startsWith' - Retrieves the events that starts with the string specified in filter parameters + 'isExactly' - Retrieves the events that exactly match with the string specified in filter parameters + +.PARAMETER UserFilter + String that can applied in filtering on 'UserName' column. + +.PARAMETER SeverityFilter + String that can applied in filtering on 'Severity' column. + +.PARAMETER TimeFilter + String that can applied in filtering on 'EventTime' column. + +.PARAMETER ModuleFilter + String that can applied in filtering on 'Module' column. + +.PARAMETER MessageFilter + String that can applied in filtering on 'Message' column. + +.EXAMPLE + Querying all the database events on database $hvDbServer. + $e = Get-HVEvent -hvDbServer $hvDbServer + $e.Events + +.EXAMPLE + Querying all the database events where user name startswith 'aduser', severity is of 'err' type, having module name as 'broker', message starting with 'aduser' and time starting with 'HH:MM:SS.fff'. + The resulting events will be exported to a csv file 'myEvents.csv'. + $e = Get-HVEvent -HvDbServer $hvDbServer -TimePeriod 'all' -FilterType 'startsWith' -UserFilter 'aduser' -SeverityFilter 'err' -TimeFilter 'HH:MM:SS.fff' -ModuleFilter 'broker' -MessageFilter 'aduser' + $e.Events | Export-Csv -Path 'myEvents.csv' -NoTypeInformation + +.OUTPUTS + Returns a custom object that has events information in 'Events' property. Events property will have events information with five columns: UserName, Severity, EventTime, Module and Message. + +.NOTES + Author : Paramesh Oddepally. + Author email : poddepally@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()] + param( + [Parameter(Mandatory = $true)] + [pscustomobject]$HvDbServer, + + [Parameter(Mandatory = $false)] + [ValidateSet('day','week','month','all')] + [string]$TimePeriod = 'all', + + [Parameter(Mandatory = $false)] + [ValidateSet('contains','startsWith','isExactly')] + [string]$FilterType = 'contains', + + [Parameter(Mandatory = $false)] + [string]$UserFilter = "", + + [Parameter(Mandatory = $false)] + [string]$SeverityFilter = "", + + [Parameter(Mandatory = $false)] + [string]$TimeFilter = "", + + [Parameter(Mandatory = $false)] + [string]$ModuleFilter = "", + + [Parameter(Mandatory = $false)] + [string]$MessageFilter = "" + ) + + begin { + $dbConnection = $hvDbServer.dbConnection + $dbTablePrefix = $hvDbServer.dbTablePrefix + + # database table names + $eventTable = $dbTablePrefix + "event" + $eventDataTable = $dbTablePrefix + "event_data" + + # Verify the connection type in connectObject type + $isSqlType = $dbConnection.GetType().name.Equals("SqlConnection") + $isOracleType = $dbConnection.GetType().name.Equals("OracleConnection") + + if ($isSqlType) { + $command = New-Object System.Data.Sqlclient.Sqlcommand + $adapter = New-Object System.Data.SqlClient.SqlDataAdapter + } elseif ($isOracleType) { + $command = New-Object System.Data.OracleClient.OracleCommand + $adapter = New-Object System.Data.OracleClient.OracleDataAdapter + } else { + Write-Error "The dbConnection object in hvDbServer parameter is not an SQL/Oracle DB connection:[$dbConnection.GetType().Name] " + break + } + } + + process { + $command.Connection = $dbConnection + + # Extract the filter parameters and build the filterQuery string + $filterQuery = "" + + if ($userFilter -ne "") { + $filterQuery = $filterQuery + " UserSID.StrValue" + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$userFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$userFilter%'" } + else { $filterQuery = $filterQuery + " LIKE '$userFilter'" } + } + + if ($severityFilter -ne "") { + if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } + $filterQuery = $filterQuery + " Severity" + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$severityFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$severityFilter%'" } + else { $filterQuery = " LIKE '$severityFilter'" } + } + + if ($moduleFilter -ne "") { + if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } + $filterQuery = $filterQuery + " Module" + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$moduleFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$moduleFilter%'" } + else { $filterQuery = " LIKE '$moduleFilter'" } + } + + if ($messageFilter -ne "") { + if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } + $filterQuery = $filterQuery + " ModuleAndEventText" + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$messageFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$messageFilter%'" } + else { $filterQuery = " LIKE '$messageFilter'" } + } + + if ($timeFilter -ne "") { + if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } + + if ($isSqlType) { $filterQuery = $filterQuery + " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff')" } + else { $timePeriodQuery = $filterQuery = $filterQuery + " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3')" } + + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$timeFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$timeFilter%'" } + else { $filterQuery = " LIKE '$timeFilter'" } + } + + + # Calculate the Timeperiod and build the timePeriodQuery string + # It queries the current time from database server and calculates the time range + if ($timePeriod -eq 'day') { + $timeInDays = 1 + } elseif ($timePeriod -eq 'week') { + $timeInDays = 7 + } elseif ($timePeriod -eq 'month') { + $timeInDays = 30 + } else { + $timeInDays = 0 + } + + if ($isSqlType) { + $query = "SELECT CURRENT_TIMESTAMP" + } else { + $query = "SELECT CURRENT_TIMESTAMP from dual" + } + + $command.CommandText = $query + $adapter.SelectCommand = $command + $DataTable = New-Object System.Data.DataTable + $adapter.Fill($DataTable) + + $toDate = $DataTable.Rows[0][0] + $fromDate = $toDate.AddDays(- ($timeInDays)) + + if ($timePeriod -eq 'all') { + if ($isSqlType) { $timePeriodQuery = " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') < '" + $toDate + "'" } + else { $timePeriodQuery = " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') < '" + $toDate + "'" } + } else { + if ($isSqlType) { $timePeriodQuery = " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') BETWEEN '" + $fromDate + "' AND '" + $toDate + "'" } + else { $timePeriodQuery = " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') BETWEEN '" + $fromDate + "' AND '" + $toDate + "'" } + } + + + # Build the Query string based on the database type and filter parameters + if ($isSqlType) { + $query = "SELECT UserSID.StrValue AS UserName, Severity, FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') as EventTime, Module, ModuleAndEventText AS Message FROM $eventTable " + + " LEFT OUTER JOIN (SELECT EventID, StrValue FROM $eventDataTable WITH (NOLOCK) WHERE (Name = 'UserDisplayName')) UserSID ON $eventTable.EventID = UserSID.EventID " + $query = $query + " WHERE $timePeriodQuery" + if ($filterQuery -ne "") { $query = $query + " AND $filterQuery" } + $query = $query + " ORDER BY EventTime DESC" + } else { + $query = " SELECT UserSID.StrValue AS UserName, Severity, TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') AS EventTime, Module, ModuleAndEventText AS Message FROM $eventTable " + + " LEFT OUTER JOIN (SELECT EventID, StrValue FROM $eventDataTable WHERE (Name = 'UserDisplayName')) UserSID ON $eventTable.EventID = UserSID.EventID" + $query = $query + " WHERE $timePeriodQuery" + if ($filterQuery -ne "") { $query = $query + " AND $filterQuery" } + $query = $query + " ORDER BY EventTime DESC" + } + + $command.CommandText = $query + $adapter.SelectCommand = $command + + $DataTable = New-Object System.Data.DataTable + $adapter.Fill($DataTable) + + Write-Host "Number of records found : " $DataTable.Rows.Count + + <# + # This code allows the events to get printed on console + Write-Host " User Time Severity Module ModuleAndEventText " + Foreach($row in $DataTable.Rows) { + Write-Host $row[0] " " $row[1] " " $row[2] " " $row[3] " " $row[4] " " + }#> + + return New-Object pscustomobject -Property @{ Events = $DataTable; } + } + + end { + [System.gc]::collect() + } +} + +function Get-HVFarm { +<# +.SYNOPSIS + This function is used to find farms based on the search criteria provided by the user. + +.DESCRIPTION + This function queries the specified Connection Server for farms which are configured on the server. If no farm is configured on the specified connection server or no farm matches the given search criteria, it will return null. + +.PARAMETER FarmName + farmName to be searched + +.PARAMETER FarmDisplayName + farmDisplayName to be searched + +.PARAMETER FarmType + farmType to be searched. It can take following values: + "AUTOMATED" - search for automated farms only + 'MANUAL' - search for manual farms only + +.PARAMETER Enabled + search for farms which are enabled + +.PARAMETER Full + Switch to get list of FarmSummaryView or FarmInfo objects in the result. If it is true a list of FarmInfo objects is returned ohterwise a list of FarmSummaryView objects is returned. + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' -FarmDisplayName 'Sales RDS Farm' + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' -Enabled $true + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' -Full + +.OUTPUTs + Returns the list of FarmSummaryView or FarmInfo object matching the query criteria. + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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)] + [string] + $FarmName, + + [Parameter(Mandatory = $false)] + [string] + $FarmDisplayName, + + [Parameter(Mandatory = $false)] + [ValidateSet('MANUAL','AUTOMATED')] + [string] + $FarmType, + + [Parameter(Mandatory = $false)] + [boolean] + $Enabled, + + [Parameter(Mandatory = $false)] + [switch] + $Full, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + # + # This translates the function arguments into the View API properties that must be queried + $farmSelectors = @{ + 'farmName' = 'data.name'; + 'farmDisplayName' = 'data.displayName'; + 'enabled' = 'data.enabled'; + 'farmType' = 'data.type'; + } + + $parms = $psboundparameters + + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $query = New-Object VMware.Hv.QueryDefinition + + # build the query values + + $query.queryEntityType = 'FarmSummaryView' + [VMware.Hv.queryfilter[]]$filterSet = @() + foreach ($setting in $farmSelectors.Keys) { + if ($null -ne $parms[$setting]) { + $equalsFilter = New-Object VMware.Hv.QueryFilterEquals + $equalsFilter.memberName = $farmSelectors[$setting] + $equalsFilter.value = $parms[$setting] + $filterSet += $equalsFilter + } + } + if ($filterSet.Count -gt 0) { + $queryList = New-Object VMware.Hv.QueryFilterAnd + $queryList.Filters = $filterset + $query.Filter = $queryList + } + + $queryResults = $query_service_helper.QueryService_Query($services, $query) + $farmList = $queryResults.results + if ($full) { + $farm_service_helper = New-Object VMware.Hv.FarmService + $queryResults = @() + foreach ($id in $farmList.id) { + $info = $farm_service_helper.Farm_Get($services,$id) + $queryResults += $info + } + $farmList = $queryResults + } + return $farmList +} + +function Get-HVPool { +<# +.Synopsis + Gets pool(s) information with given search parameters. + +.DESCRIPTION + Queries and returns pools information, the pools list would be determined based on + queryable fields poolName, poolDisplayName, poolType, userAssignment, enabled, + provisioningEnabled. When more than one fields are used for query the pools which + satisfy all fields criteria would be returned. + +.PARAMETER PoolName + Pool name to query for. + If the value is null or not provided then filter will not be applied, + otherwise the pools which has name same as value will be returned. + +.PARAMETER PoolDisplayName + Pool display name to query for. + If the value is null or not provided then filter will not be applied, + otherwise the pools which has display name same as value will be returned. + +.PARAMETER PoolType + Pool type to filter with. + If the value is null or not provided then filter will not be applied. + If the value is MANUAL then only manual pools would be returned. + If the value is AUTOMATED then only automated pools would be returned + If the value is RDS then only Remote Desktop Service Pool pools would be returned + +.PARAMETER UserAssignment + User Assignment of pool to filter with. + If the value is null or not provided then filter will not be applied. + If the value is DEDICATED then only dedicated pools would be returned. + If the value is FLOATING then only floating pools would be returned + +.PARAMETER Enabled + Pool enablement to filter with. + If the value is not provided then then filter will not be applied. + If the value is true then only pools which are enabled would be returned. + If the value is false then only pools which are disabled would be returned. + +.PARAMETER Full + Switch to get full information about the pool. + Use this switch only when you require complete information about pool. + +.PARAMETER HvServer + Reference to Horizon View Server to query the pools from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer + +.EXAMPLE + Get-HVPool -PoolName 'mypool' -PoolType MANUAL -UserAssignment FLOATING -Enabled $true -ProvisioningEnabled $true + +.EXAMPLE + Get-HVPool -PoolType AUTOMATED -UserAssignment FLOATING -full + +.EXAMPLE + Get-HVPool -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false + +.EXAMPLE + Get-HVPool -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false -HvServer $mycs + +.OUTPUTS + If switch -Full is used then returns list of DesktopSummaryView + else returns list of objects of type Desktop + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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)] + [string] + $PoolName, + + [Parameter(Mandatory = $false)] + [string] + $PoolDisplayName, + + [Parameter(Mandatory = $false)] + [ValidateSet('MANUAL','AUTOMATED','RDS')] + [string] + $PoolType, + + [Parameter(Mandatory = $false)] + [ValidateSet('FLOATING','DEDICATED')] + [string] + $UserAssignment, + + [Parameter(Mandatory = $false)] + [boolean] + $Enabled, + + [Parameter(Mandatory = $false)] + [boolean] + $ProvisioningEnabled, + + [Parameter(Mandatory = $false)] + [switch] + $Full, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + # + # This translates the function arguments into the View API properties that must be queried + $poolSelectors = @{ + 'poolName' = 'desktopSummaryData.name'; + 'poolDisplayName' = 'desktopSummaryData.displayName'; + 'enabled' = 'desktopSummaryData.enabled'; + 'poolType' = 'desktopSummaryData.type'; + 'userAssignment' = 'desktopSummaryData.userAssignment'; + 'provisioningEnabled' = 'desktopSummaryData.provisioningEnabled' + } + + $parms = $psboundparameters + + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $query = New-Object VMware.Hv.QueryDefinition + + $wildCard = $false + #Only supports wild card '*' + if ($parms['PoolName'] -and $parms['PoolName'].contains('*')) { + $wildcard = $true + } + if ($parms['PoolDisplayName'] -and $parms['PoolDisplayName'].contains('*')) { + $wildcard = $true + } + # build the query values + $query.queryEntityType = 'DesktopSummaryView' + if (! $wildcard) { + [VMware.Hv.queryfilter[]]$filterSet = @() + foreach ($setting in $poolSelectors.Keys) { + if ($null -ne $parms[$setting]) { + $equalsFilter = New-Object VMware.Hv.QueryFilterEquals + $equalsFilter.memberName = $poolSelectors[$setting] + $equalsFilter.value = $parms[$setting] + $filterSet += $equalsFilter + } + } + if ($filterSet.Count -gt 0) { + $andFilter = New-Object VMware.Hv.QueryFilterAnd + $andFilter.Filters = $filterset + $query.Filter = $andFilter + } + $queryResults = $query_service_helper.QueryService_Query($services,$query) + $poolList = $queryResults.results + } + if ($wildcard -or [string]::IsNullOrEmpty($poolList)) { + $query.Filter = $null + $queryResults = $query_service_helper.QueryService_Query($services,$query) + $strFilterSet = @() + foreach ($setting in $poolSelectors.Keys) { + if ($null -ne $parms[$setting]) { + if ($wildcard -and (($setting -eq 'PoolName') -or ($setting -eq 'PoolDisplayName')) ) { + $strFilterSet += '($_.' + $poolSelectors[$setting] + ' -like "' + $parms[$setting] + '")' + } else { + $strFilterSet += '($_.' + $poolSelectors[$setting] + ' -eq "' + $parms[$setting] + '")' + } + } + } + $whereClause = [string]::Join(' -and ', $strFilterSet) + $scriptBlock = [Scriptblock]::Create($whereClause) + $poolList = $queryResults.results | where $scriptBlock + } + if ($full) { + $queryResults = @() + $desktop_helper = New-Object VMware.Hv.DesktopService + foreach ($id in $poolList.id) { + $info = $desktop_helper.Desktop_Get($services,$id) + $queryResults += $info + } + $poolList = $queryResults + } + return $poolList +} + +function Get-HVQueryFilter { +<# +.Synopsis + Creates a VMware.Hv.QueryFilter based on input provided. + +.DESCRIPTION + This is a factory method to create a VMware.Hv.QueryFilter. The type of the QueryFilter would be determined based on switch used. + +.PARAMETER MemberName + Property path separated by . (dot) from the root of queryable data object which is being queried for + +.PARAMETER MemberValue + Value of property (memberName) which is used for filtering + +.PARAMETER Eq + Switch to create QueryFilterEquals filter + +.PARAMETER Ne + Switch to create QueryFilterNotEquals filter + +.PARAMETER Contains + Switch to create QueryFilterContains filter + +.PARAMETER Startswith + Switch to create QueryFilterStartsWith filter + +.PARAMETER Not + Switch to create QueryFilterNot filter, used for negating existing filter + +.PARAMETER And + Switch to create QueryFilterAnd filter, used for joing two or more filters + +.PARAMETER Or + Switch to create QueryFilterOr filter, used for joing two or more filters + +.PARAMETER Filter + Filter to used in QueryFilterNot to negate the result + +.PARAMETER Filters + List of filters to join using QueryFilterAnd or QueryFilterOr + + +.EXAMPLE + Get-HVQueryFilter data.name -Eq vmware + +.EXAMPLE + Get-HVQueryFilter -MemberName data.name -Eq -MemberValue vmware + +.EXAMPLE + Get-HVQueryFilter data.name -Ne vmware + +.EXAMPLE + Get-HVQueryFilter data.name -Contains vmware + +.EXAMPLE + Get-HVQueryFilter data.name -Startswith vmware + +.EXAMPLE + $filter = Get-HVQueryFilter data.name -Startswith vmware + Get-HVQueryFilter -Not $filter + +.EXAMPLE + $filter1 = Get-HVQueryFilter data.name -Startswith vmware + $filter2 = Get-HVQueryFilter data.name -Contains pool + Get-HVQueryFilter -And @($filter1, $filter2) + +.EXAMPLE + $filter1 = Get-HVQueryFilter data.name -Startswith vmware + $filter2 = Get-HVQueryFilter data.name -Contains pool + Get-HVQueryFilter -Or @($filter1, $filter2) + +.OUTPUTS + Returns the QueryFilter object + +.NOTES + Author : Kummara Ramamohan. + Author email : kramamohan@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()] + param( + # Type 1 parametersets which requires memberName, memberValue as input + [Parameter(ParameterSetName = 'eq',Mandatory = $true,Position = 0)] + [Parameter(ParameterSetName = 'contains',Mandatory = $true,Position = 0)] + [Parameter(ParameterSetName = 'startswith',Mandatory = $true,Position = 0)] + [Parameter(ParameterSetName = 'ne',Mandatory = $true,Position = 0)] + [string]$MemberName, + + [Parameter(ParameterSetName = "eq",Mandatory = $true,Position = 1)] + [switch]$Eq, + + [Parameter(ParameterSetName = "contains",Mandatory = $true,Position = 1)] + [switch]$Contains, + + [Parameter(ParameterSetName = "startswith",Mandatory = $true,Position = 1)] + [switch]$Startswith, + + [Parameter(ParameterSetName = "ne",Mandatory = $true,Position = 1)] + [switch]$Ne, + + [Parameter(ParameterSetName = 'eq',Mandatory = $true,Position = 2)] + [Parameter(ParameterSetName = 'contains',Mandatory = $true,Position = 2)] + [Parameter(ParameterSetName = 'startswith',Mandatory = $true,Position = 2)] + [Parameter(ParameterSetName = 'ne',Mandatory = $true,Position = 2)] + [System.Object]$MemberValue, + + # Negation # + [Parameter(ParameterSetName = "not",Mandatory = $true,Position = 0)] + [switch]$Not, + + [Parameter(ParameterSetName = 'not',Mandatory = $true,Position = 1)] + [VMware.Hv.QueryFilter]$Filter, + + # Aggregators to join more than 1 filters # + [Parameter(ParameterSetName = 'and',Mandatory = $true,Position = 0)] + [switch]$And, + + [Parameter(ParameterSetName = "or",Mandatory = $true,Position = 0)] + [switch]$Or, + + [Parameter(ParameterSetName = "and",Mandatory = $true,Position = 1)] + [Parameter(ParameterSetName = "or",Mandatory = $true,Position = 1)] + [VMware.Hv.QueryFilter[]]$Filters + ) + + begin { + $switchToClassName = @{ + 'eq' = 'QueryFilterEquals'; + 'startswith' = 'QueryFilterStartsWith'; + 'contains' = 'QueryFilterContains'; + 'ne' = 'QueryFilterNotEquals'; + 'not' = 'QueryFilterNot'; + 'and' = 'QueryFilterAnd'; + 'or' = 'QueryFilterOr'; + } + } + process { + $queryFilter = Get_New_Object -typeName $switchToClassName[$PsCmdlet.ParameterSetName] + + switch ($PsCmdlet.ParameterSetName) { + + { @( 'eq','startswith','contains','ne') -icontains $_ } { + $queryFilter.memberName = $memberName + $queryFilter.value = $membervalue + } + + { @( 'and','or') -icontains $_ } { + $queryFilter.filters = $filters + } + + { @( 'not') -icontains $_ } { + $queryFilter.filter = $filter + } + } + } + end { + return $queryFilter + } +} + +function Get-HVQueryResult { +<# +.Synopsis + Returns the query results from ViewApi Query Service + +.DESCRIPTION + Get-HVQueryResult is a API to query the results using ViewApi. The filtering of the returned + list would be done based on input parameters filter, sortDescending, sortyBy, limit + +.PARAMETER EntityType + ViewApi Queryable entity type which is being queried for.The return list would be containing objects of entityType + +.PARAMETER Filter + Filter to used for filtering the results, See Get-HVQueryFilter for more information + +.PARAMETER SortBy + Data field path used for sorting the results + +.PARAMETER SortDescending + If the value is set to true (default) then the results will be sorted in descending order + If the value is set to false then the results will be sorted in ascending order + +.PARAMETER Limit + Max number of objects to retrieve. Default would be 0 which means retieve all the results + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer + +.EXAMPLE + Get-HVQueryResult DesktopSummaryView + +.EXAMPLE + Get-HVQueryResult DesktopSummaryView (Get-HVQueryFilter data.name -Eq vmware) + +.EXAMPLE + Get-HVQueryResult -EntityType DesktopSummaryView -Filter (Get-HVQueryFilter desktopSummaryData.name -Eq vmware) + +.EXAMPLE + Get-HVQueryResult -EntityType DesktopSummaryView -Filter (Get-HVQueryFilter desktopSummaryData.name -Eq vmware) -SortBy desktopSummaryData.displayName + +.EXAMPLE + $myFilter = Get-HVQueryFilter data.name -Contains vmware + Get-HVQueryResult -EntityType DesktopSummaryView -Filter $myFilter -SortBy desktopSummaryData.displayName -SortDescending $false + +.EXAMPLE + Get-HVQueryResult DesktopSummaryView -Limit 10 + +.OUTPUTS + Returns the list of objects of entityType + +.NOTES + Author : Kummara Ramamohan. + Author email : kramamohan@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(Position = 0,Mandatory = $true)] + [ValidateSet('ADUserOrGroupSummaryView','ApplicationIconInfo','ApplicationInfo','DesktopSummaryView', + 'EntitledUserOrGroupGlobalSummaryView','EntitledUserOrGroupLocalSummaryView','FarmHealthInfo', + 'FarmSummaryView','GlobalApplicationEntitlementInfo','GlobalEntitlementSummaryView', + 'MachineNamesView','MachineSummaryView','PersistentDiskInfo','PodAssignmentInfo', + 'RDSServerInfo','RDSServerSummaryView','RegisteredPhysicalMachineInfo','SampleInfo', + 'SessionLocalSummaryView','TaskInfo','URLRedirectionInfo','UserHomeSiteInfo')] + [string]$EntityType, + + [Parameter(Position = 1,Mandatory = $false)] + [VMware.Hv.QueryFilter]$Filter = $null, + + [Parameter(Position = 2,Mandatory = $false)] + [string]$SortBy = $null, + + [Parameter(Position = 3,Mandatory = $false)] + [bool]$SortDescending = $true, + + [Parameter(Position = 4,Mandatory = $false)] + [int16]$Limit = 0, + + [Parameter(Position = 5,Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $queryDef = New-Object VMware.Hv.QueryDefinition + $queryDef.queryEntityType = $entityType + $queryDef.sortDescending = $sortDescending + + if ($sortBy) { + $queryDef.sortBy = $sortBy + } + + if ($limit -gt 0) { + $queryDef.limit = $limit + } + + $queryDef.filter = $filter + + $returnList = @() + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $queryResults = $query_service_helper.QueryService_Create($services,$queryDef) + $returnList += $queryResults.results + + while ($queryResults -and ($queryResults.RemainingCount -gt 0)) { + $queryResults = $query_service_helper.QueryService_GetNext($services,$queryResults.id) + $returnList += $queryResults.results + } + + if ($queryResults.id) { + $query_service_helper.QueryService_Delete($services,$queryResults.id) + } + } + + end { + return $returnList + } +} + +function New-HVFarm { +<# +.Synopsis + Creates a new farm. + +.DESCRIPTION + Creates a new farm, the type would be determined based on input parameters. + +.PARAMETER LinkedClone + Switch to Create Automated Linked Clone farm. + +.PARAMETER Manual + Switch to Create Manual farm. + +.PARAMETER FarmName + Name of the farm. + +.PARAMETER FarmDisplayName + Display name of the farm. + +.PARAMETER Description + Description of the farm. + +.PARAMETER AccessGroup + View access group can organize the servers in the farm. + Default Value is 'Root'. + +.PARAMETER Enable + Set true to enable the farm otherwise set to false. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) where the farm RDS Servers are located. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER ParentVM + Base image VM for RDS Servers. + Applicable only to Linked Clone farms. + +.PARAMETER SnapshotVM + Base image snapshot for RDS Servers. + +.PARAMETER VmFolder + VM folder to deploy the RDSServers to. + Applicable to Linked Clone farms. + +.PARAMETER HostOrCluster + Host or cluster to deploy the RDSServers in. + Applicable to Linked Clone farms. + +.PARAMETER ResourcePool + Resource pool to deploy the RDSServers. + Applicable to Linked Clone farms. + +.PARAMETER Datastores + Datastore names to store the RDSServer. + Applicable to Linked Clone farms. + +.PARAMETER UseVSAN + Whether to use vSphere VSAN. This is applicable for vSphere 5.5 or later. + Applicable to Linked Clone farms. + +.PARAMETER EnableProvisioning + Set to true to enable provision of RDSServers immediately in farm. + Applicable to Linked Clone farms. + +.PARAMETER StopOnProvisioningError + Set to true to stop provisioning of all RDSServers on error. + Applicable to Linked Clone farms. + +.PARAMETER TransparentPageSharingScope + The transparent page sharing scope. + The default value is 'VM'. + +.PARAMETER NamingMethod + Determines how the VMs in the farm are named. + Set PATTERN to use naming pattern. + The default value is PATTERN. Curentlly only PATTERN is allowed. + +.PARAMETER NamingPattern + RDS Servers will be named according to the specified naming pattern. + Value would be considered only when $namingMethod = PATTERN + The default value is farmName + '{n:fixed=4}'. + +.PARAMETER MinReady + Minimum number of ready (provisioned) Servers during View Composer maintenance operations. + The default value is 0. + Applicable to Linked Clone farms. + +.PARAMETER MaximumCount + Maximum number of Servers in the farm. + The default value is 1. + Applicable to Linked Clone farms. + +.PARAMETER AdContainer + This is the Active Directory container which the Servers will be added to upon creation. + The default value is 'CN=Computers'. + Applicable to Linked Clone farm. + +.PARAMETER NetBiosName + Domain Net Bios Name. + Applicable to Linked Clone farms. + +.PARAMETER DomainAdmin + Domain Administrator user name which will be used to join the domain. + Default value is null. + Applicable to Linked Clone farms. + +.PARAMETER SysPrepName + The customization spec to use. + Applicable to Linked Clone farms. + +.PARAMETER RdsServers + List of existing registered RDS server names to add into manual farm. + Applicable to Manual farms. + +.PARAMETER Spec + Path of the JSON specification file. + +.PARAMETER HvServer + Reference to Horizon View Server to query the farms from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + New-HVFarm -LinkedClone -FarmName 'LCFarmTest' -ParentVM 'Win_Server_2012_R2' -SnapshotVM 'Snap_RDS' -VmFolder 'PoolVM' -HostOrCluster 'cls' -ResourcePool 'cls' -Datastores 'datastore1 (5)' -FarmDisplayName 'LC Farm Test' -Description 'created LC Farm from PS' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "LCFarmVM_PS" -MinReady 1 -MaximumCount 1 -SysPrepName "RDSH_Cust2" -NetBiosName "adviewdev" + +.EXAMPLE + New-HVFarm -Spec C:\VMWare\Specs\LinkedClone.json + +.EXAMPLE + New-HVFarm -Manual -FarmName "manualFarmTest" -FarmDisplayName "manualFarmTest" -Description "Manual PS Test" -RdsServers "vm-for-rds.eng.vmware.com","vm-for-rds-2.eng.vmware.com" + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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 = $true,ParameterSetName = "LINKED_CLONE")] + [switch] + $LinkedClone, + + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [switch] + $Manual, + + #farmSpec.farmData.name + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $FarmName, + + #farmSpec.farmData.displayName + [Parameter(Mandatory = $false)] + [string] + $FarmDisplayName = $farmName, + + #farmSpec.farmData.description + [Parameter(Mandatory = $false)] + [string] + $Description = ' ', + + #farmSpec.farmData.accessGroup + [Parameter(Mandatory = $false)] + [string] + $AccessGroup = 'Root', + + #farmSpec.farmData.enabled + [Parameter(Mandatory = $false)] + [boolean] + $Enable = $true, + + #farmSpec.automatedfarmSpec.virtualCenter if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $Vcenter, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVM if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $ParentVM, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshotVM if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $SnapshotVM, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $VmFolder, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.hostOrCluster if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $HostOrCluster, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.resourcePool if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $ResourcePool, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string[]] + $Datastores, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.useVSAN if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $UseVSAN, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean] + $EnableProvisioning = $true, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean] + $StopOnProvisioningError = $true, + + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $TransparentPageSharingScope = 'VM', + + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.namingMethod if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('PATTERN')] + [string] + $NamingMethod = 'PATTERN', + + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.namingPattern if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $NamingPattern = $farmName + '{n:fixed=4}', + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [int] + $MinReady = 0, + + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [int] + $MaximumCount = 1, + + #farmSpec.automatedfarmSpec.customizationSettings.adContainer if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string] + $AdContainer = 'CN=Computers', + + #farmSpec.automatedfarmSpec.customizationSettings.domainAdministrator + [Parameter(Mandatory = $true,ParameterSetName = 'LINKED_CLONE')] + [string] + $NetBiosName, + + #farmSpec.automatedfarmSpec.customizationSettings.domainAdministrator + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string] + $DomainAdmin = $null, + + #farmSpec.automatedfarmSpec.customizationSettings.sysprepCustomizationSettings.customizationSpec if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $SysPrepName, + + ##farmSpec.manualfarmSpec.rdsServers + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [string[]] + $RdsServers, + + [Parameter(Mandatory = $false,ParameterSetName = 'JSON_FILE')] + [string] + $Spec, + + [Parameter(Mandatory = $false)] + $HvServer = $null + + ) + # + # farmSpec/FarmInfo + # *farmData + # +AccessGroupId + # +FarmSessionSettings + # FarmAutomatedfarmSpec/FarmAutomatedFarmData + # */+VirtualCenterId + # FarmRDSServerNamingSpec/FarmVirtualMachineNamingSettings + # FarmPatternNamingSpec/FarmPatternNamingSettings + # FarmVirtualCenterProvisioningSettings + # FarmVirtualCenterProvisioningData/virtualCenterProvisioningData + # FarmVirtualCenterStorageSettings + # FarmVirtualCenterNetworkingSettings + # FarmVirtualCenterManagedCommonSettings + # FarmCustomizationSettings + # ViewComposerDomainAdministratorId + # ADContainerId + # FarmSysprepCustomizationSettings + # CustomizationSpecId + # FarmManualfarmSpec + # RDSServerId[] + # + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + + if ($farmName) { + try { + $sourceFarm = Get-HVFarm -farmName $farmName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($sourceFarm) { + Write-Error "Farm with name [$farmName] already exists" + return + } + } + $farm_service_helper = New-Object VMware.Hv.FarmService + if ($spec) { + try { + $jsonObject = Get_Json_Object -specFile $spec + } catch { + Write-Error "Json file exception, $_" + break + } + if ($jsonObject.type -eq 'AUTOMATED') { + $farmType = 'AUTOMATED' + if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenter) { + $vCenter = $jsonObject.AutomatedFarmSpec.VirtualCenter + } + $linkedClone = $true + $netBiosName = $jsonObject.NetBiosName + $adContainer = $jsonObject.AutomatedFarmSpec.CustomizationSettings.AdContainer + + $namingMethod = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.NamingMethod + $namingPattern = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern + $maximumCount = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers + + $transparentPageSharingScope = $jsonObject.AutomatedFarmSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope + + if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm) { + $parentVM = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm + } + if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot) { + $snapshotVM = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot + } + $vmFolder = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.VmFolder + $hostOrCluster = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.HostOrCluster + $resourcePool = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ResourcePool + $dataStoreList = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores + foreach ($dtStore in $dataStoreList) { + $datastores += $dtStore.Datastore + } + $sysPrepName = $jsonObject.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec + } elseif ($jsonObject.type -eq 'MANUAL') { + $manual = $true + $farmType = 'MANUAL' + $RdsServersObjs = $jsonObject.ManualFarmSpec.RdsServers + + foreach ($RdsServerObj in $RdsServersObjs) { + $rdsServers += $RdsServerObj.rdsServer + } + } + $farmDisplayName = $jsonObject.data.DisplayName + $description = $jsonObject.data.Description + $accessGroup = $jsonObject.data.AccessGroup + $farmName = $jsonObject.data.name + } + + if ($linkedClone) { + $farmType = 'AUTOMATED' + $provisioningType = 'VIEW_COMPOSER' + } elseif ($manual) { + $farmType = 'MANUAL' + } + + $script:farmSpecObj = Get_Farm_Spec -farmType $farmType -provisioningType $provisioningType -namingMethod $namingMethod + + # + # build out the infrastructure based on type of provisioning + # + $handleException = $false + switch ($farmType) { + + 'MANUAL' { + try { + $serverList = Get-RegisteredRDSServers -services $services -serverList $rdsServers + $farmSpecObj.ManualFarmSpec.RdsServers = $serverList + } catch { + $handleException = $true + Write-Error "Failed to create Farm with error: $_" + break + } + } + default { + # + # accumulate properties that are shared among various type + # + + # + # vCenter: if $vcenterID is defined, then this is a clone + # if the user specificed the name, then find it from the list + # if none specified, then automatically use the vCenter if there is only one + # + + if (!$virtualCenterID) { + $virtualCenterID = Get_Vcenter_ID -services $services -vCenter $vCenter + } + + if ($null -eq $virtualCenterID) { + $handleException = $true + break + } + + # + # transparentPageSharingScope + # + + if (!$farmVirtualCenterManagedCommonSettings) { + if ($farmSpecObj.AutomatedFarmSpec) { + $farmSpecObj.AutomatedFarmSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope + } + $farmVirtualCenterManagedCommonSettings = $farmSpecObj.AutomatedFarmSpec.virtualCenterManagedCommonSettings + } + + if (!$farmVirtualMachineNamingSpec) { + $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.NamingMethod = $namingMethod + $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern = $namingPattern + $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers = $maximumCount + } else { + $vmNamingSpec = New-Object VMware.Hv.FarmRDSServerNamingSpec + $vmNamingSpec.NamingMethod = 'PATTERN' + + $vmNamingSpec.patternNamingSettings = New-Object VMware.Hv.FarmPatternNamingSettings + $vmNamingSpec.patternNamingSettings.namingPattern = $namingPattern + $vmNamingSpec.patternNamingSettings.maxNumberOfRDSServers = $maximumCount + } + + # + # build the VM LIST + # + try { + $farmVirtualCenterProvisioningData = Build_VM_List_Farm -vc $virtualCenterID -vmObject $farmVirtualCenterProvisioningData + $hostClusterId = $farmVirtualCenterProvisioningData.HostOrCluster + $farmVirtualCenterStorageSettings = Build_Datastore_List_Farm -hostclusterID $hostClusterId -storageObject $farmVirtualCenterStorageSettings + $farmVirtualCenterNetworkingSettings = Build_Network_List_Farm -networkObject $farmVirtualCenterNetworkingSettings + $farmCustomizationSettings = Build_Customization_Settings_Farm -vc $virtualCenterID -customObject $farmCustomizationSettings + } catch { + $handleException = $true + Write-Error "Failed to create Farm with error: $_" + break + } + + $farmSpecObj.AutomatedFarmSpec.RdsServerMaxSessionsData.MaxSessionsType = "UNLIMITED" + + if (!$FarmVirtualCenterProvisioningSettings) { + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.enableProvisioning = $true + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $true + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = 0 + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $farmVirtualCenterProvisioningData + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $farmVirtualCenterStorageSettings + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $FarmVirtualCenterNetworkingSettings + + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings = $farmCustomizationSettings + $farmSpecObj.AutomatedFarmSpec.ProvisioningType = $provisioningType + $farmSpecObj.AutomatedFarmSpec.VirtualCenter = $virtualCenterID + } else { + $FarmVirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $farmVirtualCenterProvisioningData + $FarmVirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $farmVirtualCenterStorageSettings + $FarmVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $FarmVirtualCenterNetworkingSettings + + $FarmAutomatedFarmSpec = New-Object VMware.Hv.FarmAutomatedFarmSpec + $FarmAutomatedFarmSpec.ProvisioningType = $provisioningType + $FarmAutomatedFarmSpec.VirtualCenter = $virtualCenterID + $FarmAutomatedFarmSpec.VirtualCenterProvisioningSettings = $farmVirtualCenterProvisioningSettings + $FarmAutomatedFarmSpec.virtualCenterManagedCommonSettings = $farmVirtualCenterManagedCommonSettings + $FarmAutomatedFarmSpec.CustomizationSettings = $farmCustomizationSettings + } + } + } + + if ($handleException) { + break + } + + $farmData = $farmSpecObj.data + $AccessGroup_service_helper = New-Object VMware.Hv.AccessGroupService + $ag = $AccessGroup_service_helper.AccessGroup_List($services) | Where-Object { $_.base.name -eq $accessGroup } + $farmData.AccessGroup = $ag.id + + $farmData.name = $farmName + $farmData.DisplayName = $farmDisplayName + $farmData.Description = $description + $farmSpecObj.type = $farmType + + if ($FarmAutomatedFarmSpec) { + $farmSpecObj.AutomatedFarmSpec = $FarmAutomatedFarmSpec + } + if ($FarmManualFarmSpec) { + $farmSpecObj.ManualFarmSpec = $FarmManualFarmSpec + } + + # Please uncomment below code, if you want to save the json file + <# +$myDebug = convertto-json -InputObject $farmSpecObj -depth 12 +$myDebug | out-file -filepath c:\temp\copiedfarm.json +#> + $farm_service_helper.Farm_Create($services, $farmSpecObj) + } + + end { + [System.gc]::collect() + } + +} + +function Build_VM_List_Farm { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmVirtualCenterProvisioningData]$VmObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID + ) + if (!$vmObject) { + $vmObject = $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData + } + if ($parentVM) { + $BaseImage_service_helper = New-Object VMware.Hv.BaseImageVmService + $parentList = $BaseImage_service_helper.BaseImageVm_List($services, $vcID) + $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } + if ($null -eq $parentVMObj) { + throw "No Parent VM found with name: [$parentVM]" + } + $vmObject.ParentVm = $parentVMObj.id + $dataCenterID = $parentVMObj.datacenter + $vmObject.datacenter = $dataCenterID + } + if ($snapshotVM) { + $BaseImageSnapshot_service_helper = New-Object VMware.Hv.BaseImageSnapshotService + $snapshotList = $BaseImageSnapshot_service_helper.BaseImageSnapshot_List($services, $parentVMObj.id) + $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } + if ($null -eq $snapshotVMObj) { + throw "No Snapshot found with name: [$snapshotVM] for VM name: [$parentVM] " + } + $vmObject.Snapshot = $snapshotVMObj.id + } + if ($vmFolder) { + $VmFolder_service_helper = New-Object VMware.Hv.VmFolderService + $folders = $VmFolder_service_helper.VmFolder_GetVmFolderTree($services, $vmObject.datacenter) + $folderList = @() + $folderList += $folders + while ($folderList.Length -gt 0) { + $item = $folderList[0] + if ($item -and !$_.folderdata.incompatiblereasons.inuse -and !$_.folderdata.incompatiblereasons.viewcomposerreplicafolder -and ($item.folderdata.name -eq $vmFolder)) { + $vmObject.VmFolder = $item.id + break + } + foreach ($folderItem in $item.children) { + $folderList += $folderItem + } + $folderList = $folderList[1..$folderList.Length] + } + if ($null -eq $vmObject.VmFolder) { + throw "No VM Folder found with name: [$vmFolder]" + } + } + if ($hostOrCluster) { + $HostOrCluster_service_helper = New-Object VMware.Hv.HostOrClusterService + $hostClusterList = ($HostOrCluster_service_helper.HostOrCluster_GetHostOrClusterTree($services, $vmobject.datacenter)).treeContainer.children.info + $HostClusterObj = $hostClusterList | Where-Object { $_.name -eq $hostOrCluster } + if ($null -eq $HostClusterObj) { + throw "No host or cluster found with name: [$hostOrCluster]" + } + $vmObject.HostOrCluster = $HostClusterObj.id + } + if ($resourcePool) { + $ResourcePool_service_helper = New-Object VMware.Hv.ResourcePoolService + $resourcePoolList = $ResourcePool_service_helper.ResourcePool_GetResourcePoolTree($services, $vmobject.HostOrCluster) + $resourcePoolObj = $resourcePoolList | Where-Object { $_.resourcepooldata.name -eq $resourcePool } + if ($null -eq $resourcePoolObj) { + throw "No resource pool found with name: [$resourcePool]" + } + $vmObject.ResourcePool = $resourcePoolObj.id + } + return $vmObject +} + +function Build_Datastore_List_Farm { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmVirtualCenterStorageSettings]$StorageObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.HostOrClusterId]$HostClusterID + ) + if (!$storageObject) { + $storageObject = New-Object VMware.Hv.FarmVirtualCenterStorageSettings + + $FarmSpaceReclamationSettings = New-Object VMware.Hv.FarmSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $false } + + $FarmViewComposerStorageSettingsList = @{ + 'useSeparateDatastoresReplicaAndOSDisks' = $false; + 'replicaDiskDatastore' = $FarmReplicaDiskDatastore + 'useNativeSnapshots' = $false; + 'spaceReclamationSettings' = $FarmSpaceReclamationSettings; + } + + $storageObject.ViewComposerStorageSettings = New-Object VMware.Hv.FarmViewComposerStorageSettings -Property $FarmViewComposerStorageSettingsList + } + + if ($datastores) { + $Datastore_service_helper = New-Object VMware.Hv.DatastoreService + $datastoreList = $Datastore_service_helper.Datastore_ListDatastoresByHostOrCluster($services, $hostClusterID) + $datastoresSelected = @() + foreach ($ds in $datastores) { + $datastoresSelected += ($datastoreList | Where-Object { $_.datastoredata.name -eq $ds }).id + } + foreach ($ds in $datastoresSelected) { + $datastoresObj = New-Object VMware.Hv.FarmVirtualCenterDatastoreSettings + $datastoresObj.Datastore = $ds + $datastoresObj.StorageOvercommit = 'UNBOUNDED' + $StorageObject.Datastores += $datastoresObj + } + } + if ($storageObject.Datastores.Count -eq 0) { + throw "No datastores found with name: [$datastores]" + } + if ($useVSAN) { $storageObject.useVSAN = $useVSAN } + return $storageObject +} + +function Build_Network_List_Farm { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmVirtualCenterNetworkingSettings]$NetworkObject + ) + if (!$networkObject) { + $networkObject = $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings + } + return $networkObject +} + +function Build_Customization_Settings_Farm { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmCustomizationSettings]$CustomObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID + ) + if (!$customObject) { + $ViewComposerDomainAdministrator_service_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService + $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministrator_service_helper.ViewComposerDomainAdministrator_List($services, $vcID) | Where-Object { $_.base.domain -cmatch $netBiosName }) + if (! [string]::IsNullOrWhitespace($domainAdmin)) { + $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministratorID | Where-Object { $_.base.userName -ieq $domainAdmin }).id + } else { + $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id + } + if ($null -eq $ViewComposerDomainAdministratorID) { + throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" + } + $ADDomain_service_helper = New-Object VMware.Hv.ADDomainService + $adDomianId = ($ADDomain_service_helper.ADDomain_List($services) | Where-Object { $_.NetBiosName -eq $netBiosName } | Select-Object -Property id) + if ($null -eq $adDomianId) { + throw "No Domain found with netBiosName: [$netBiosName]" + } + $ad_containder_service_helper = New-Object VMware.Hv.AdContainerService + $adContainerId = ($ad_containder_service_helper.ADContainer_ListByDomain($services, $adDomianId.id) | Where-Object { $_.Rdn -eq $adContainer } | Select-Object -Property id).id + if ($null -eq $adContainerId) { + throw "No AdContainer found with name: [$adContainer]" + } + #Support only Sysprep Customization + $sysprepCustomizationSettings = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings + + # Get SysPrep CustomizationSpec ID + $CustomizationSpec_service_helper = New-Object VMware.Hv.CustomizationSpecService + $sysPrepIds = $CustomizationSpec_service_helper.CustomizationSpec_List($services, $vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id + if ($sysPrepIds.Count -eq 0) { + throw "No Sysprep Customization spec found with Name: [$sysPrepName]" + } + $sysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id + + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.DomainAdministrator = $ViewComposerDomainAdministratorID + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.AdContainer = $adContainerId + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.ReusePreExistingAccounts = $false + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings = $sysprepCustomizationSettings + + $customObject = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings + } + return $customObject +} + +function Get_Farm_Spec { + param( + [Parameter(Mandatory = $true)] + [string]$FarmType, + + [Parameter(Mandatory = $false)] + [string]$ProvisioningType, + + [Parameter(Mandatory = $false)] + [string]$NamingMethod + ) + + $farm_helper = New-Object VMware.Hv.FarmService + $farm_spec_helper = $farm_helper.getFarmSpecHelper() + $farm_spec_helper.setType($farmType) + if ($farmType -eq 'AUTOMATED') { + $farm_spec_helper.getDataObject().AutomatedFarmSpec.RdsServerNamingSpec.PatternNamingSettings = $farm_helper.getFarmPatternNamingSettingsHelper().getDataObject() + $farm_spec_helper.getDataObject().AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings = $farm_helper.getFarmViewComposerStorageSettingsHelper().getDataObject() + } elseif ($farmType -eq 'MANUAL') { + # No need to set + } + return $farm_spec_helper.getDataObject() +} + +function New-HVPool { +<# +.Synopsis + Creates new desktop pool. + +.DESCRIPTION + Creates new desktop pool, the type and user assignment type would be + determined based on input parameters. + +.PARAMETER InstantClone + Switch to Create Instant Clone pool. + +.PARAMETER LinkedClone + Switch to Create Linked Clone pool. + +.PARAMETER FullClone + Switch to Create Full Clone pool. + +.PARAMETER Manual + Switch to Create Manual Clone pool. + +.PARAMETER Rds + Switch to Create RDS pool. + +.PARAMETER PoolName + Name of the pool. + +.PARAMETER PoolDisplayName + Display name of pool. + +.PARAMETER Description + Description of pool. + +.PARAMETER AccessGroup + View access group can organize the desktops in the pool. + Default Value is 'Root'. + +.PARAMETER GlobalEntitlement + Description of pool. + Global entitlement to associate the pool. + +.PARAMETER UserAssignment + User Assignment type of pool. + Set to DEDICATED for dedicated desktop pool. + Set to FLOATING for floating desktop pool. + +.PARAMETER AutomaticAssignment + Automatic assignment of a user the first time they access the machine. + Applicable to dedicated desktop pool. + +.PARAMETER Enable + Set true to enable the pool otherwise set to false. + +.PARAMETER ConnectionServerRestrictions + Connection server restrictions. + This is a list of tags that access to the desktop is restricted to. + No list means that the desktop can be accessed from any connection server. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) where the pool virtual machines are located. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER Template + Virtual machine Template name to clone Virtual machines. + Applicable only to Full Clone pools. + +.PARAMETER ParentVM + Parent Virtual Machine to clone Virtual machines. + Applicable only to Linked Clone and Instant Clone pools. + +.PARAMETER SnapshotVM + Base image VM for Linked Clone pool and current Image for Instant Clone Pool. + +.PARAMETER VmFolder + VM folder to deploy the VMs to. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER HostOrCluster + Host or cluster to deploy the VMs in. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER ResourcePool + Resource pool to deploy the VMs. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER Datastores + Datastore names to store the VM + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER UseVSAN + Whether to use vSphere VSAN. This is applicable for vSphere 5.5 or later. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER StopOnProvisioningError + Set to true to stop provisioning of all VMs on error. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER TransparentPageSharingScope + The transparent page sharing scope. + The default value is 'VM'. + +.PARAMETER NamingMethod + Determines how the VMs in the desktop are named. + Set SPECIFIED to use specific name. + Set PATTERN to use naming pattern. + The default value is PATTERN. For Instant Clone pool the value must be PATTERN. + +.PARAMETER NamingPattern + Virtual machines will be named according to the specified naming pattern. + Value would be considered only when $namingMethod = PATTERN. + The default value is poolName + '{n:fixed=4}'. + +.PARAMETER MinReady + Minimum number of ready (provisioned) machines during View Composer maintenance operations. + The default value is 0. + Applicable to Linked Clone Pools. + +.PARAMETER MaximumCount + Maximum number of machines in the pool. + The default value is 1. + Applicable to Full, Linked, Instant Clone Pools + +.PARAMETER SpareCount + Number of spare powered on machines in the pool. + The default value is 1. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER ProvisioningTime + Determines when machines are provisioned. + Supported values are ON_DEMAND, UP_FRONT. + The default value is UP_FRONT. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER MinimumCount + The minimum number of machines to have provisioned if on demand provisioning is selected. + The default value is 0. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER SpecificNames + Specified names of VMs in the pool. + The default value is -1 + Applicable to Full, Linked and Cloned Pools. + +.PARAMETER StartInMaintenanceMode + Set this to true to allow virtual machines to be customized manually before users can log + in and access them. + the default value is false + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER NumUnassignedMachinesKeptPoweredOn + Number of unassigned machines kept powered on. value should be less than max number of vms in the pool. + The default value is 1. + Applicable to Full, Linked, Instant Clone Pools. + When JSON Spec file is used for pool creation, the value will be read from JSON spec. + +.PARAMETER AdContainer + This is the Active Directory container which the machines will be added to upon creation. + The default value is 'CN=Computers'. + Applicable to Instant Clone Pool. + +.PARAMETER NetBiosName + Domain Net Bios Name. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER DomainAdmin + Domain Administrator user name which will be used to join the domain. + Default value is null. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER CustType + Type of customization to use. + Supported values are 'CLONE_PREP','QUICK_PREP','SYS_PREP','NONE'. + Applicable to Full, Linked Clone Pools. + +.PARAMETER SysPrepName + The customization spec to use. + Applicable to Full, Linked Clone Pools. + +.PARAMETER Source + Source of the Virtual machines for manual pool. + Supported values are 'VIRTUAL_CENTER','UNMANAGED'. + Set VIRTUAL_CENTER for vCenter managed VMs. + Set UNMANAGED for Physical machines or VMs which are not vCenter managed VMs. + Applicable to Manual Pools. + +.PARAMETER VM + List of existing virtual machine names to add into manual pool. + Applicable to Manual Pools. + +.PARAMETER Farm + Farm to create RDS pools + Applicable to RDS Pools. + +.PARAMETER Spec + Path of the JSON specification file. + +.PARAMETER ClonePool + Existing pool info to clone a new pool. + +.PARAMETER HvServer + Reference to Horizon View Server to query the pools from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Create new automated linked clone pool with naming method pattern + New-HVPool -LinkedClone -PoolName 'vmwarepool' -UserAssignment FLOATING -ParentVM 'Agent_vmware' -SnapshotVM 'kb-hotfix' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -Datastores 'datastore1' -NamingMethod PATTERN -PoolDisplayName 'vmware linkedclone pool' -Description 'created linkedclone pool from ps' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "vmware2" -MinReady 1 -MaximumCount 1 -SpareCount 1 -ProvisioningTime UP_FRONT -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root + +.EXAMPLE + Create new automated linked clone pool by using JSON spec file + New-HVPool -Spec C:\VMWare\Specs\LinkedClone.json + +.EXAMPLE + Clone new pool from automated linked (or) full clone pool + Get-HVPool -PoolName 'vmwarepool' | New-HVPool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; + (OR) + $vmwarepool = Get-HVPool -PoolName 'vmwarepool'; New-HVPool -ClonePool $vmwarepool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; + +.EXAMPLE + Create new automated instant clone pool with naming method pattern + New-HVPool -InstantClone -PoolName "InsPoolvmware" -PoolDisplayName "insPool" -Description "create instant pool" -UserAssignment FLOATING -ParentVM 'Agent_vmware' -SnapshotVM 'kb-hotfix' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -NamingMethod PATTERN -Datastores 'datastore1' -NamingPattern "inspool2" -NetBiosName 'adviewdev' -DomainAdmin root + +.EXAMPLE + Create new automated full clone pool with naming method pattern + New-HVPool -FullClone -PoolName "FullClone" -PoolDisplayName "FullClonePra" -Description "create full clone" -UserAssignment DEDICATED -Template 'powerCLI-VM-TEMPLATE' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -Datastores 'datastore1' -NamingMethod PATTERN -NamingPattern 'FullCln1' -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root + +.EXAMPLE + Create new managed manual pool from virtual center managed VirtualMachines. + New-HVPool -MANUAL -PoolName 'manualVMWare' -PoolDisplayName 'MNLPUL' -Description 'Manual pool creation' -UserAssignment FLOATING -Source VIRTUAL_CENTER -VM 'PowerCLIVM1', 'PowerCLIVM2' + +.EXAMPLE + Create new unmanaged manual pool from unmanaged VirtualMachines. + New-HVPool -MANUAL -PoolName 'unmangedVMWare' -PoolDisplayName 'unMngPl' -Description 'unmanaged Manual Pool creation' -UserAssignment FLOATING -Source UNMANAGED -VM 'myphysicalmachine.vmware.com' + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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 = $true,ParameterSetName = 'INSTANT_CLONE')] + [switch] + $InstantClone, + + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [switch] + $LinkedClone, + + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [switch] + $FullClone, + + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [switch] + $Manual, + + [Parameter(Mandatory = $true,ParameterSetName = 'RDS')] + [switch] + $Rds, + + [Parameter(Mandatory = $true,ParameterSetName = 'JSON_FILE')] + [string] + $Spec, + + [Parameter(Mandatory = $true,ValueFromPipeline = $true,ParameterSetName = 'CLONED_POOL')] + $ClonePool, + + #desktopSpec.desktopBase.name + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'RDS')] + [Parameter(Mandatory = $true,ParameterSetName = 'CLONED_POOL')] + [string] + $PoolName, + + #desktopSpec.desktopBase.displayName + [Parameter(Mandatory = $false)] + [string] + $PoolDisplayName = $poolName, + + #desktopSpec.desktopBase.description + [Parameter(Mandatory = $false)] + [string] + $Description = ' ', + + #desktopSpec.desktopBase.accessGroup + [Parameter(Mandatory = $false)] + [string] + $AccessGroup = 'Root', + + #desktopSpec.globalEntitlement + [Parameter(Mandatory = $false)] + [string] + $GlobalEntitlement, + + #desktopSpec.automatedDesktopSpec.desktopUserAssignment.userAssigment if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.manualDesktopSpec.desktopUserAssignment.userAssigment if MANUAL + + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [ValidateSet('FLOATING','DEDICATED')] + [string] + $UserAssignment, + + #desktopSpec.automatedDesktopSpec.desktopUserAssignment.automaticAssignment + [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [boolean] + $AutomaticAssignment = $true, + + #desktopSpec.desktopSettings.enabled + [Parameter(Mandatory = $false)] + [boolean] + $Enable = $true, + + #desktopSpec.desktopSettings.connectionServerRestrictions + [Parameter(Mandatory = $false)] + [string[]] + $ConnectionServerRestrictions, + + #desktopSpec.automatedDesktopSpec.virtualCenter if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.manualDesktopSpec.virtualCenter if MANUAL + [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [string] + $Vcenter, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.template if FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string] + $Template, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVM if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [string] + $ParentVM, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshotVM if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [string] + $SnapshotVM, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string] + $VmFolder, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.hostOrCluster if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string] + $HostOrCluster, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.resourcePool if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string] + $ResourcePool, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string[]] + $Datastores, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.useVSAN if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [string] + $UseVSAN, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [boolean] + $EnableProvisioning = $true, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [boolean] + $StopOnProvisioningError = $true, + + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] + [string] + $TransparentPageSharingScope = 'VM', + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.namingMethod if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] + [ValidateSet('SPECIFIED','PATTERN')] + [string] + $NamingMethod = 'PATTERN', + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.namingPattern if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] + [string] + $NamingPattern = $poolName + '{n:fixed=4}', + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [int] + $MinReady = 0, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.maxNumberOfMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [int] + $MaximumCount = 1, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.numberOfSpareMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [int] + $SpareCount = 1, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.provisioningTime if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [ValidateSet('ON_DEMAND','UP_FRONT')] + [string] + $ProvisioningTime = 'UP_FRONT', + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.minimumNumberOfMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [int] + $MinimumCount = 0, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.namingPattern if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] + [string[]] + $SpecificNames = $poolName + '-1', + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.startMachinesInMaintenanceMode if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [boolean] + $StartInMaintenanceMode = $false, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.numUnassignedMachinesKeptPoweredOnif LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = "JSON_FILE")] + [int] + $NumUnassignedMachinesKeptPoweredOn = 1, + + #desktopSpec.automatedDesktopSpec.customizationSettings.cloneprepCustomizationSettings.instantCloneEngineDomainAdministrator if INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + $AdContainer = 'CN=Computers', + + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [string]$NetBiosName, + + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string]$DomainAdmin = $null, + + #desktopSpec.automatedDesktopSpec.customizationSettings.customizationType if LINKED_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = "FULL_CLONE")] + [ValidateSet('CLONE_PREP','QUICK_PREP','SYS_PREP','NONE')] + [string] + $CustType, + + #desktopSpec.automatedDesktopSpec.customizationSettings.sysprepCustomizationSettings.customizationSpec if LINKED_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = "FULL_CLONE")] + [string] + $SysPrepName, + + #manual desktop + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [ValidateSet('VIRTUAL_CENTER','UNMANAGED')] + [string] + $Source, + + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $false,ParameterSetName = "JSON_FILE")] + [string[]]$VM, + + #farm + [Parameter(Mandatory = $false,ParameterSetName = 'RDS')] + [string] + $Farm, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + # + # + # + # DesktopSpec/DesktopInfo + # *DesktopBase + # +AccessGroupId + # &DesktopSettings + # DesktopLogoffSettings + # DesktopDisplayProtocolSettings + # DesktopPCoIPDisplaySettings + # DesktopAdobeFlashSettings + # DesktopAdobeFlashSettings + # DesktopMirageConfigurationOverrides + # DesktopAutomatedDesktopSpec/DesktopAutomatedDesktopData + # */+VirtualCenterId + # DesktopUserAssignment + # DesktopVirtualMachineNamingSpec/DesktopVirtualMachineNamingSettings + # DesktopPatternNamingSpec/DesktopPatternNamingSettings + # DesktopSpecificNamingSettings/DesktopSpecificNamingSettings + # DesktopVirtualCenterProvisioningSettings + # DesktopVirtualCenterProvisioningData/virtualCenterProvisioningData + # DesktopVirtualCenterStorageSettings + # DesktopVirtualCenterNetworkingSettings + # DesktopVirtualCenterManagedCommonSettings + # DesktopCustomizationSettings + # ViewComposerDomainAdministratorId + # ADContainerId + # DesktopNoCustomizationSettings + # DesktopSysprepCustomizationSettings + # CustomizationSpecId + # DesktopQuickprepCustomizationSettings + # DesktopQuickprepCustomizationSettings + # DesktopCloneprepCustomizationSettings + # InstantCloneEngineDomainAdministratorId + # DesktopManualDesktopSpec + # DesktopUserAssignment + # MachineId[] + # VirtualCenterId + # DesktopViewStorageAcceleratorSettings + # DesktopBlackoutTime[] + # DesktopVirtualCenterManagedCommonSettings + # DesktopRDSDesktopSpec + # DesktopBlackoutTime[] + # DesktopGlobalEntitlementData + # GlobalEntitlementId + + + # retrieve values from the pipeline ... takes care of "get-hvpool -poolName | New-HVPool -poolName common parameters + # + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + + if ($poolName) { + try { + $sourcePool = Get-HVPool -poolName $poolName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($sourcePool) { + Write-Error "Pool with name: [$poolName] already exists" + break + } + } + + if ($spec) { + try { + $jsonObject = Get_Json_Object -specFile $spec + } catch { + Write-Error "Json file exception, $_" + break + } + if ($jsonObject.type -eq "AUTOMATED") { + $poolType = 'AUTOMATED' + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenter) { + $vCenter = $jsonObject.AutomatedDesktopSpec.VirtualCenter + } + $userAssignment = $jsonObject.AutomatedDesktopSpec.userAssignment.userAssignment + $automaticAssignment = $jsonObject.AutomatedDesktopSpec.userAssignment.AutomaticAssignment + $netBiosName = $jsonObject.NetBiosName + if (!$jsonObject.AutomatedDesktopSpec.CustomizationSettings.AdContainer) { + Write-Host "adContainer was empty using CN=Computers" + } else { + $adContainer = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.AdContainer + } + $custType = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CustomizationType + if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "INSTANT_CLONE_ENGINE") { + $InstantClone = $true + } else { + if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "VIEW_COMPOSER") { + $LinkedClone = $true + } else { + $FullClone = $true + } + $sysPrepName = $jsonObject.SysPrepName + } + $namingMethod = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.NamingMethod + $transparentPageSharingScope = $jsonObject.AutomatedDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope + if ($namingMethod -eq "PATTERN") { + $namingPattern = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.namingPattern + $maximumCount = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.maxNumberOfMachines + $spareCount = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.numberOfSpareMachines + $provisioningTime = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.provisioningTime + } else { + $specificNames = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.specifiedNames + $startInMaintenanceMode = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode + $numUnassignedMachinesKeptPoweredOn = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Template) { + $template = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Template + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm) { + $parentVM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot) { + $snapshotVM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot + } + $vmFolder = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.VmFolder + $hostOrCluster = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.HostOrCluster + $resourcePool = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ResourcePool + $dataStoreList = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores + foreach ($dtStore in $dataStoreList) { + $datastores += $dtStore.Datastore + } + } elseif ($jsonObject.type -eq "MANUAL") { + $MANUAL = $true + $poolType = 'MANUAL' + $userAssignment = $jsonObject.ManualDesktopSpec.userAssignment.userAssignment + $automaticAssignment = $jsonObject.ManualDesktopSpec.userAssignment.AutomaticAssignment + $source = $jsonObject.ManualDesktopSpec.source + $VMs = $jsonObject.ManualDesktopSpec.Machines + foreach ($vmObj in $VMs) { + $VM += $vmObj.Machine + } + + } else { + $RDS = $true + $poolType = 'RDS' + $farm = $jsonObject.RdsDesktopSpec.farm + } + $poolDisplayName = $jsonObject.base.DisplayName + $description = $jsonObject.base.Description + $accessGroup = $jsonObject.base.AccessGroup + $poolName = $jsonObject.base.name + } + + if ($PSCmdlet.MyInvocation.ExpectingInput -or $clonePool) { + + if ($clonePool -and ($clonePool.GetType().name -eq 'DesktopSummaryView')) { + $clonePool = Get-HVPool -poolName $clonePool.desktopsummarydata.name -Full + } else { + Write-Error "In pipeline did not get object of expected type DesktopSummaryView" + return + } + $poolType = $clonePool.type + $desktopBase = $clonePool.base + $desktopSettings = $clonePool.DesktopSettings + $provisioningType = $null + if ($clonePool.AutomatedDesktopData) { + $provisioningType = $clonePool.AutomatedDesktopData.ProvisioningType + $virtualCenterID = $clonePool.AutomatedDesktopData.VirtualCenter + $desktopUserAssignment = $clonePool.AutomatedDesktopData.userAssignment + $desktopVirtualMachineNamingSpec = $clonePool.AutomatedDesktopData.VmNamingSettings + $DesktopVirtualCenterProvisioningSettings = $clonePool.AutomatedDesktopData.VirtualCenterProvisioningSettings + $DesktopVirtualCenterProvisioningData = $DesktopVirtualCenterProvisioningSettings.VirtualCenterProvisioningData + $DesktopVirtualCenterStorageSettings = $DesktopVirtualCenterProvisioningSettings.VirtualCenterStorageSettings + $DesktopVirtualCenterNetworkingSettings = $DesktopVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings + $desktopVirtualCenterManagedCommonSettings = $clonePool.AutomatedDesktopData.virtualCenterManagedCommonSettings + $desktopCustomizationSettings = $clonePool.AutomatedDesktopData.CustomizationSettings + } + if (($null -eq $provisioningType) -or ($provisioningType -eq 'INSTANT_CLONE_ENGINE')) { + Write-Error "Only Automated linked clone or full clone pool support cloning" + break + } + } else { + + if ($InstantClone) { + $poolType = 'AUTOMATED' + $provisioningType = 'INSTANT_CLONE_ENGINE' + } + elseif ($LinkedClone) { + $poolType = 'AUTOMATED' + $provisioningType = 'VIEW_COMPOSER' + } + elseif ($FullClone) { + $poolType = 'AUTOMATED' + $provisioningType = 'VIRTUAL_CENTER' + } + elseif ($Manual) { $poolType = 'MANUAL' } + elseif ($RDS) { $poolType = 'RDS' } + + } + $script:desktopSpecObj = Get_Desktop_Spec -poolType $poolType -provisioningType $provisioningType -namingMethod $namingMethod + + # + # accumulate properties that are shared among various type + # + + if ($poolType -ne 'RDS') { + # + # vCenter: if $vcenterID is defined, then this is a clone + # if the user specificed the name, then find it from the list + # if none specified, then automatically use the vCenter if there is only one + # + # skips Unmanged Manual pool for VC check + if (! (($poolType -eq 'MANUAL') -and ($source -eq 'UNMANAGED'))) { + + if (!$virtualCenterID) { + $virtualCenterID = Get_Vcenter_ID -services $services -vCenter $vCenter + } + if ($null -eq $virtualCenterID) { + $handleException = $true + break + } + } + # + # populate user assignment + # + if (!$desktopUserAssignment) { + if ($desktopSpecObj.AutomatedDesktopSpec) { + $desktopSpecObj.AutomatedDesktopSpec.userAssignment.userAssignment = $userAssignment + $desktopSpecObj.AutomatedDesktopSpec.userAssignment.AutomaticAssignment = $automaticAssignment + $desktopUserAssignment = $desktopSpecObj.AutomatedDesktopSpec.userAssignment + } else { + $desktopSpecObj.ManualDesktopSpec.userAssignment.userAssignment = $userAssignment + $desktopSpecObj.ManualDesktopSpec.userAssignment.AutomaticAssignment = $automaticAssignment + $desktopUserAssignment = $desktopSpecObj.ManualDesktopSpec.userAssignment + } + + } + # + # transparentPageSharingScope + # + if (!$desktopVirtualCenterManagedCommonSettings) { + if ($desktopSpecObj.AutomatedDesktopSpec) { + $desktopSpecObj.AutomatedDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope + $desktopVirtualCenterManagedCommonSettings = $desktopSpecObj.AutomatedDesktopSpec.virtualCenterManagedCommonSettings + } else { + $desktopSpecObj.ManualDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope + $desktopVirtualCenterManagedCommonSettings = $desktopSpecObj.ManualDesktopSpec.virtualCenterManagedCommonSettings + } + } + } + # + # build out the infrastructure based on type of provisioning + # + switch ($poolType) + { + 'RDS' { + <# + Query FarmId from Farm Name + #> + $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals + $QueryFilterEquals.memberName = 'data.name' + $QueryFilterEquals.value = $farm + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'FarmSummaryView' + $defn.Filter = $QueryFilterEquals + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $queryResults = $query_service_helper.QueryService_Query($services,$defn) + if ($queryResults.results.Count -eq 0) { + Write-Error "No farm found with name: [$farm]" + return + } + $farmID = $queryResults.results.id + $desktopSpecObj.RdsDesktopSpec.farm = $farmID + } + 'MANUAL' { + [VMware.Hv.MachineId[]]$machineList = $null + $desktopSpecObj.ManualDesktopSpec.source = $source + if ($source -eq 'VIRTUAL_CENTER') { + # Get vCenter VMs + $vmTable = @{} + $vm | ForEach-Object { $vmTable[$_] = $_ } + $virtual_machine_helper = New-Object VMware.Hv.VirtualMachineService + $machineId = ($virtual_machine_helper.VirtualMachine_List($services,$virtualCenterId) | Where-Object { $vmTable.Contains($_.name) } | Select-Object -Property Id) + $machineList += $machineId.id + $desktopSpecObj.ManualDesktopSpec.VirtualCenter = $virtualCenterID + } else { + # Get Physical Regstered VMs + $machineList = Get-RegisteredPhysicalMachines -services $services -machinesList $VM + } + $desktopSpecObj.ManualDesktopSpec.Machines = $machineList + } + default { + if (!$desktopVirtualMachineNamingSpec) { + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.NamingMethod = $namingMethod + if ($namingMethod -eq 'PATTERN') { + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.namingPattern = $namingPattern + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.maxNumberOfMachines = $maximumCount + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.numberOfSpareMachines = $spareCount + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.provisioningTime = $provisioningTime + + if ($provisioningTime -eq 'ON_DEMAND') { $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.minNumberOfMachines = $minimumCount } + } else { + $desktopSpecifiedName = @() + $specificNames | ForEach-Object { $desktopSpecifiedName += New-Object VMware.Hv.DesktopSpecifiedName -Property @{ 'vmName' = $_; } } + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.specifiedNames = $desktopSpecifiedName + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode = $startInMaintenanceMode + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn = $numUnassignedMachinesKeptPoweredOn + } + } else { + $vmNamingSpec = New-Object VMware.Hv.DesktopVirtualMachineNamingSpec + if ($desktopVirtualMachineNamingSpec.NamingMethod -eq 'PATTERN') { + $vmNamingSpec.NamingMethod = 'PATTERN' + $vmNamingSpec.patternNamingSettings = $desktopVirtualMachineNamingSpec.patternNamingSettings + $vmNamingSpec.patternNamingSettings.namingPattern = $namingPattern + } else { + $desktopSpecifiedName = @() + $specificNames | ForEach-Object { $desktopSpecifiedName += New-Object VMware.Hv.DesktopSpecifiedName -Property @{ 'vmName' = $_; } } + $vmNamingSpec.NamingMethod = 'SPECIFIED' + $vmNamingSpec.SpecificNamingSpec = New-Object VMware.Hv.DesktopSpecificNamingSpec + $vmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn = $desktopVirtualMachineNamingSpec.specificNamingSettings.numUnassignedMachinesKeptPoweredOn + $vmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode = $desktopVirtualMachineNamingSpec.specificNamingSettings.startMachinesInMaintenanceMode + $vmNamingSpec.SpecificNamingSpec.specifiedNames = $desktopSpecifiedName + } + + } + + # + # build the VM LIST + # + $handleException = $false + try { + $desktopVirtualCenterProvisioningData = Build_VM_List -vc $virtualCenterID -vmObject $desktopVirtualCenterProvisioningData + $hostClusterId = $desktopVirtualCenterProvisioningData.HostOrCluster + $desktopVirtualCenterStorageSettings = Build_Datastore_List -hostclusterID $hostClusterId -storageObject $desktopVirtualCenterStorageSettings + $DesktopVirtualCenterNetworkingSettings = Build_Network_List -networkObject $DesktopVirtualCenterNetworkingSettings + $desktopCustomizationSettings = Build_Customization_Settings -vc $virtualCenterID -customObject $desktopCustomizationSettings + } catch { + $handleException = $true + Write-Error "Failed to create Pool with error: $_" + break + } + + if (!$DesktopVirtualCenterProvisioningSettings) { + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.enableProvisioning = $true + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $true + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = 0 + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings = $desktopCustomizationSettings + $desktopSpecObj.AutomatedDesktopSpec.ProvisioningType = $provisioningType + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenter = $virtualCenterID + } + else { + $DesktopVirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData + $DesktopVirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings + $DesktopVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings + + $DesktopAutomatedDesktopSpec = New-Object VMware.Hv.DesktopAutomatedDesktopSpec + $DesktopAutomatedDesktopSpec.ProvisioningType = $provisioningType + $DesktopAutomatedDesktopSpec.VirtualCenter = $virtualCenterID + $DesktopAutomatedDesktopSpec.userAssignment = $desktopUserAssignment + $DesktopAutomatedDesktopSpec.VmNamingSpec = $vmNamingSpec + $DesktopAutomatedDesktopSpec.VirtualCenterProvisioningSettings = $desktopVirtualCenterProvisioningSettings + $DesktopAutomatedDesktopSpec.virtualCenterManagedCommonSettings = $desktopVirtualCenterManagedCommonSettings + $DesktopAutomatedDesktopSpec.CustomizationSettings = $desktopCustomizationSettings + } + } + } + + if ($handleException) { + break + } + if (!$desktopBase) { + $accessGroup_client = New-Object VMware.Hv.AccessGroupService + $ag = $accessGroup_client.AccessGroup_List($services) | Where-Object { $_.base.name -eq $accessGroup } + $desktopSpecObj.base.AccessGroup = $ag.id + } else { + $desktopSpecObj.base = $desktopBase + } + + $desktopSpecObj.base.name = $poolName + $desktopSpecObj.base.DisplayName = $poolDisplayName + $desktopSpecObj.base.Description = $description + $desktopSpecObj.type = $poolType + + if ($desktopSettings) { $desktopSpecObj.DesktopSettings = $desktopSettings } + + if ($desktopAutomatedDesktopSpec) { + $desktopSpecObj.AutomatedDesktopSpec = $desktopAutomatedDesktopSpec + } + if ($DesktopManualDesktopSpecList) { $desktopSpecObj.ManualDesktopSpec = $DesktopManualDesktopSpecList } + if ($desktopRDSDesktopSpec) { $desktopSpecObj.RdsDesktopSpec = $RDSDesktopSpec } + if ($desktopGlobalEntitlementData) { $desktopSpecObj.GlobalEntitlementData = $desktopGlobalEntitlementData } + + # Please uncomment below code, if you want save desktopSpec object to json file + <# + $myDebug = convertto-json -InputObject $desktopSpecObj -depth 12 + $myDebug | out-file -filepath c:\temp\copieddesktop.json + #> + $desktop_helper = New-Object VMware.Hv.DesktopService + $desktop_helper.Desktop_create($services,$desktopSpecObj) + } + + end { + $desktopSpecObj = $null + [System.gc]::collect() + } + +} + +function Build_VM_List { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopVirtualCenterProvisioningData]$VmObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID + ) + if (!$vmObject) { $vmObject = $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData } + if ($template) { + $vm_template_helper = New-Object VMware.Hv.VmTemplateService + $templateList = $vm_template_helper.VmTemplate_List($services,$vcID) + $templateVM = $templateList | Where-Object { $_.name -eq $template } + if ($null -eq $templateVM) { + throw "No template VM found with Name: [$template]" + } + $vmObject.Template = $templateVM.id + $dataCenterID = $templateVM.datacenter + $vmObject.datacenter = $dataCenterID + } + if ($parentVM) { + $base_imageVm_helper = New-Object VMware.Hv.BaseImageVmService + $parentList = $base_imageVm_helper.BaseImageVm_List($services,$vcID) + $parentVmObj = $parentList | Where-Object { $_.name -eq $parentVM } + if ($null -eq $parentVMObj) { + throw "No parent VM found with Name: [$parentVM]" + } + $vmObject.ParentVm = $parentVmObj.id + $dataCenterID = $parentVmObj.datacenter + $vmObject.datacenter = $dataCenterID + } + if ($snapshotVM) { + $baseImageSnapshot_helper = New-Object VMware.Hv.BaseImageSnapshotService + $snapshotList = $baseImageSnapshot_helper.BaseImageSnapshot_List($services,$parentVmObj.id) + $snapshotVmObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } + if ($null -eq $snapshotVmObj) { + throw "No sanpshot found with Name: [$snapshotVM]" + } + $vmObject.Snapshot = $snapshotVmObj.id + } + if ($vmFolder) { + $vmFolder_helper = New-Object VMware.Hv.VmFolderService + $folders = $vmFolder_helper.VmFolder_GetVmFolderTree($services,$vmObject.datacenter) + $folderList = @() + $folderList += $folders + while ($folderList.Length -gt 0) { + $item = $folderList[0] + if ($item -and !$_.folderdata.incompatiblereasons.inuse -and !$_.folderdata.incompatiblereasons.viewcomposerreplicafolder -and ($item.folderdata.name -eq $vmFolder)) { + $vmObject.VmFolder = $item.id + break + } + foreach ($folderItem in $item.children) { + $folderList += $folderItem + } + $folderList = $folderList[1..$folderList.Length] + } + if ($null -eq $vmObject.VmFolder) { + throw "No vmfolder found with Name: [$vmFolder]" + } + } + if ($hostOrCluster) { + $vmFolder_helper = New-Object VMware.Hv.HostOrClusterService + $hostClusterList = ($vmFolder_helper.HostOrCluster_GetHostOrClusterTree($services,$vmobject.datacenter)).treeContainer.children.info + $hostClusterObj = $hostClusterList | Where-Object { $_.name -eq $hostOrCluster } + if ($null -eq $hostClusterObj) { + throw "No hostOrCluster found with Name: [$hostOrCluster]" + } + $vmObject.HostOrCluster = $hostClusterObj.id + } + if ($resourcePool) { + $resourcePool_helper = New-Object VMware.Hv.ResourcePoolService + $resourcePoolList = $resourcePool_helper.ResourcePool_GetResourcePoolTree($services,$vmobject.HostOrCluster) + $resourcePoolObj = $resourcePoolList | Where-Object { $_.resourcepooldata.name -eq $resourcePool } + if ($null -eq $resourcePoolObj) { + throw "No hostOrCluster found with Name: [$resourcePool]" + } + $vmObject.ResourcePool = $resourcePoolObj.id + } + return $vmObject +} + +function Build_Datastore_List { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopVirtualCenterStorageSettings]$StorageObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.HostOrClusterId]$HostClusterID + ) + if (!$storageObject) { + $storageObject = New-Object VMware.Hv.DesktopVirtualCenterStorageSettings + $storageAcceleratorList = @{ + 'useViewStorageAccelerator' = $false + } + $desktopViewStorageAcceleratorSettings = New-Object VMware.Hv.DesktopViewStorageAcceleratorSettings -Property $storageAcceleratorList + $storageObject.viewStorageAcceleratorSettings = $desktopViewStorageAcceleratorSettings + $desktopSpaceReclamationSettings = New-Object VMware.Hv.DesktopSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $false } + $desktopPersistentDiskSettings = New-Object VMware.Hv.DesktopPersistentDiskSettings -Property @{ 'redirectWindowsProfile' = $false } + $desktopNonPersistentDiskSettings = New-Object VMware.Hv.DesktopNonPersistentDiskSettings -Property @{ 'redirectDisposableFiles' = $false } + + $desktopViewComposerStorageSettingsList = @{ + 'useSeparateDatastoresReplicaAndOSDisks' = $false; + 'useNativeSnapshots' = $false; + 'spaceReclamationSettings' = $desktopSpaceReclamationSettings; + 'persistentDiskSettings' = $desktopPersistentDiskSettings; + 'nonPersistentDiskSettings' = $desktopNonPersistentDiskSettings + } + if (!$FullClone) { + $storageObject.ViewComposerStorageSettings = New-Object VMware.Hv.DesktopViewComposerStorageSettings -Property $desktopViewComposerStorageSettingsList + } + } + if ($datastores) { + $datastore_helper = New-Object VMware.Hv.DatastoreService + $datastoreList = $datastore_helper.Datastore_ListDatastoresByHostOrCluster($services,$hostClusterID) + $datastoresSelected = @() + foreach ($ds in $datastores) { + $datastoresSelected += ($datastoreList | Where-Object { $_.datastoredata.name -eq $ds }).id + } + foreach ($ds in $datastoresSelected) { + $myDatastores = New-Object VMware.Hv.DesktopVirtualCenterDatastoreSettings + $myDatastores.Datastore = $ds + $mydatastores.StorageOvercommit = 'UNBOUNDED' + $storageObject.Datastores += $myDatastores + } + } + if ($storageObject.Datastores.Count -eq 0) { + throw "No datastore found with Name: [$datastores]" + } + if ($useVSAN) { $storageObject.useVSAN = $useVSAN } + return $storageObject +} + +function Build_Network_List { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopVirtualCenterNetworkingSettings]$NetworkObject + ) + if (!$networkObject) { + $networkObject = $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings + } + return $networkObject +} + +function Build_Customization_Settings { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopCustomizationSettings]$CustomObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID + ) + if (!$customObject) { + # View Composer and Instant Clone Engine Active Directory container for QuickPrep and ClonePrep. This must be set for Instant Clone Engine or SVI sourced desktops. + if ($InstantClone -or $LinkedClone) { + $ad_domain_helper = New-Object VMware.Hv.ADDomainService + $adDomianId = ($ad_domain_helper.ADDomain_List($services) | Where-Object { $_.NetBiosName -eq $netBiosName } | Select-Object -Property id) + if ($null -eq $adDomianId) { + throw "No Domain found with netBiosName: [$netBiosName]" + } + $ad_container_helper = New-Object VMware.Hv.AdContainerService + $adContainerId = ($ad_container_helper.ADContainer_ListByDomain($services,$adDomianId.id) | Where-Object { $_.Rdn -eq $adContainer } | Select-Object -Property id).id + if ($null -eq $adContainerId) { + throw "No AdContainer found with name: [$adContainer]" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.AdContainer = $adContainerId + } + if ($InstantClone) { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'CLONE_PREP' + $instantCloneEngineDomainAdministrator_helper = New-Object VMware.Hv.InstantCloneEngineDomainAdministratorService + $instantCloneEngineDomainAdministrator = ($instantCloneEngineDomainAdministrator_helper.InstantCloneEngineDomainAdministrator_List($services) | Where-Object { $_.namesData.dnsName -match $netBiosName }) + if (![string]::IsNullOrWhitespace($domainAdmin)) { + $instantCloneEngineDomainAdministrator = ($instantCloneEngineDomainAdministrator | Where-Object { $_.base.userName -eq $domainAdmin }).id + } else { + $instantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator[0].id + } + if ($null -eq $instantCloneEngineDomainAdministrator) { + throw "No Instant Clone Engine Domain Administrator found with netBiosName: [$netBiosName]" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings = Get_CustomizationSettings_Objects + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator + } + else { + if ($LinkedClone) { + $viewComposerDomainAdministrator_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService + $ViewComposerDomainAdministratorID = ($viewComposerDomainAdministrator_helper.ViewComposerDomainAdministrator_List($services,$vcID) | Where-Object { $_.base.domain -match $netBiosName }) + if (![string]::IsNullOrWhitespace($domainAdmin)) { + $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministratorID | Where-Object { $_.base.userName -ieq $domainAdmin }).id + } else { + $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id + } + if ($null -eq $ViewComposerDomainAdministratorID) { + throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" + } + if ($custType -eq 'SYS_PREP') { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings = Get_CustomizationSettings_Objects + + # Get SysPrep CustomizationSpec ID + $customization_spec_helper = New-Object VMware.Hv.CustomizationSpecService + $sysPrepIds = $customization_spec_helper.CustomizationSpec_List($services,$vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id + if ($sysPrepIds.Count -eq 0) { + throw "No Sysprep Customization Spec found with Name: [$sysPrepName]" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id + } elseif ($custType -eq 'QUICK_PREP') { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'QUICK_PREP' + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings = Get_CustomizationSettings_Objects + } else { + throw "The customization type: [$custType] is not supported for LinkedClone Pool" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.DomainAdministrator = $ViewComposerDomainAdministratorID + } elseif ($FullClone) { + if ($custType -eq 'SYS_PREP') { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings = Get_CustomizationSettings_Objects + # Get SysPrep CustomizationSpec ID + $customization_spec_helper = New-Object VMware.Hv.CustomizationSpecService + $sysPrepIds = $customization_spec_helper.CustomizationSpec_List($services,$vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id + if ($sysPrepIds.Count -eq 0) { + throw "No Sysprep Customization Spec found with Name: [$sysPrepName]" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id + } elseif ($custType -eq 'NONE') { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings = Get_CustomizationSettings_Objects + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings.DoNotPowerOnVMsAfterCreation = $false + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = "NONE" + } else { + throw "The customization type: [$custType] is not supported for FullClone Pool." + } + } + } + $customObject = $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings + } + return $customObject +} + +function Get_CustomizationSettings_Objects { + if ($InstantClone) { + return New-Object VMware.Hv.DesktopCloneprepCustomizationSettings + } elseif ($LinkedClone) { + if ($custType -eq 'QUICK_PREP') { + return New-Object VMware.Hv.DesktopQuickPrepCustomizationSettings + } else { + return New-Object VMware.Hv.DesktopSysPrepCustomizationSettings + } + } else { + if ($custType -eq 'SYS_PREP') { + return New-Object VMware.Hv.DesktopSysPrepCustomizationSettings + } else { + return New-Object VMware.Hv.DesktopNoCustomizationSettings + } + } +} + +function Get_Desktop_Spec { + + param( + [Parameter(Mandatory = $true)] + [string]$PoolType, + + [Parameter(Mandatory = $false)] + [string]$ProvisioningType, + + [Parameter(Mandatory = $false)] + [string]$NamingMethod + ) + $desktop_helper = New-Object VMware.Hv.DesktopService + $desktop_spec_helper = $desktop_helper.getDesktopSpecHelper() + $desktop_spec_helper.setType($poolType) + if ($poolType -eq $desktop_spec_helper.TYPE_AUTOMATED) { + if ($namingMethod -eq 'PATTERN') { + $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings = $desktop_helper.getDesktopPatternNamingSettingsHelper().getDataObject() + } else { + $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec = $desktop_helper.getDesktopSpecificNamingSpecHelper().getDataObject() + } + if ($provisioningType -ne 'VIRTUAL_CENTER') { + $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings = $desktop_helper.getDesktopViewComposerStorageSettingsHelper().getDataObject() + } + } elseif ($poolType -eq 'MANUAL') { + $desktop_spec_helper.getDataObject().ManualDesktopSpec.userAssignment = $desktop_helper.getDesktopUserAssignmentHelper().getDataObject() + $desktop_spec_helper.getDataObject().ManualDesktopSpec.viewStorageAcceleratorSettings = $desktop_helper.getDesktopViewStorageAcceleratorSettingsHelper().getDataObject() + $desktop_spec_helper.getDataObject().ManualDesktopSpec.virtualCenterManagedCommonSettings = $desktop_helper.getDesktopVirtualCenterManagedCommonSettingsHelper().getDataObject() + } else { + $desktop_spec_helper.getDataObject().RdsDesktopSpec = $desktop_helper.getDesktopRDSDesktopSpecHelper().getDataObject() + } + return $desktop_spec_helper.getDataObject() + +} + +function Remove-HVFarm { +<# +.SYNOPSIS + Deletes specified farm(s). + +.DESCRIPTION + This function deletes the farm(s) with the specified name/object(s) from the Connection Server. Optionally, user can pipe the farm object(s) as input to this function. + +.PARAMETER FarmName + Name of the farm to be deleted. + +.PARAMETER Farm + Object(s) of the farm to be deleted. Object(s) should be of type FarmSummaryView/FarmInfo. + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Remove-HVFarm -FarmName 'Farm-01' -HvServer $hvServer + +.EXAMPLE + $farm_array | Remove-HVFarm -HvServer $hvServer + +.EXAMPLE + $farm1 = Get-HVFarm -FarmName 'Farm-01' + Remove-HVFarm -Farm $farm1 + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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 = $true,ParameterSetName = 'option')] + [string] + [ValidateNotNullOrEmpty()] $FarmName, + + # Farmobject + [Parameter(ValueFromPipeline = $true,Mandatory = $true,ParameterSetName = 'pipeline')] + [ValidateNotNullOrEmpty()] $Farm, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $farmList = @() + if ($farmName) { + try { + $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($farmSpecObj) { + foreach ($farmObj in $farmSpecObj) { + $farmList += $farmObj.id + } + } else { + Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farmName]" + break + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + foreach ($item in $farm) { + if ($item.GetType().name -eq 'FarmInfo' -or $item.GetType().name -eq 'FarmSummaryView') { + $farmList += $item.id + } + else { + Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" + [System.gc]::collect() + return + } + } + } + $farm_service_helper = New-Object VMware.Hv.FarmService + foreach ($item in $farmList) { + $farm_service_helper.Farm_Delete($services, $item) + } + Write-Host "Farm Deleted" + + } + end { + [System.gc]::collect() + } +} + +function Remove-HVPool { +<# +.SYNOPSIS + Deletes specified pool(s). + +.DESCRIPTION + This function deletes the pool(s) with the specified name/object(s) from Connection Server. This can be used for deleting any pool irrespective of its type. + Optionally, user can pipe the pool object(s) as input to this function. + +.PARAMETER PoolName + Name of the pool to be deleted. + +.PARAMETER Pool + Object(s) of the pool to be deleted. + +.PARAMETER DeleteFromDisk + Switch parameter to delete the virtual machine(s) from the disk. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER TerminateSession + Logs off a session forcibly to virtual machine(s). This operation will also log off a locked session. + +.EXAMPLE + Remove-HVPool -HvServer $hvServer -PoolName 'FullClone' -DeleteFromDisk + +.EXAMPLE + $pool_array | Remove-HVPool -HvServer $hvServer -DeleteFromDisk + +.EXAMPLE + Remove-HVPool -Pool $pool1 + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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,ParameterSetName = 'option')] + [string] $poolName, + + # PoolObject + [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] + $Pool, + + [Parameter(Mandatory = $false)] + [switch] $TerminateSession = $false, + + [Parameter(Mandatory = $false)] + [switch] $DeleteFromDisk, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $poolList = @() + if ($poolName) { + try { + $myPools = get-hvpool -poolName $poolName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($myPools) { + foreach ($poolObj in $myPools) { + $poolList += $poolObj.id + } + } else { + Write-Error "No desktopsummarydata found with pool name: [$pool]" + break + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + foreach ($item in $pool) { + if (($item.GetType().name -eq 'DesktopInfo') -or ($item.GetType().name -eq 'DesktopSummaryView')) { + $poolList += $item.id + } + else { + Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" + [System.gc]::collect() + return + } + } + } + $desktop_service_helper = New-Object VMware.Hv.DesktopService + $deleteSpec = New-Object VMware.Hv.DesktopDeleteSpec + $deleteSpec.DeleteFromDisk = $deleteFromDisk + foreach ($item in $poolList) { + if ($terminateSession) { + #Terminate session + $queryResults = Get-HVQueryResults MachineSummaryView (Get-HVQueryFilter base.desktop -eq $item) + $sessions += $queryResults.base.session + + if ($null -ne $sessions) { + $session_service_helper = New-Object VMware.Hv.SessionService + try { + Write-Host "Terminating Sessions, it may take few seconds..." + $session_service_helper.Session_LogoffSessionsForced($services,$sessions) + } catch { + Write-Host "Warning: Terminate Session failed." + } + } else { + Write-Host "No session found." + } + } + Write-Host "Deleting Pool" + $desktop_service_helper.Desktop_Delete($services,$item,$deleteSpec) + } + } + + end { + [System.gc]::collect() + } +} + +function Set-HVFarm { +<# +.SYNOPSIS + Edit farm configuration by passing key/values as parameters/json. + +.DESCRIPTION + This function allows user to edit farm configuration by passing key/value pairs. Optionally, user can pass a JSON spec file. User can also pipe the farm object(s) as input to this function. + +.PARAMETER FarmName + Name of the farm to edit. + +.PARAMETER Farm + Object(s) of the farm to edit. Object(s) should be of type FarmSummaryView/FarmInfo. + +.PARAMETER Key + Property names path separated by . (dot) from the root of desktop spec. + +.PARAMETER Value + Property value corresponds to above key name. + +.PARAMETER Spec + Path of the JSON specification file containing key/value pair. + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Set-HVFarm -FarmName 'Farm-o1' -Spec 'C:\Edit-HVFarm\ManualEditFarm.json' + +.EXAMPLE + Set-HVFarm -FarmName 'Farm-o1' -Key 'base.description' -Value 'updated description' + +.EXAMPLE + $farm_array | Set-HVFarm -Key 'base.description' -Value 'updated description' + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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,ParameterSetName = 'option')] + [string]$FarmName, + + [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] + $Farm, + + [Parameter(Mandatory = $false)] + [string]$Key, + + [Parameter(Mandatory = $false)] + $Value, + + [Parameter(Mandatory = $false)] + [string]$Spec, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $farmList = @() + if ($farmName) { + try { + $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($farmSpecObj) { + foreach ($farmObj in $farmSpecObj) { + $farmList += $farmObj.id + } + } else { + Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farmName]" + break + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + foreach ($item in $farm) { + if ($item.GetType().name -eq 'FarmInfo' -or $item.GetType().name -eq 'FarmSummaryView') { + $farmList += $item.id + } + else { + Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" + [System.gc]::collect() + return + } + } + } + + $updates = @() + if ($key -and $value) { + $updates += Get_MapEntry -key $key -value $value + } elseif ($key -or $value) { + Write-Error "Both key:[$key] and value:[$value] need to be specified" + } + if ($spec) { + $specObject = Get_Json_Object -specFile $spec + foreach ($member in ($specObject.PSObject.Members | Where-Object { $_.MemberType -eq 'NoteProperty' })) { + $updates += Get_MapEntry -key $member.name -value $member.value + } + } + $farm_service_helper = New-Object VMware.Hv.FarmService + foreach ($item in $farmList) { + $farm_service_helper.Farm_Update($services,$item,$updates) + } + } + + end { + $updates = $null + [System.gc]::collect() + } +} + +function Set-HVPool { +<# +.SYNOPSIS + Sets the existing pool properties. + +.DESCRIPTION + This cmdlet allows user to edit pool configuration by passing key/value pair. Optionally, user can pass a JSON spec file. + +.PARAMETER PoolName + Name of the pool to edit. + +.PARAMETER Pool + Object(s) of the pool to edit. + +.PARAMETER Key + Property names path separated by . (dot) from the root of desktop spec. + +.PARAMETER Value + Property value corresponds to above key name. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER Spec + Path of the JSON specification file containing key/value pair. + +.EXAMPLE + Set-HVPool -PoolName 'ManualPool' -Spec 'C:\Edit-HVPool\EditPool.json' + +.EXAMPLE + Set-HVPool -PoolName 'RDSPool' -Key 'base.description' -Value 'update description' + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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,ParameterSetName = 'option')] + [string]$PoolName, + + #pool object + [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] + $Pool, + + [Parameter(Mandatory = $false)] + [string]$Key, + + [Parameter(Mandatory = $false)] + $Value, + + [Parameter(Mandatory = $false)] + [string]$Spec, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $poolList = @() + if ($poolName) { + try { + $desktopPools = Get-HVPool -poolName $poolName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($desktopPools) { $poolList += $desktopPools.id } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + foreach ($item in $pool) { + if (($item.GetType().name -eq 'DesktopInfo') -or ($item.GetType().name -eq 'DesktopSummaryView')) { + $poolList += $item.id + } + else { + Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" + [System.gc]::collect() + return + } + } + } + $updates = @() + if ($key -and $value) { + $updates += Get_MapEntry -key $key -value $value + } elseif ($key -or $value) { + Write-Error "Both key:[$key] and value:[$value] needs to be specified" + } + if ($spec) { + try { + $specObject = Get_Json_Object -specFile $spec + } catch { + Write-Error "Json file exception, $_" + return + } + foreach ($member in ($specObject.PSObject.Members | Where-Object { $_.MemberType -eq 'NoteProperty' })) { + $updates += Get_MapEntry -key $member.name -value $member.value + } + } + + $desktop_helper = New-Object VMware.Hv.DesktopService + foreach ($item in $poolList) { + $desktop_helper.Desktop_Update($services,$item,$updates) + } + } + + end { + [System.gc]::collect() + } +} + +function Start-HVFarm { +<# +.SYNOPSIS + Perform maintenance tasks on the farm(s). + +.DESCRIPTION + This function is used to perform maintenance tasks like enable/disable, start/stop and recompose the farm. + +.PARAMETER Farm + Name/Object(s) of the farm. Object(s) should be of type FarmSummaryView/FarmInfo. + +.PARAMETER Enable + Switch to enable the farm(s). + +.PARAMETER Disable + Switch to disable the farm(s). + +.PARAMETER Start + Switch to enable provisioning immediately for the farm(s). It's applicable only for 'AUTOMATED' farm type. + +.PARAMETER Stop + Switch to disable provisioning immediately for the farm(s). It's applicable only for 'AUTOMATED' farm type. + +.PARAMETER Recompose + Switch for recompose operation. Requests a recompose of RDS Servers in the specified 'AUTOMATED' farm. This marks the RDS Servers for recompose, which is performed asynchronously. + +.PARAMETER StartTime + Specifies when to start the operation. If unset, the operation will begin immediately. + +.PARAMETER LogoffSetting + Determines when to perform the operation on machines which have an active session. This property will be one of: + "FORCE_LOGOFF" - Users will be forced to log off when the system is ready to operate on their RDS Servers. Before being forcibly logged off, users may have a grace period in which to save their work (Global Settings). + "WAIT_FOR_LOGOFF" - Wait for connected users to disconnect before the task starts. The operation starts immediately on RDS Servers without active sessions. + +.PARAMETER StopOnFirstError + Indicates that the operation should stop on first error. + +.PARAMETER Servers + The RDS Server(s) id to recompose. Provide a comma separated list for multiple RDSServerIds. + +.PARAMETER ParentVM + New base image VM for automated farm's RDS Servers. This must be in the same datacenter as the base image of the RDS Server. + +.PARAMETER SnapshotVM + Base image snapshot for the Automated Farm's RDS Servers. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) of the given farm. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Start-HVFarm -Recompose -Farm 'Farm-01' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' + +.EXAMPLE + Start-HVFarm -Farm 'Farm-01' -Enable + +.EXAMPLE + Start-HVFarm -Farm 'Farm-01' -Disable + +.EXAMPLE + Start-HVFarm -Farm 'Farm-01' -Start + +.EXAMPLE + Start-HVFarm -Farm 'Farm-01' -Stop + +.EXAMPLE + $myTime = Get-Date '10/03/2016 12:30:00' + Start-HVFarm -Farm 'Farm-01' -Recompose -LogoffSetting 'FORCE_LOGOFF' -ParentVM 'ParentVM' -SnapshotVM 'SnapshotVM' -StartTime $myTime + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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 = $true,ValueFromPipeline = $true)] + $Farm, + + [Parameter(Mandatory = $false,ParameterSetName = 'ENABLE')] + [switch]$Enable, + + [Parameter(Mandatory = $false,ParameterSetName = 'DISABLE')] + [switch]$Disable, + + [Parameter(Mandatory = $false,ParameterSetName = 'START')] + [switch]$Start, + + [Parameter(Mandatory = $false,ParameterSetName = 'STOP')] + [switch]$Stop, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [switch]$Recompose, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [System.DateTime]$StartTime, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [ValidateSet('FORCE_LOGOFF','WAIT_FOR_LOGOFF')] + [string]$LogoffSetting, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [boolean]$StopOnFirstError = $true, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [string []]$Servers, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [string]$ParentVM, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [string]$SnapshotVM, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [string]$Vcenter, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $farmList = @{} + $farmType = @{} + $farmSource = @{} + $farm_service_helper = New-Object VMware.Hv.FarmService + if ($farm) { + if ($farm.GetType().name -eq 'FarmInfo') { + $id = $farm.id + $name = $farm.data.name + $type = $farm.type + } + elseif ($farm.GetType().name -eq 'FarmSummaryView') { + $id = $farm.id + $name = $farm.data.name + $type = $farm.data.type + } + elseif ($farm.GetType().name -eq 'String') { + try { + $farmSpecObj = Get-HVFarm -farmName $farm -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($farmSpecObj) { + $id = $farmSpecObj.id + $name = $farmSpecObj.data.name + $type = $farmSpecObj.data.type + } else { + Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farm]" + break + } + } else { + Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" + break + } + if ($type -eq 'AUTOMATED') { + $source = 'VIEW_COMPOSER' + } + $farmList.Add($id,$name) + $farmType.Add($id,$type) + $farmSource.Add($id,$source) + } + } + + + end { + foreach ($item in $farmList.Keys) { + $operation = $PsCmdlet.ParameterSetName + Write-Host "Performing $operation" on $farmList.$item + switch ($operation) { + 'RECOMPOSE' { + if ($farmSource.$item -ne 'VIEW_COMPOSER') { + Write-Error "RECOMPOSE operation is not supported for farm with name [$farmList.$item]" + break + } else { + $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter + if ($null -eq $vcId) { + break + } + $serverList = Get-AllRDSServersInFarm -services $services -farm $item -serverList $servers + if ($null -eq $serverList) { + Write-Error "No servers found for the farm [$item]" + } + $spec = New-Object VMware.Hv.FarmRecomposeSpec + $spec.LogoffSetting = $logoffSetting + $spec.StopOnFirstError = $stopOnFirstError + $spec.RdsServers = $serverList + try { + $spec = Set_Spec_Vms_Farm -vcId $vcId -spec $spec + } catch { + Write-Error "RECOMPOSE task failed with error: $_" + break + } + if ($startTime) { $spec.startTime = $startTime } + # Update Base Image VM and Snapshot in Farm + $updates = @() + $updates += Get_MapEntry -key 'automatedFarmData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVm' -value $spec.ParentVM + $updates += Get_MapEntry -key 'automatedFarmData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshot' -value $spec.Snapshot + $farm_service_helper.Farm_Update($services,$item,$updates) + + $farm_service_helper.Farm_Recompose($services,$item,$spec) + } + } + 'ENABLE' { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'data.enabled' + $map.value = $true + $farm_service_helper.Farm_Update($services,$item,$map) + } + 'DISABLE' { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'data.enabled' + $map.value = $false + $farm_service_helper.Farm_Update($services,$item,$map) + } + 'START' { + if ($farmType.$item -ne 'AUTOMATED') { + Write-Error "Start operation is not supported for farm with name [$farmList.$item]" + break + } else { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'automatedFarmData.virtualCenterProvisioningSettings.enableProvisioning' + $map.value = $true + $farm_service_helper.Farm_Update($services,$item,$map) + } + } + 'STOP' { + if ($farmType.$item -ne 'AUTOMATED') { + Write-Error "STOP operation is not supported for farm with name [$farmList.$item]" + break + } else { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'automatedFarmData.virtualCenterProvisioningSettings.enableProvisioning' + $map.value = $false + $farm_service_helper.Farm_Update($services,$item,$map) + } + } + } + return + } + } + +} + +function Get-AllRDSServersInFarm ($Services,$Farm,$ServerList) { + [VMware.Hv.RDSServerId[]]$servers = @() + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $remainingCount = 1 # run through loop at least once + $query = New-Object VMware.Hv.QueryDefinition + $query.queryEntityType = 'RDSServerSummaryView' + $farmFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'MemberName' = 'base.farm'; 'value' = $farm } + if ($serverList) { + $serverFilters = [VMware.Hv.queryFilter[]]@() + foreach ($name in $serverList) { + $serverFilters += (New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $name }) + } + $serverList = New-Object VMware.Hv.QueryFilterOr -Property @{ 'filters' = $serverFilters } + $treeList = @() + $treeList += $serverList + $treelist += $farmFilter + $query.Filter = New-Object VMware.Hv.QueryFilterAnd -Property @{ 'filters' = $treeList } + } else { + $query.Filter = $farmFilter + } + while ($remainingCount -ge 1) { + $queryResults = $query_service_helper.QueryService_Query($services,$query) + $results = $queryResults.results + $servers += $results.id + $query.StartingOffset = $query.StartingOffset + $queryResults.results.Count + $remainingCount = $queryResults.RemainingCount + } + return $servers +} + +function Set_Spec_Vms_Farm { + param( + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID, + + [Parameter(Mandatory = $true)] + $Spec + ) + if ($parentVM) { + $baseImage_service_helper = New-Object VMware.Hv.BaseImageVmService + $parentList = $baseImage_service_helper.BaseImageVm_List($services, $vcID) + $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } + if ($null -eq $parentVMObj) { + throw "No Parent VM found with name: [$parentVM]" + } + $spec.ParentVm = $parentVMObj.id + } + if ($snapshotVM) { + $parentVM = $spec.ParentVm.id + $baseImageSnapshot_service_helper = New-Object VMware.Hv.BaseImageSnapshotService + $snapshotList = $baseImageSnapshot_service_helper.BaseImageSnapshot_List($services, $spec.ParentVm) + $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } + if ($null -eq $snapshotVMObj) { + throw "No Snapshot found with name: [$snapshotVM] for VM name: [$parentVM] " + } + $spec.Snapshot = $snapshotVMObj.id + } + return $spec +} + +function Start-HVPool { +<# +.SYNOPSIS + Perform maintenance tasks on Pool. + +.DESCRIPTION + This cmdlet is used to perform maintenance tasks like enable/disable the pool, enable/disable the provisioning of a pool, refresh, rebalance, recompose, push image and cancel image. Push image and Cancel image tasks only applies for instant clone pool. + +.PARAMETER Pool + Name/Object(s) of the pool. + +.PARAMETER Enable + Switch parameter to enable the pool. + +.PARAMETER Disable + Switch parameter to disable the pool. + +.PARAMETER Start + Switch parameter to start the pool. + +.PARAMETER Stop + Switch parameter to stop the pool. + +.PARAMETER Refresh + Switch parameter to refresh operation. + +.PARAMETER Recompose + Switch parameter to recompose operation. + +.PARAMETER Rebalance + Switch parameter to rebalance operation. + +.PARAMETER SchedulePushImage + Switch parameter to push image operation. + +.PARAMETER CancelPushImage + Switch parameter to cancel push image operation. + +.PARAMETER StartTime + Specifies when to start the operation. If unset, the operation will begin immediately. + +.PARAMETER LogoffSetting + Determines when to perform the operation on machines which have an active session. This property will be one of: + 'FORCE_LOGOFF' - Users will be forced to log off when the system is ready to operate on their virtual machines. + 'WAIT_FOR_LOGOFF' - Wait for connected users to disconnect before the task starts. The operation starts immediately on machines without active sessions. + +.PARAMETER StopOnFirstError + Indicates that the operation should stop on first error. + +.PARAMETER Machines + The machine names to recompose. These must be associated with the pool. + +.PARAMETER ParentVM + New base image VM for the desktop. This must be in the same datacenter as the base image of the desktop. + +.PARAMETER SnapshotVM + Name of the snapshot used in pool deployment. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) of the given pool. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.EXAMPLE + Start-HVPool -Recompose -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' + +.EXAMPLE + Start-HVPool -Refresh -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF + +.EXAMPLE + $myTime = Get-Date '10/03/2016 12:30:00' + Start-HVPool -Eebalance -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -StartTime $myTime + +.EXAMPLE + Start-HVPool -SchedulePushImage -Pool 'InstantPool' -LogoffSetting FORCE_LOGOFF -ParentVM 'InsParentVM' -SnapshotVM 'InsSnapshotVM' + +.EXAMPLE + Start-HVPool -CancelPushImage -Pool 'InstantPool' + +.EXAMPLE + Start-HVPool -Pool 'TestPool' -Enable + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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( + # handles both objects and string + [Parameter(Mandatory = $true,ValueFromPipeline = $true)] + $Pool, + + [Parameter(Mandatory = $false,ParameterSetName = 'ENABLE')] + [switch]$Enable, + + [Parameter(Mandatory = $false,ParameterSetName = 'DISABLE')] + [switch]$Disable, + + [Parameter(Mandatory = $false,ParameterSetName = 'START')] + [switch]$Start, + + [Parameter(Mandatory = $false,ParameterSetName = 'STOP')] + [switch]$Stop, + + [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] + [switch]$Refresh, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [switch]$Recompose, + + [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] + [switch]$Rebalance, + + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [switch]$SchedulePushImage, + + [Parameter(Mandatory = $false,ParameterSetName = 'CANCEL_PUSH_IMAGE')] + [switch]$CancelPushImage, + + [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [System.DateTime]$StartTime, + + [Parameter(Mandatory = $true,ParameterSetName = 'REBALANCE')] + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $true,ParameterSetName = 'REFRESH')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [ValidateSet('FORCE_LOGOFF','WAIT_FOR_LOGOFF')] + [string]$LogoffSetting, + + [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [boolean]$StopOnFirstError = $true, + + [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] + [string []]$Machines, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [string]$ParentVM, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [string]$SnapshotVM, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [string]$Vcenter, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + + $poolList = @{} + $poolType = @{} + $poolSource = @{} + if ($pool) { + foreach ($item in $pool) { + if ($item.GetType().name -eq 'DesktopInfo') { + $id = $item.id + $name = $item.base.name + $source = $item.source + $type = $item.type + } elseif ($item.GetType().name -eq 'DesktopSummaryView') { + $id = $item.id + $name = $item.desktopsummarydata.name + $source = $item.desktopsummarydata.source + $type = $item.desktopsummarydata.type + } elseif ($item.GetType().name -eq 'String') { + try { + $poolObj = Get-HVPool -poolName $item -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($poolObj) { + $id = $poolObj.id + $name = $poolObj.desktopsummarydata.name + $source = $poolObj.desktopsummarydata.source + $type = $poolObj.desktopsummarydata.type + } else { + Write-Error "No desktopsummarydata found with pool name: [$item]" + break + } + } else { + Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" + break + } + $poolList.Add($id,$name) + $poolType.Add($id,$type) + $poolSource.Add($id,$source) + } + } + } + + end { + foreach ($item in $poolList.Keys) { + $operation = $PsCmdlet.ParameterSetName + Write-Host "Performing $operation on" $poolList.$item + $desktop_helper = New-Object VMware.Hv.DesktopService + switch ($operation) { + 'REBALANCE' { + $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRebalanceSpec' -desktopId $item + if ($null -ne $spec) { + # make sure current task on VMs, must be None + $desktop_helper.Desktop_Rebalance($services,$item,$spec) + } + } + 'REFRESH' { + $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRefreshSpec' -desktopId $item + if ($null -ne $spec) { + # make sure current task on VMs, must be None + $desktop_helper.Desktop_Refresh($services,$item,$spec) + } + } + 'RECOMPOSE' { + $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRecomposeSpec' -desktopId $item + if ($null -ne $spec) { + $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter + $spec = Set_Spec_Vms -vcId $vcId -spec $spec + + # make sure current task on VMs, must be None + $desktop_helper.Desktop_Recompose($services,$item,$spec) + + # Update Base Image VM and Snapshot in Pool + $updates = @() + $updates += Get_MapEntry -key 'automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVm' -value $spec.ParentVM + $updates += Get_MapEntry -key 'automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshot' -value $spec.Snapshot + $desktop_helper.Desktop_Update($services,$item,$updates) + + } + } + 'PUSH_IMAGE' { + if ($poolSource.$item -ne 'INSTANT_CLONE_ENGINE') { + Write-Error "$poolList.$item is not a INSTANT CLONE pool" + break + } else { + $spec = New-Object VMware.Hv.DesktopPushImageSpec + $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter + $spec = Set_Spec_Vms -vcId $vcId -spec $spec + $spec.Settings = New-Object VMware.Hv.DesktopPushImageSettings + $spec.Settings.LogoffSetting = $logoffSetting + $spec.Settings.StopOnFirstError = $stopOnFirstError + if ($startTime) { $spec.Settings.startTime = $startTime } + $desktop_helper.Desktop_SchedulePushImage($services,$item,$spec) + } + } + 'CANCEL_PUSH_IMAGE' { + if ($poolSource.$item -ne 'INSTANT_CLONE_ENGINE') { + Write-Error "$poolList.$item is not a INSTANT CLONE pool" + break + } else { + $desktop_helper.Desktop_CancelScheduledPushImage($services,$item) + } + } + 'ENABLE' { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'desktopSettings.enabled' + $map.value = $true + $desktop_helper.Desktop_Update($services,$item,$map) + } + 'DISABLE' { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'desktopSettings.enabled' + $map.value = $false + $desktop_helper.Desktop_Update($services,$item,$map) + } + 'START' { + if ($poolType.$item -ne 'Automated') { + Write-Error "$poolList.$item is not a Automated pool" + break + } else { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'automatedDesktopData.virtualCenterProvisioningSettings.enableProvisioning' + $map.value = $true + $desktop_helper.Desktop_Update($services,$item,$map) + } + } + 'STOP' { + if ($poolType.$item -ne 'Automated') { + Write-Error "$poolList.$item is not a Automated pool" + break + } else { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'automatedDesktopData.virtualCenterProvisioningSettings.enableProvisioning' + $map.value = $false + $desktop_helper.Desktop_Update($services,$item,$map) + } + } + } + } + } +} + +function Get-Machines ($Pool,$MachineList) { + [VMware.Hv.MachineId[]]$machines = @() + $remainingCount = 1 # run through loop at least once + $query = New-Object VMware.Hv.QueryDefinition + $query.queryEntityType = 'MachineSummaryView' + $poolFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'MemberName' = 'base.desktop'; 'value' = $pool } + if ($machineList) { + $machineFilters = [vmware.hv.queryFilter[]]@() + foreach ($name in $machineList) { + $machineFilters += (New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $name }) + } + $machineList = New-Object VMware.Hv.QueryFilterOr -Property @{ 'filters' = $machineFilters } + $treeList = @() + $treeList += $machineList + $treelist += $poolFilter + $query.Filter = New-Object VMware.Hv.QueryFilterAnd -Property @{ 'filters' = $treeList } + } else { + $query.Filter = $poolFilter + } + while ($remainingCount -ge 1) { + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $queryResults = $query_service_helper.QueryService_Query($services, $query) + $results = $queryResults.results + $machines += $results.id + $query.StartingOffset = $query.StartingOffset + $queryResults.results.Count + $remainingCount = $queryResults.RemainingCount + } + return $machines +} + +function Set_Spec_Vms { + param( + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID, + + [Parameter(Mandatory = $true)] + $Spec + ) + if ($parentVM) { + $baseimage_helper = New-Object VMware.Hv.BaseImageVmService + $parentList = $baseimage_helper.BaseImageVm_List($services,$vcID) + $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } + $spec.ParentVm = $parentVMObj.id + } + if ($snapshotVM) { + $baseimage_snapshot_helper = New-Object VMware.Hv.BaseImageSnapshotService + $snapshotList = $baseimage_snapshot_helper.BaseImageSnapshot_List($services,$spec.ParentVm) + $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } + $spec.Snapshot = $snapshotVMObj.id + } + return $spec +} + +function Get_TaskSpec { + param( + [Parameter(Mandatory = $true)] + [string]$Source, + + [Parameter(Mandatory = $true)] + [string]$PoolName, + + [Parameter(Mandatory = $true)] + [string]$Operation, + + [Parameter(Mandatory = $true)] + [string]$TaskSpecName, + + [Parameter(Mandatory = $true)] + $DesktopId + + ) + if ($source -ne 'VIEW_COMPOSER') { + Write-Error "$operation task is not supported for pool type: [$source]" + return $null + } + $machineList = Get-Machines $desktopId $machines + if ($machineList.Length -eq 0) { + Write-Error "Failed to get any Virtual Center machines with the given pool name: [$poolName]" + return $null + } + $spec = Get_New_Object -TypeName $taskSpecName + $spec.LogoffSetting = $logoffSetting + $spec.StopOnFirstError = $stopOnFirstError + $spec.Machines = $machineList + if ($startTime) { $spec.startTime = $startTime } + return $spec +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVEvent,Get-HVFarm,Get-HVPool,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool From a316ba5dda1d68b8cd4c32fa09eeb94def6b26ee Mon Sep 17 00:00:00 2001 From: praveenmathamsetty Date: Tue, 15 Nov 2016 11:27:06 +0530 Subject: [PATCH 14/20] Revert "temp" This reverts commit 3c686ecaba0b778caeeaeab349437477ca00f1be. --- .../New-HVFarm/AutomatedLinkedCloneFarm.json | 80 - .../New-HVFarm/ManualFarm.json | 24 - .../New-HVPool/FullClone.json | 82 - .../New-HVPool/InstantClone.json | 105 - .../New-HVPool/LinkedClone.json | 105 - .../New-HVPool/ManualSpec.json | 35 - .../VMware.Hv.Helper/New-HVPool/RdsSpec.json | 16 - .../Set-HVFarm/AutomatedEditFarm.json | 6 - .../Set-HVFarm/ManualEditFarm.json | 5 - .../Set-HVPool/AutomatedEditPool.Json | 8 - .../Set-HVPool/ManualEditPool.json | 8 - .../Set-HVPool/RdsEditPool.json | 6 - .../VMware.Hv.Helper/VMware.HV.Helper.psd1 | 95 - .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 4743 ----------------- 14 files changed, 5318 deletions(-) delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/ManualFarm.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/FullClone.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/InstantClone.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/LinkedClone.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/ManualSpec.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/RdsSpec.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psd1 delete mode 100644 Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psm1 diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json deleted file mode 100644 index 3706374..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "Type": "AUTOMATED", - "Data": { - "Name": "LCFarmTest", - "DisplayName": "Ankit LC Farm Test", - "AccessGroup": "Root", - "Description": "created LC Farm from PS", - "Enabled": null, - "Deleting": false, - "Settings": null, - "Desktop": null, - "DisplayProtocolSettings": null, - "ServerErrorThreshold": null, - "MirageConfigurationOverrides": null - }, - "AutomatedFarmSpec": { - "ProvisioningType": "VIEW_COMPOSER", - "VirtualCenter": null, - "RdsServerNamingSpec": { - "NamingMethod": "PATTERN", - "PatternNamingSettings": { - "NamingPattern": "LCFarmVM_PS", - "MaxNumberOfRDSServers": 1 - } - }, - "VirtualCenterProvisioningSettings": { - "EnableProvisioning": true, - "StopProvisioningOnError": true, - "MinReadyVMsOnVComposerMaintenance": 0, - "VirtualCenterProvisioningData": { - "ParentVm": "Win_Server_2012_R2", - "Snapshot": "Snap_RDS", - "Datacenter": null, - "VmFolder": "AnkitPoolVM", - "HostOrCluster": "cls", - "ResourcePool": "cls" - }, - "VirtualCenterStorageSettings": { - "Datastores": [ - { - "Datastore": "datastore1 (5)", - "StorageOvercommit": "UNBOUNDED" - } - ], - "UseVSan": false, - "ViewComposerStorageSettings": { - "UseSeparateDatastoresReplicaAndOSDisks": false, - "ReplicaDiskDatastore": null, - "UseNativeSnapshots": false, - "SpaceReclamationSettings": { - "ReclaimVmDiskSpace": false, - "ReclamationThresholdGB": null, - "BlackoutTimes": null - } - } - }, - "VirtualCenterNetworkingSettings": { - "Nics": null - } - }, - "VirtualCenterManagedCommonSettings": { - "TransparentPageSharingScope": "VM" - }, - "CustomizationSettings": { - "CustomizationType": "SYS_PREP", - "DomainAdministrator": null, - "AdContainer": "CN=Computers", - "ReusePreExistingAccounts": false, - "SysprepCustomizationSettings": { - "CustomizationSpec": "RDSH_Cust2" - } - }, - "RdsServerMaxSessionsData": { - "MaxSessionsType": "UNLIMITED", - "MaxSessions": null - } - }, - "ManualFarmSpec": null, - "NetBiosName" : "adankit" -} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/ManualFarm.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/ManualFarm.json deleted file mode 100644 index cf674c1..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVFarm/ManualFarm.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "Type": "MANUAL", - "Data": { - "Name": "manualFarmTest", - "DisplayName": "manualFarmTest", - "AccessGroup": "Root", - "Description": "Manual PS Test", - "Enabled": null, - "Deleting": false, - "Settings": null, - "Desktop": null, - "DisplayProtocolSettings": null, - "ServerErrorThreshold": null, - "MirageConfigurationOverrides": null - }, - "AutomatedFarmSpec": null, - "ManualFarmSpec": { - "RdsServers": [ - { - "rdsServer": "WIN-ORKA1Q8B0P7" - } - ] - } -} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/FullClone.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/FullClone.json deleted file mode 100644 index 2ae9539..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/FullClone.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "Base": { - "Name" : "FulClnJSON", - "DisplayName": "FullClonePraJSON", - "AccessGroup": "Root", - "Description": "create full clone via JSON" - }, - "DesktopSettings": null, - "Type": "AUTOMATED", - "AutomatedDesktopSpec": { - "ProvisioningType": "VIRTUAL_CENTER", - "VirtualCenter": null, - "UserAssignment": { - "UserAssignment": "DEDICATED", - "AutomaticAssignment": true - }, - "VmNamingSpec": { - "NamingMethod": "PATTERN", - "PatternNamingSettings": { - "NamingPattern": "FullClnJson1", - "MaxNumberOfMachines": 1, - "NumberOfSpareMachines": 1, - "ProvisioningTime": "UP_FRONT", - "MinNumberOfMachines": null - }, - "SpecificNamingSpec": null - }, - "VirtualCenterProvisioningSettings": { - "EnableProvisioning": true, - "StopProvisioningOnError": true, - "MinReadyVMsOnVComposerMaintenance": 0, - "VirtualCenterProvisioningData": { - "Template": "powerCLI-VM-TEMPLATE", - "ParentVm": null, - "Snapshot": null, - "Datacenter": null, - "VmFolder": "Praveen", - "HostOrCluster": "CS-1", - "ResourcePool": "CS-1" - }, - "VirtualCenterStorageSettings": { - "Datastores": [ - { - "Datastore": "datastore1", - "StorageOvercommit": "UNBOUNDED" - } - ], - "UseVSan": false, - "ViewComposerStorageSettings": null, - "ViewStorageAcceleratorSettings": { - "UseViewStorageAccelerator": false, - "ViewComposerDiskTypes": null, - "RegenerateViewStorageAcceleratorDays": null, - "BlackoutTimes": null - } - }, - "VirtualCenterNetworkingSettings": { - "Nics": null - } - }, - "VirtualCenterManagedCommonSettings": { - "TransparentPageSharingScope": "VM" - }, - "CustomizationSettings": { - "CustomizationType": "SYS_PREP", - "DomainAdministrator": null, - "AdContainer": "CN=Computers", - "ReusePreExistingAccounts": false, - "NoCustomizationSettings": { - "DoNotPowerOnVMsAfterCreation": false - }, - "SysprepCustomizationSettings": null, - "QuickprepCustomizationSettings": null, - "CloneprepCustomizationSettings": null - } - }, - "ManualDesktopSpec": null, - "RdsDesktopSpec": null, - "GlobalEntitlementData": null, - "NetBiosName" : "adviewdev", - "SysPrepName" : "praveencust" -} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/InstantClone.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/InstantClone.json deleted file mode 100644 index a8da482..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/InstantClone.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "Base": { - "Name" : "InsClnJSON", - "DisplayName": "insPoolPr", - "AccessGroup": "ROOT", - "Description": "create instant pool" - }, - "DesktopSettings": null, - "Type": "AUTOMATED", - "AutomatedDesktopSpec": { - "ProvisioningType": "INSTANT_CLONE_ENGINE", - "VirtualCenter": null, - "UserAssignment": { - "UserAssignment": "FLOATING", - "AutomaticAssignment": true - }, - "VmNamingSpec": { - "NamingMethod": "PATTERN", - "PatternNamingSettings": { - "NamingPattern": "inspoolJson1", - "MaxNumberOfMachines": 1, - "NumberOfSpareMachines": 1, - "ProvisioningTime": "UP_FRONT", - "MinNumberOfMachines": null - }, - "SpecificNamingSpec": null - }, - "VirtualCenterProvisioningSettings": { - "EnableProvisioning": true, - "StopProvisioningOnError": true, - "MinReadyVMsOnVComposerMaintenance": 0, - "VirtualCenterProvisioningData": { - "Template": null, - "ParentVm": "Agent_pra", - "Snapshot": "kb-hotfix", - "Datacenter": null, - "VmFolder": "Praveen", - "HostOrCluster": "CS-1", - "ResourcePool": "CS-1" - }, - "VirtualCenterStorageSettings": { - "Datastores": [ - { - "Datastore": "datastore1", - "StorageOvercommit": "UNBOUNDED" - } - ], - "UseVSan": false, - "ViewComposerStorageSettings": { - "UseSeparateDatastoresReplicaAndOSDisks": false, - "ReplicaDiskDatastore": null, - "UseNativeSnapshots": false, - "SpaceReclamationSettings": { - "ReclaimVmDiskSpace": false, - "ReclamationThresholdGB": null - }, - "PersistentDiskSettings": { - "RedirectWindowsProfile": false, - "UseSeparateDatastoresPersistentAndOSDisks": null, - "PersistentDiskDatastores": null, - "DiskSizeMB": null, - "DiskDriveLetter": null - }, - "NonPersistentDiskSettings": { - "RedirectDisposableFiles": false, - "DiskSizeMB": null, - "DiskDriveLetter": null - } - }, - "ViewStorageAcceleratorSettings": { - "UseViewStorageAccelerator": false, - "ViewComposerDiskTypes": null, - "RegenerateViewStorageAcceleratorDays": null, - "BlackoutTimes": null - } - }, - "VirtualCenterNetworkingSettings": { - "Nics": null - } - }, - "VirtualCenterManagedCommonSettings": { - "TransparentPageSharingScope": "VM" - }, - "CustomizationSettings": { - "CustomizationType": "CLONE_PREP", - "DomainAdministrator": null, - "AdContainer": "CN=Computers", - "ReusePreExistingAccounts": false, - "NoCustomizationSettings": null, - "SysprepCustomizationSettings": null, - "QuickprepCustomizationSettings": null, - "CloneprepCustomizationSettings": { - "InstantCloneEngineDomainAdministrator": null, - "PowerOffScriptName": null, - "PowerOffScriptParameters": null, - "PostSynchronizationScriptName": null, - "PostSynchronizationScriptParameters": null - } - } - }, - "ManualDesktopSpec": null, - "RdsDesktopSpec": null, - "GlobalEntitlementData": null, - "NetBiosName" : "adviewdev" -} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/LinkedClone.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/LinkedClone.json deleted file mode 100644 index 53171a6..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/LinkedClone.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "Base": { - "Name" : "LnkClnJSon", - "DisplayName": "praveen linkedclone pool", - "AccessGroup": "Root", - "Description": "created linkedclone pool from ps" - }, - "DesktopSettings": null, - "Type": "AUTOMATED", - "AutomatedDesktopSpec": { - "ProvisioningType": "VIEW_COMPOSER", - "VirtualCenter": null, - "UserAssignment": { - "UserAssignment": "FLOATING", - "AutomaticAssignment": true - }, - "VmNamingSpec": { - "NamingMethod": "PATTERN", - "PatternNamingSettings": { - "NamingPattern": "patternPra1", - "MaxNumberOfMachines": 1, - "NumberOfSpareMachines": 1, - "ProvisioningTime": "UP_FRONT", - "MinNumberOfMachines": null - }, - "SpecificNamingSpec": null - }, - "VirtualCenterProvisioningSettings": { - "EnableProvisioning": true, - "StopProvisioningOnError": true, - "MinReadyVMsOnVComposerMaintenance": 0, - "VirtualCenterProvisioningData": { - "Template": null, - "ParentVm": "Agent_pra", - "Snapshot": "kb-hotfix", - "Datacenter": null, - "VmFolder": "Praveen", - "HostOrCluster": "CS-1", - "ResourcePool": "CS-1" - }, - "VirtualCenterStorageSettings": { - "Datastores": [ - { - "Datastore": "datastore1", - "StorageOvercommit": "UNBOUNDED" - } - ], - "UseVSan": false, - "ViewComposerStorageSettings": { - "UseSeparateDatastoresReplicaAndOSDisks": false, - "ReplicaDiskDatastore": null, - "UseNativeSnapshots": false, - "SpaceReclamationSettings": { - "ReclaimVmDiskSpace": false, - "ReclamationThresholdGB": null - }, - "PersistentDiskSettings": { - "RedirectWindowsProfile": false, - "UseSeparateDatastoresPersistentAndOSDisks": null, - "PersistentDiskDatastores": null, - "DiskSizeMB": null, - "DiskDriveLetter": null - }, - "NonPersistentDiskSettings": { - "RedirectDisposableFiles": false, - "DiskSizeMB": null, - "DiskDriveLetter": null - } - }, - "ViewStorageAcceleratorSettings": { - "UseViewStorageAccelerator": false, - "ViewComposerDiskTypes": null, - "RegenerateViewStorageAcceleratorDays": null, - "BlackoutTimes": null - } - }, - "VirtualCenterNetworkingSettings": { - "Nics": null - } - }, - "VirtualCenterManagedCommonSettings": { - "TransparentPageSharingScope": "VM" - }, - "CustomizationSettings": { - "CustomizationType": "QUICK_PREP", - "DomainAdministrator": null, - "AdContainer": "CN=Computers", - "ReusePreExistingAccounts": false, - "NoCustomizationSettings": null, - "SysprepCustomizationSettings": null, - "QuickprepCustomizationSettings": { - "PowerOffScriptName": null, - "PowerOffScriptParameters": null, - "PostSynchronizationScriptName": null, - "PostSynchronizationScriptParameters": null - }, - "CloneprepCustomizationSettings": null - } - }, - "ManualDesktopSpec": null, - "RdsDesktopSpec": null, - "GlobalEntitlementData": null, - "NetBiosName" : "adviewdev", - "SysPrepName" : "praveencust" -} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/ManualSpec.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/ManualSpec.json deleted file mode 100644 index b302bba..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/ManualSpec.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "Base": { - "Name" : "MnlJson", - "DisplayName": "MNLPUL", - "AccessGroup": "ROOT", - "Description": "Manual pool creation" - }, - "DesktopSettings": null, - "Type": "MANUAL", - "AutomatedDesktopSpec": null, - "ManualDesktopSpec": { - "UserAssignment": { - "UserAssignment": "FLOATING", - "AutomaticAssignment": true - }, - "Source": "VIRTUAL_CENTER", - "Machines": [ - { - "Machine" : "PowerCLI-VM" - } - ], - "VirtualCenter": null, - "ViewStorageAcceleratorSettings": { - "UseViewStorageAccelerator": false, - "ViewComposerDiskTypes": null, - "RegenerateViewStorageAcceleratorDays": null, - "BlackoutTimes": null - }, - "VirtualCenterManagedCommonSettings": { - "TransparentPageSharingScope": "VM" - } - }, - "RdsDesktopSpec": null, - "GlobalEntitlementData": null -} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/RdsSpec.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/RdsSpec.json deleted file mode 100644 index 86b3571..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/New-HVPool/RdsSpec.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "Base": { - "Name" : "RdsJson", - "DisplayName": "TestRDSPS", - "AccessGroup": "Root", - "Description": "Testing PS" - }, - "DesktopSettings": null, - "Type": "RDS", - "AutomatedDesktopSpec": null, - "ManualDesktopSpec": null, - "RdsDesktopSpec": { - "Farm": "Farm2" - }, - "GlobalEntitlementData": null -} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json deleted file mode 100644 index cad9343..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "data.description" : "update through edit farm function", - "data.displayName" : "LCFarmTestUpdated1", - "data.displayProtocolSettings.defaultDisplayProtocol" : "PCOIP", - "automatedFarmData.virtualCenterManagedCommonSettings.transparentPageSharingScope" : "FARM" -} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json deleted file mode 100644 index 533c39f..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "data.description" : "update through edit farm function", - "data.displayName" : "ManualFarmTestUpdated1", - "data.displayProtocolSettings.defaultDisplayProtocol" : "PCOIP" -} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json deleted file mode 100644 index 9654b14..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "base.description" : "update through edit pool function", - "base.displayName" : "Henry2DspNm", - "desktopSettings.displayProtocolSettings.defaultDisplayProtocol" : "BLAST", - "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.useViewStorageAccelerator" : true, - "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.viewComposerDiskTypes" : "OS_DISKS", - "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.regenerateViewStorageAcceleratorDays" : 8 -} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json deleted file mode 100644 index 6fc8adc..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "base.description" : "update through edit pool", - "base.displayName" : "pooldisp", - "desktopSettings.displayProtocolSettings.defaultDisplayProtocol" : "BLAST", - "manualDesktopData.viewStorageAcceleratorSettings.useViewStorageAccelerator" : true, - "manualDesktopData.viewStorageAcceleratorSettings.viewComposerDiskTypes" : "OS_DISKS", - "manualDesktopData.viewStorageAcceleratorSettings.regenerateViewStorageAcceleratorDays" : 8 -} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json deleted file mode 100644 index 58bf859..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "base.description" : "update through edit pool function", - "base.displayName" : "RDS2DspNm", - "desktopSettings.flashSettings.quality" : "LOW", - "desktopSettings.flashSettings.throttling" : "CONSERVATIVE" -} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psd1 b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psd1 deleted file mode 100644 index 7d9e262..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psd1 +++ /dev/null @@ -1,95 +0,0 @@ -# -# Module manifest for module 'VMware.HV' -# -# Generated by: "VMware" -# -# Generated on: 9/20/2016 -# - -@{ - -# Script module or binary module file associated with this manifest. -# RootModule = '' - -# Version number of this module. -ModuleVersion = '1.0' - -# ID used to uniquely identify this module -GUID = '6d3f7fb5-4e52-43d8-91e1-f65f72532a1d' - -# Author of this module -Author = 'VMware' - -# Company or vendor of this module -CompanyName = 'VMware, Inc.' - -# Copyright statement for this module -Copyright = 'Copyright (c) 2016 VMware, Inc. All rights reserved.' - -# Description of the functionality provided by this module -# Description = 'This Windows PowerShell script module contains Advanced functions of VIEW API Service.' - -# Minimum version of the Windows PowerShell engine required by this module -# PowerShellVersion = '' - -# 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 the .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 = @('VMware.VimAutomation.HorizonView') - -# 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 = @('VMware.HV.Helper.psm1') - -# 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 = '*' - -# 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 -# PrivateData = '' - -# HelpInfo URI of this module -# HelpInfoURI = '' - -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' - -} diff --git a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psm1 deleted file mode 100644 index 3d533f5..0000000 --- a/Modules/VMware.Hv.Helper/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ /dev/null @@ -1,4743 +0,0 @@ -#Script Module : VMware.Hv.Helper -#Version : 1.0 - -#Copyright 2016 VMware, Inc. All Rights Reserved. - -#Permission is hereby granted, free of charge, to any person obtaining a copy of -#this software and associated documentation files (the "Software"), to deal in -#the Software without restriction, including without limitation the rights to -#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -#of the Software, and to permit persons to whom the Software is furnished to do -#so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in all -#copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -#SOFTWARE. - - -function Get_New_Object { - param( - [Parameter(Mandatory = $true)] - [string]$TypeName, - - [Parameter(Mandatory = $false)] - [System.Collections.Hashtable]$PropertyName - ) - $objStr = 'VMware.Hv.' + $typeName - return New-Object $objStr -Property $propertyName -} - -function Get_ViewAPI_Service { - param( - [Parameter(Mandatory = $false)] - $HvServer - ) - if ($null -ne $hvServer) { - if ($hvServer.GetType().name -ne 'ViewServerImpl') { - $type = $hvServer.GetType().name - Write-Error "Expected hvServer type is ViewServerImpl, but received: [$type]" - return $null - } - elseif ($hvServer.IsConnected) { - return $hvServer.ExtensionData - } - } elseif ($global:DefaultHVServers.Length -gt 0) { - if ($pscmdlet.ShouldProcess($global:DefaultHVServers[0].uid,'hvServer not specified, use default hvServer connection?')) { - $hvServer = $global:DefaultHVServers[0] - return $hvServer.ExtensionData - } - } - return $null -} - -function Get_Vcenter_ID { - param( - [Parameter(Mandatory = $true)] - $Services, - - [Parameter(Mandatory = $false)] - [string] - $Vcenter - ) - $vc_service_helper = New-Object VMware.Hv.VirtualCenterService - $vcList = $vc_service_helper.VirtualCenter_List($services) - if ($vCenter) { - #ServerSpec.ServerName is IP/FQDN of the vCenter server. Input vCenter will be IP/FQDN of the vcenter server - $virtualCenterId = ($vcList | Where-Object { $_.ServerSpec.ServerName -eq $vCenter }).id - if ($virtualCenterId.Count -ne 1) { - Write-Error "vCenter Server not found: [$vCenter], please make sure vCenter is added in Connection Server" - return $null - } - } - else { - if ($vcList.Count -ne 1) { - Write-Error "Multiple Vcenter servers found, please specify the vCenter Name" - return $null - } - else { $virtualCenterId = $vcList.id } - } - return $virtualCenterId -} - -function Get_Json_Object { - param( - [Parameter(Mandatory = $true)] - [string]$SpecFile - ) - try { - return Get-Content -Raw $specFile | ConvertFrom-Json - } catch { - throw "Failed to read json file [$specFile], $_" - } -} - -function Get_MapEntry { - param( - [Parameter(Mandatory = $true)] - $Key, - - [Parameter(Mandatory = $true)] - $Value - ) - - $update = New-Object VMware.Hv.MapEntry - $update.key = $key - $update.value = $value - return $update -} - -function Get-RegisteredPhysicalMachines ($Services,$MachinesList) { - [VMware.Hv.MachineId[]]$machines = $null - $query_service_helper = New-Object VMware.Hv.QueryServiceService - foreach ($machineName in $machinesList) { - $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals - $QueryFilterEquals.memberName = 'machineBase.name' - $QueryFilterEquals.value = $machineName - - $defn = New-Object VMware.Hv.QueryDefinition - $defn.queryEntityType = 'RegisteredPhysicalMachineInfo' - $defn.Filter = $QueryFilterEquals - - $queryResults = $query_service_helper.QueryService_Query($services,$defn) - $res = $queryResults.results - $machines += $res.id - } - return $machines -} - -function Get-RegisteredRDSServers ($Services,$ServerList) { - [VMware.Hv.RDSServerId[]]$servers = $null - $query_service_helper = New-Object VMware.Hv.QueryServiceService - foreach ($serverName in $serverList) { - $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals - $QueryFilterEquals.memberName = 'base.name' - $QueryFilterEquals.value = $serverName - - $defn = New-Object VMware.Hv.QueryDefinition - $defn.queryEntityType = 'RDSServerInfo' - $defn.Filter = $QueryFilterEquals - - $queryResults = $query_service_helper.QueryService_Query($services,$defn) - - $servers += $queryResults.results.id - } - if ($null -eq $servers) { - throw "No Registered RDS server found with name: [$serverList]" - } - return $servers -} -function Add-HVDesktop { -<# -.SYNOPSIS -Adds virtual machine to existing pool - -.DESCRIPTION -The Add-HVDesktop adds virtual machines to already exiting pools by using view API service object(hvServer) of Connect-HVServer cmdlet. VMs can be added to any of unmanaged manual, managed manual or Specified name. This advanced function do basic checks for pool and view API service connection existance, hvServer object is bound to specific connection server. - -.PARAMETER PoolName - Pool name to which new VMs are to be added. - -.PARAMETER Machines - List of virtual machine names which need to be added to the given pool. - -.PARAMETER Users - List of virtual machine users for given machines. - -.PARAMETER Vcenter - Virtual Center server-address (IP or FQDN) of the given pool. This should be same as provided to the Connection Server while adding the vCenter server. - -.PARAMETER HvServer - View API service object of Connect-HVServer cmdlet. - -.EXAMPLE - Add managed manual VMs to existing manual pool - Add-HVDesktop -PoolName 'ManualPool' -Machines 'manualPool1', 'manualPool2'. - -.EXAMPLE - Add virtual machines to automated specific named dedicated pool - Add-HVDesktop -PoolName 'SpecificNamed' -Machines 'vm-01', 'vm-02' -Users 'user1', 'user2' - -.EXAMPLE - Add machines to automated specific named Floating pool - Add-HVDesktop -PoolName 'SpecificNamed' -Machines 'vm-03', 'vm-04' - -.EXAMPLE - Add machines to unmanged manual pool - Add-HVDesktop -PoolName 'Unmanaged' -Machines 'desktop-1.eng.vmware.com' - -.NOTES - Author : Praveen Mathamsetty. - Author email : pmathamsetty@vmware.com - Version : 1.0 - Dependencies : Make sure pool already exists before adding VMs to it. - - ===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 = $true)] - [string] - $PoolName, - - [Parameter(Mandatory = $true)] - [string[]] - $Machines, - - [Parameter(Mandatory = $false)] - [string[]] - $Users, - - [Parameter(Mandatory = $false)] - [string] - $Vcenter, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - try { - $desktopPool = Get-HVPool -poolName $poolName -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVPool advanced function is loaded, $_" - break - } - if ($desktopPool) { - $id = $desktopPool.id - $type = $desktopPool.desktopsummarydata.type - $source = $desktopPool.desktopsummarydata.source - $userAssignment = $desktopPool.desktopsummarydata.userAssignment - } else { - Write-Error "Unable to retrieve DesktopSummaryView with given poolName: [$poolName]" - break - } - - $desktop_service_helper = New-Object VMware.Hv.DesktopService - $user_assignement_helper = $desktop_service_helper.getDesktopUserAssignmentHelper() - switch ($type) { - 'AUTOMATED' { - if (($userAssignment -eq $user_assignement_helper.USER_ASSIGNMENT_DEDICATED) -and ($machines.Length -ne $users.Length)) { - Write-Error "Parameters machines length: [$machines.Length] and users length: [$users.Length] should be of same size" - return - } - [VMware.Hv.DesktopSpecifiedName[]]$desktopSpecifiedNameArray = @() - $cnt = 0 - foreach ($machine in $machines) { - $specifiedNames = New-Object VMware.Hv.DesktopSpecifiedName - $specifiedNames.vmName = $machine - if ($userAssignment -eq $user_assignement_helper.USER_ASSIGNMENT_DEDICATED -and $users) { - try { - $specifiedNames.user = Get_UserId -user $users[$cnt] - } catch { - Write-Error "Unable to retrieve UserOrGroupId for user: [$users[$cnt]], $_" - return - } - } - $desktopSpecifiedNameArray += $specifiedNames - $cnt += 1 - } - $desktop_service_helper.Desktop_AddMachinesToSpecifiedNamingDesktop($services,$id,$desktopSpecifiedNameArray) - } - 'MANUAL' { - if ($source -eq 'UNMANAGED') { - $machineList = Get-RegisteredPhysicalMachines -services $services -machinesList $machines - if ($machineList.Length -eq 0) { - Write-Error "Failed to retrieve registerd physical machines with the given machines parameter" - return - } - } else { - $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter - $machineList = Get-MachinesByVCenter -machineList $machines -vcId $vcId - if ($machineList.Length -eq 0) { - Write-Error "Failed to get any Virtual Center machines with the given machines parameter" - return - } - } - $desktop_service_helper.Desktop_AddMachinesToManualDesktop($services,$id,$machineList) - } - default { - Write-Error "Only Automated/Manual pool types support this add operation" - break - } - } - } - - end { - [System.gc]::collect() - } -} - -function Get_UserId ($User) { - - $defn = New-Object VMware.Hv.QueryDefinition - $defn.queryEntityType = 'ADUserOrGroupSummaryView' - [VMware.Hv.QueryFilter[]]$filters = $null - $groupfilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.group'; 'value' = $false } - $userNameFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $user } - $treeList = @() - $treeList += $userNameFilter - $treelist += $groupfilter - $filterAnd = New-Object VMware.Hv.QueryFilterAnd - $filterAnd.Filters = $treelist - $defn.Filter = $filterAnd - $query_service_helper = New-Object VMware.Hv.QueryServiceService - $res = $query_service_helper.QueryService_Query($services,$defn) - if ($null -eq $res.results) { - throw "Query service did not return any users with given user name: [$user]" - } - return $res.results.id -} - -function Get-MachinesByVCenter ($MachineList,$VcId) { - - [VMware.Hv.MachineId[]]$machines = $null - $virtualMachine_helper = New-Object VMware.Hv.VirtualMachineService - $vcMachines = $virtualMachine_helper.VirtualMachine_List($services,$vcId) - $machineDict = @{} - foreach ($vMachine in $vcMachines) { - $machineDict.Add($vMachine.name,$vMachine.id) - } - foreach ($machineName in $machineList) { - if ($machineDict.Contains($machineName)) { - $machines += $machineDict.$machineName - } - } - return $machines -} -function Add-HVRDSServer { -<# -.SYNOPSIS - Add RDS Servers to an existing farm. - -.DESCRIPTION - The Add-HVRDSServer adds RDS Servers to already exiting farms by using view API service object(hvServer) of Connect-HVServer cmdlet. We can add RDSServers to manual farm type only. This advanced function do basic checks for farm and view API service connection existance. This hvServer is bound to specific connection server. - -.PARAMETER FarmName - farm name to which new RDSServers are to be added. - -.PARAMETER RdsServers - RDS servers names which need to be added to the given farm. Provide a comma separated list for multiple names. - -.PARAMETER HvServer - View API service object of Connect-HVServer cmdlet. - -.EXAMPLE - Add RDSServers to manual farm - Add-HVRDSServer -Farm "manualFarmTest" -RdsServers "vm-for-rds","vm-for-rds-2" - -.OUTPUTS - None - -.NOTES - Author : Ankit Gupta. - Author email : guptaa@vmware.com - Version : 1.0 - Dependencies : Make sure farm already exists before adding RDSServers to it. - - ===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 = $true,ValueFromPipeline = $true)] - $FarmName, - - [Parameter(Mandatory = $true)] - [string[]] - $RdsServers, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - try { - $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" - break - } - if ($farmSpecObj) { - $id = $farmSpecObj.id - $type = $farmSpecObj.data.type - - } else { - Write-Error "Unable to retrieve FarmSummaryView with given farmName: [$farmName]" - break - } - $farm_service_helper = New-Object VMware.Hv.FarmService - switch ($type) { - 'AUTOMATED' { - Write-Error "Only Manual farm types supported for this add operation" - break - } - 'MANUAL' { - try { - $serverList = Get-RegisteredRDSServers -services $services -serverList $rdsServers - $farm_service_helper.Farm_AddRDSServers($services, $id, $serverList) - } catch { - Write-Error "Failed to Add RDS Server to Farm with error: $_" - break - } - } - } - } - - end { - [System.gc]::collect() - } -} -[System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient") | Out-Null - -function Connect-HVEvent { -<# -.SYNOPSIS - This function is used to connect to the event database configured on Connection Server. - -.DESCRIPTION - This function queries the specified Connection Server for event database configuration and returns the connection object to it. If event database is not configured on specified connection server, it will return null. - Currently, Horizon 7 is supporting SQL server and Oracle 12c as event database servers. To configure event database, goto 'Event Database Configuration' tab in Horizon admin UI. - -.PARAMETER HvServer - View API service object of Connect-HVServer cmdlet. - -.PARAMETER DbUserName - User name to be used in database connection. If not passed, default database user name on the Connection Server will be used. - -.PARAMETER DbPassword - Password corresponds to 'dbUserName' user. - -.EXAMPLE - Connecting to the database with default username configured on Connection Server $hvServer. - Connect-HVEvent -HvServer $hvServer - -.EXAMPLE - Connecting to the database configured on Connection Server $hvServer with customised user name 'system'. - $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' - -.EXAMPLE - Connecting to the database with customised user name and password. - $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' -DbPassword 'censored' - -.EXAMPLE - Connecting to the database with customised user name and password, with password being a SecureString. - $password = Read-Host 'Database Password' -AsSecureString - $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' -DbPassword $password - -.OUTPUTS - Returns a custom object that has database connection as 'dbConnection' property. - -.NOTES - Author : Paramesh Oddepally. - Author email : poddepally@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()] - param( - [Parameter(Mandatory = $false)] - $DbPassword = $null, - - [Parameter(Mandatory = $false)] - $HvServer = $null, - - [Parameter(Mandatory = $false)] - [string]$DbUserName = $null - ) - - begin { - # Connect to Connection Server and call the View API service - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - $EventDatabaseHelper = New-Object VMware.Hv.EventDatabaseService - $EventDatabaseInfo = $EventDatabaseHelper.EventDatabase_Get($services) - - # Check whether event database is configured on the connection server - # If not, return empty - if (!$EventDatabaseInfo.EventDatabaseSet) { - Write-Error "Event Database is not configured on Connection Server. To configure Event DB, go to 'Events Configuration' Tab in Horizon Admin UI" - break - } - - $dbServer = $EventDatabaseInfo.Database.server - $dbType = $EventDatabaseInfo.Database.type - $dbPort = $EventDatabaseInfo.Database.port - $dbName = $EventDatabaseInfo.Database.name - if (!$dbUserName) { $dbUserName = $EventDatabaseInfo.Database.userName } - $dbTablePrefix = $EventDatabaseInfo.Database.tablePrefix - - if (!$dbPassword) { $dbPassword = Read-Host 'Database Password for' $dbUserName@$dbServer -AsSecureString } - - if ($dbType -eq "SQLSERVER") { - if ($dbPassword.GetType().name -eq 'String'){ - $password = ConvertTo-SecureString $dbPassword -AsPlainText -Force - } elseif ($dbPassword.GetType().name -eq 'SecureString') { - $password = $dbPassword - } else { - Write-Error "Unsupported type recieved for dbPassword: [$dbPassword]. dbpassword should either be String or SecureString type. " - break - } - $connectionString = "Data Source=$dbServer, $dbPort; Initial Catalog=$dbName;" - $connection = New-Object System.Data.SqlClient.SqlConnection ($connectionString) - $password.MakeReadOnly() - $connection.Credential = New-Object System.Data.SqlClient.SqlCredential($dbUserName, $password); - } elseif ($dbType -eq "ORACLE") { - if ($dbPassword.GetType().name -eq 'SecureString'){ - $password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($dbPassword)) - } elseif ($dbPassword.GetType().name -eq 'String') { - $password = $dbPassword - } else { - Write-Error "Unsupported type recieved for dbPassword: [$dbPassword]. dbpassword should either be String or SecureString type. " - break - } - $dataSource = "(DESCRIPTION = " + - "(ADDRESS = (PROTOCOL = TCP)(HOST = $dbServer)(PORT = $dbPort))" + - "(CONNECT_DATA =" + - "(SERVICE_NAME = $dbName))" + - ");" - $connectionString = "Data Source=$dataSource;User Id=$dbUserName;Password=$password;" - $connection = New-Object System.Data.OracleClient.OracleConnection ($connectionString) - } else { - Write-Error "Unsupported DB type received: [$dbType]" - break - } - } - - process { - try { - $connection.Open() - } catch { - Write-Error "Failed to connect to database server: [$dbServer], $_" - break - } - Write-Host "Successfully connected to $dbType database: [$dbServer]" - return New-Object pscustomobject -Property @{ dbConnection = $connection; dbTablePrefix = $dbTablePrefix; } - } - - end { - [System.gc]::collect() - } -} - -function Disconnect-HVEvent { -<# -.SYNOPSIS - This function is used to disconnect the database connection. - -.DESCRIPTION - This function will disconnect the database connection made earlier during Connect-HVEvent function. - -.PARAMETER HvDbServer - Connection object returned by Connect-HVEvent advanced function. This is a mandatory input. - -.EXAMPLE - Disconnecting the database connection on $hvDbServer. - Disconnect-HVEvent -HvDbServer $hvDbServer - -.OUTPUTS - None - -.NOTES - Author : Paramesh Oddepally. - Author email : poddepally@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()] - param( - [Parameter(Mandatory = $true)] - [pscustomobject]$HvDbServer - ) - - begin { - $dbConnection = $hvDbServer.dbConnection - - # Validate the hvDbServer type. If not of expected type, dbConnection will be null. - if ($null -eq $dbConnection) { - Write-Error "No valid connection object found on hvDbServer parameter: [$hvDbServer]" - break - } - - # validate the user connection type of dbConnection - if (!$dbConnection.GetType().name.Equals("SqlConnection") -and !$dbConnection.GetType().name.Equals("OracleConnection")) { - Write-Error "The dbConnection object in hvDbServer parameter is not an SQL/Oracle DB connection: [$hvDbServer.GetType().Name]" - break - } - } - - process { - $dbConnection.Close() - Write-Host "Successfully closed the database connection" - } - - end { - [System.gc]::collect() - } -} - -function Get-HVEvent { -<# -.SYNOPSIS - Queries the events from event database configured on Connection Server. - -.DESCRIPTION - This function is used to query the events information from event database. It returns the object that has events in five columns as UserName, Severity, EventTime, Module and Message. EventTime will show the exact time when the event got registered in the database and it follows timezone on database server. - User can apply different filters on the event columns using the filter parameters userFilter, severityFilter, timeFilter, moduleFilter, messageFilter. Mention that when multiple filters are provided then rows which satisify all the filters will be returned. - -.PARAMETER HvDbServer - Connection object returned by Connect-HVEvent advanced function. - -.PARAMETER TimePeriod - Timeperiod of the events that user is interested in. It can take following four values: - 'day' - Lists last one day events from database - 'week' - Lists last 7 days events from database - 'month' - Lists last 30 days events from database - 'all' - Lists all the events stored in database - -.PARAMETER FilterType - Type of filter action to be applied. The parameters userfilter, severityfilter, timefilter, modulefilter, messagefilter can be used along with this. It can take following values: - 'contains' - Retrieves the events that contains the string specified in filter parameters - 'startsWith' - Retrieves the events that starts with the string specified in filter parameters - 'isExactly' - Retrieves the events that exactly match with the string specified in filter parameters - -.PARAMETER UserFilter - String that can applied in filtering on 'UserName' column. - -.PARAMETER SeverityFilter - String that can applied in filtering on 'Severity' column. - -.PARAMETER TimeFilter - String that can applied in filtering on 'EventTime' column. - -.PARAMETER ModuleFilter - String that can applied in filtering on 'Module' column. - -.PARAMETER MessageFilter - String that can applied in filtering on 'Message' column. - -.EXAMPLE - Querying all the database events on database $hvDbServer. - $e = Get-HVEvent -hvDbServer $hvDbServer - $e.Events - -.EXAMPLE - Querying all the database events where user name startswith 'aduser', severity is of 'err' type, having module name as 'broker', message starting with 'aduser' and time starting with 'HH:MM:SS.fff'. - The resulting events will be exported to a csv file 'myEvents.csv'. - $e = Get-HVEvent -HvDbServer $hvDbServer -TimePeriod 'all' -FilterType 'startsWith' -UserFilter 'aduser' -SeverityFilter 'err' -TimeFilter 'HH:MM:SS.fff' -ModuleFilter 'broker' -MessageFilter 'aduser' - $e.Events | Export-Csv -Path 'myEvents.csv' -NoTypeInformation - -.OUTPUTS - Returns a custom object that has events information in 'Events' property. Events property will have events information with five columns: UserName, Severity, EventTime, Module and Message. - -.NOTES - Author : Paramesh Oddepally. - Author email : poddepally@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()] - param( - [Parameter(Mandatory = $true)] - [pscustomobject]$HvDbServer, - - [Parameter(Mandatory = $false)] - [ValidateSet('day','week','month','all')] - [string]$TimePeriod = 'all', - - [Parameter(Mandatory = $false)] - [ValidateSet('contains','startsWith','isExactly')] - [string]$FilterType = 'contains', - - [Parameter(Mandatory = $false)] - [string]$UserFilter = "", - - [Parameter(Mandatory = $false)] - [string]$SeverityFilter = "", - - [Parameter(Mandatory = $false)] - [string]$TimeFilter = "", - - [Parameter(Mandatory = $false)] - [string]$ModuleFilter = "", - - [Parameter(Mandatory = $false)] - [string]$MessageFilter = "" - ) - - begin { - $dbConnection = $hvDbServer.dbConnection - $dbTablePrefix = $hvDbServer.dbTablePrefix - - # database table names - $eventTable = $dbTablePrefix + "event" - $eventDataTable = $dbTablePrefix + "event_data" - - # Verify the connection type in connectObject type - $isSqlType = $dbConnection.GetType().name.Equals("SqlConnection") - $isOracleType = $dbConnection.GetType().name.Equals("OracleConnection") - - if ($isSqlType) { - $command = New-Object System.Data.Sqlclient.Sqlcommand - $adapter = New-Object System.Data.SqlClient.SqlDataAdapter - } elseif ($isOracleType) { - $command = New-Object System.Data.OracleClient.OracleCommand - $adapter = New-Object System.Data.OracleClient.OracleDataAdapter - } else { - Write-Error "The dbConnection object in hvDbServer parameter is not an SQL/Oracle DB connection:[$dbConnection.GetType().Name] " - break - } - } - - process { - $command.Connection = $dbConnection - - # Extract the filter parameters and build the filterQuery string - $filterQuery = "" - - if ($userFilter -ne "") { - $filterQuery = $filterQuery + " UserSID.StrValue" - if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$userFilter%'" } - elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$userFilter%'" } - else { $filterQuery = $filterQuery + " LIKE '$userFilter'" } - } - - if ($severityFilter -ne "") { - if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } - $filterQuery = $filterQuery + " Severity" - if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$severityFilter%'" } - elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$severityFilter%'" } - else { $filterQuery = " LIKE '$severityFilter'" } - } - - if ($moduleFilter -ne "") { - if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } - $filterQuery = $filterQuery + " Module" - if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$moduleFilter%'" } - elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$moduleFilter%'" } - else { $filterQuery = " LIKE '$moduleFilter'" } - } - - if ($messageFilter -ne "") { - if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } - $filterQuery = $filterQuery + " ModuleAndEventText" - if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$messageFilter%'" } - elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$messageFilter%'" } - else { $filterQuery = " LIKE '$messageFilter'" } - } - - if ($timeFilter -ne "") { - if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } - - if ($isSqlType) { $filterQuery = $filterQuery + " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff')" } - else { $timePeriodQuery = $filterQuery = $filterQuery + " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3')" } - - if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$timeFilter%'" } - elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$timeFilter%'" } - else { $filterQuery = " LIKE '$timeFilter'" } - } - - - # Calculate the Timeperiod and build the timePeriodQuery string - # It queries the current time from database server and calculates the time range - if ($timePeriod -eq 'day') { - $timeInDays = 1 - } elseif ($timePeriod -eq 'week') { - $timeInDays = 7 - } elseif ($timePeriod -eq 'month') { - $timeInDays = 30 - } else { - $timeInDays = 0 - } - - if ($isSqlType) { - $query = "SELECT CURRENT_TIMESTAMP" - } else { - $query = "SELECT CURRENT_TIMESTAMP from dual" - } - - $command.CommandText = $query - $adapter.SelectCommand = $command - $DataTable = New-Object System.Data.DataTable - $adapter.Fill($DataTable) - - $toDate = $DataTable.Rows[0][0] - $fromDate = $toDate.AddDays(- ($timeInDays)) - - if ($timePeriod -eq 'all') { - if ($isSqlType) { $timePeriodQuery = " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') < '" + $toDate + "'" } - else { $timePeriodQuery = " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') < '" + $toDate + "'" } - } else { - if ($isSqlType) { $timePeriodQuery = " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') BETWEEN '" + $fromDate + "' AND '" + $toDate + "'" } - else { $timePeriodQuery = " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') BETWEEN '" + $fromDate + "' AND '" + $toDate + "'" } - } - - - # Build the Query string based on the database type and filter parameters - if ($isSqlType) { - $query = "SELECT UserSID.StrValue AS UserName, Severity, FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') as EventTime, Module, ModuleAndEventText AS Message FROM $eventTable " + - " LEFT OUTER JOIN (SELECT EventID, StrValue FROM $eventDataTable WITH (NOLOCK) WHERE (Name = 'UserDisplayName')) UserSID ON $eventTable.EventID = UserSID.EventID " - $query = $query + " WHERE $timePeriodQuery" - if ($filterQuery -ne "") { $query = $query + " AND $filterQuery" } - $query = $query + " ORDER BY EventTime DESC" - } else { - $query = " SELECT UserSID.StrValue AS UserName, Severity, TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') AS EventTime, Module, ModuleAndEventText AS Message FROM $eventTable " + - " LEFT OUTER JOIN (SELECT EventID, StrValue FROM $eventDataTable WHERE (Name = 'UserDisplayName')) UserSID ON $eventTable.EventID = UserSID.EventID" - $query = $query + " WHERE $timePeriodQuery" - if ($filterQuery -ne "") { $query = $query + " AND $filterQuery" } - $query = $query + " ORDER BY EventTime DESC" - } - - $command.CommandText = $query - $adapter.SelectCommand = $command - - $DataTable = New-Object System.Data.DataTable - $adapter.Fill($DataTable) - - Write-Host "Number of records found : " $DataTable.Rows.Count - - <# - # This code allows the events to get printed on console - Write-Host " User Time Severity Module ModuleAndEventText " - Foreach($row in $DataTable.Rows) { - Write-Host $row[0] " " $row[1] " " $row[2] " " $row[3] " " $row[4] " " - }#> - - return New-Object pscustomobject -Property @{ Events = $DataTable; } - } - - end { - [System.gc]::collect() - } -} - -function Get-HVFarm { -<# -.SYNOPSIS - This function is used to find farms based on the search criteria provided by the user. - -.DESCRIPTION - This function queries the specified Connection Server for farms which are configured on the server. If no farm is configured on the specified connection server or no farm matches the given search criteria, it will return null. - -.PARAMETER FarmName - farmName to be searched - -.PARAMETER FarmDisplayName - farmDisplayName to be searched - -.PARAMETER FarmType - farmType to be searched. It can take following values: - "AUTOMATED" - search for automated farms only - 'MANUAL' - search for manual farms only - -.PARAMETER Enabled - search for farms which are enabled - -.PARAMETER Full - Switch to get list of FarmSummaryView or FarmInfo objects in the result. If it is true a list of FarmInfo objects is returned ohterwise a list of FarmSummaryView objects is returned. - -.PARAMETER HvServer - Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. - -.EXAMPLE - Get-HVFarm -FarmName 'Farm-01' - -.EXAMPLE - Get-HVFarm -FarmName 'Farm-01' -FarmDisplayName 'Sales RDS Farm' - -.EXAMPLE - Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' - -.EXAMPLE - Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' -Enabled $true - -.EXAMPLE - Get-HVFarm -FarmName 'Farm-01' -Full - -.OUTPUTs - Returns the list of FarmSummaryView or FarmInfo object matching the query criteria. - -.NOTES - Author : Ankit Gupta. - Author email : guptaa@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)] - [string] - $FarmName, - - [Parameter(Mandatory = $false)] - [string] - $FarmDisplayName, - - [Parameter(Mandatory = $false)] - [ValidateSet('MANUAL','AUTOMATED')] - [string] - $FarmType, - - [Parameter(Mandatory = $false)] - [boolean] - $Enabled, - - [Parameter(Mandatory = $false)] - [switch] - $Full, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - - # - # This translates the function arguments into the View API properties that must be queried - $farmSelectors = @{ - 'farmName' = 'data.name'; - 'farmDisplayName' = 'data.displayName'; - 'enabled' = 'data.enabled'; - 'farmType' = 'data.type'; - } - - $parms = $psboundparameters - - $query_service_helper = New-Object VMware.Hv.QueryServiceService - $query = New-Object VMware.Hv.QueryDefinition - - # build the query values - - $query.queryEntityType = 'FarmSummaryView' - [VMware.Hv.queryfilter[]]$filterSet = @() - foreach ($setting in $farmSelectors.Keys) { - if ($null -ne $parms[$setting]) { - $equalsFilter = New-Object VMware.Hv.QueryFilterEquals - $equalsFilter.memberName = $farmSelectors[$setting] - $equalsFilter.value = $parms[$setting] - $filterSet += $equalsFilter - } - } - if ($filterSet.Count -gt 0) { - $queryList = New-Object VMware.Hv.QueryFilterAnd - $queryList.Filters = $filterset - $query.Filter = $queryList - } - - $queryResults = $query_service_helper.QueryService_Query($services, $query) - $farmList = $queryResults.results - if ($full) { - $farm_service_helper = New-Object VMware.Hv.FarmService - $queryResults = @() - foreach ($id in $farmList.id) { - $info = $farm_service_helper.Farm_Get($services,$id) - $queryResults += $info - } - $farmList = $queryResults - } - return $farmList -} - -function Get-HVPool { -<# -.Synopsis - Gets pool(s) information with given search parameters. - -.DESCRIPTION - Queries and returns pools information, the pools list would be determined based on - queryable fields poolName, poolDisplayName, poolType, userAssignment, enabled, - provisioningEnabled. When more than one fields are used for query the pools which - satisfy all fields criteria would be returned. - -.PARAMETER PoolName - Pool name to query for. - If the value is null or not provided then filter will not be applied, - otherwise the pools which has name same as value will be returned. - -.PARAMETER PoolDisplayName - Pool display name to query for. - If the value is null or not provided then filter will not be applied, - otherwise the pools which has display name same as value will be returned. - -.PARAMETER PoolType - Pool type to filter with. - If the value is null or not provided then filter will not be applied. - If the value is MANUAL then only manual pools would be returned. - If the value is AUTOMATED then only automated pools would be returned - If the value is RDS then only Remote Desktop Service Pool pools would be returned - -.PARAMETER UserAssignment - User Assignment of pool to filter with. - If the value is null or not provided then filter will not be applied. - If the value is DEDICATED then only dedicated pools would be returned. - If the value is FLOATING then only floating pools would be returned - -.PARAMETER Enabled - Pool enablement to filter with. - If the value is not provided then then filter will not be applied. - If the value is true then only pools which are enabled would be returned. - If the value is false then only pools which are disabled would be returned. - -.PARAMETER Full - Switch to get full information about the pool. - Use this switch only when you require complete information about pool. - -.PARAMETER HvServer - Reference to Horizon View Server to query the pools from. If the value is not passed or null then - first element from global:DefaultHVServers would be considered inplace of hvServer - -.EXAMPLE - Get-HVPool -PoolName 'mypool' -PoolType MANUAL -UserAssignment FLOATING -Enabled $true -ProvisioningEnabled $true - -.EXAMPLE - Get-HVPool -PoolType AUTOMATED -UserAssignment FLOATING -full - -.EXAMPLE - Get-HVPool -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false - -.EXAMPLE - Get-HVPool -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false -HvServer $mycs - -.OUTPUTS - If switch -Full is used then returns list of DesktopSummaryView - else returns list of objects of type Desktop - -.NOTES - Author : Praveen Mathamsetty. - Author email : pmathamsetty@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)] - [string] - $PoolName, - - [Parameter(Mandatory = $false)] - [string] - $PoolDisplayName, - - [Parameter(Mandatory = $false)] - [ValidateSet('MANUAL','AUTOMATED','RDS')] - [string] - $PoolType, - - [Parameter(Mandatory = $false)] - [ValidateSet('FLOATING','DEDICATED')] - [string] - $UserAssignment, - - [Parameter(Mandatory = $false)] - [boolean] - $Enabled, - - [Parameter(Mandatory = $false)] - [boolean] - $ProvisioningEnabled, - - [Parameter(Mandatory = $false)] - [switch] - $Full, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - - # - # This translates the function arguments into the View API properties that must be queried - $poolSelectors = @{ - 'poolName' = 'desktopSummaryData.name'; - 'poolDisplayName' = 'desktopSummaryData.displayName'; - 'enabled' = 'desktopSummaryData.enabled'; - 'poolType' = 'desktopSummaryData.type'; - 'userAssignment' = 'desktopSummaryData.userAssignment'; - 'provisioningEnabled' = 'desktopSummaryData.provisioningEnabled' - } - - $parms = $psboundparameters - - $query_service_helper = New-Object VMware.Hv.QueryServiceService - $query = New-Object VMware.Hv.QueryDefinition - - $wildCard = $false - #Only supports wild card '*' - if ($parms['PoolName'] -and $parms['PoolName'].contains('*')) { - $wildcard = $true - } - if ($parms['PoolDisplayName'] -and $parms['PoolDisplayName'].contains('*')) { - $wildcard = $true - } - # build the query values - $query.queryEntityType = 'DesktopSummaryView' - if (! $wildcard) { - [VMware.Hv.queryfilter[]]$filterSet = @() - foreach ($setting in $poolSelectors.Keys) { - if ($null -ne $parms[$setting]) { - $equalsFilter = New-Object VMware.Hv.QueryFilterEquals - $equalsFilter.memberName = $poolSelectors[$setting] - $equalsFilter.value = $parms[$setting] - $filterSet += $equalsFilter - } - } - if ($filterSet.Count -gt 0) { - $andFilter = New-Object VMware.Hv.QueryFilterAnd - $andFilter.Filters = $filterset - $query.Filter = $andFilter - } - $queryResults = $query_service_helper.QueryService_Query($services,$query) - $poolList = $queryResults.results - } - if ($wildcard -or [string]::IsNullOrEmpty($poolList)) { - $query.Filter = $null - $queryResults = $query_service_helper.QueryService_Query($services,$query) - $strFilterSet = @() - foreach ($setting in $poolSelectors.Keys) { - if ($null -ne $parms[$setting]) { - if ($wildcard -and (($setting -eq 'PoolName') -or ($setting -eq 'PoolDisplayName')) ) { - $strFilterSet += '($_.' + $poolSelectors[$setting] + ' -like "' + $parms[$setting] + '")' - } else { - $strFilterSet += '($_.' + $poolSelectors[$setting] + ' -eq "' + $parms[$setting] + '")' - } - } - } - $whereClause = [string]::Join(' -and ', $strFilterSet) - $scriptBlock = [Scriptblock]::Create($whereClause) - $poolList = $queryResults.results | where $scriptBlock - } - if ($full) { - $queryResults = @() - $desktop_helper = New-Object VMware.Hv.DesktopService - foreach ($id in $poolList.id) { - $info = $desktop_helper.Desktop_Get($services,$id) - $queryResults += $info - } - $poolList = $queryResults - } - return $poolList -} - -function Get-HVQueryFilter { -<# -.Synopsis - Creates a VMware.Hv.QueryFilter based on input provided. - -.DESCRIPTION - This is a factory method to create a VMware.Hv.QueryFilter. The type of the QueryFilter would be determined based on switch used. - -.PARAMETER MemberName - Property path separated by . (dot) from the root of queryable data object which is being queried for - -.PARAMETER MemberValue - Value of property (memberName) which is used for filtering - -.PARAMETER Eq - Switch to create QueryFilterEquals filter - -.PARAMETER Ne - Switch to create QueryFilterNotEquals filter - -.PARAMETER Contains - Switch to create QueryFilterContains filter - -.PARAMETER Startswith - Switch to create QueryFilterStartsWith filter - -.PARAMETER Not - Switch to create QueryFilterNot filter, used for negating existing filter - -.PARAMETER And - Switch to create QueryFilterAnd filter, used for joing two or more filters - -.PARAMETER Or - Switch to create QueryFilterOr filter, used for joing two or more filters - -.PARAMETER Filter - Filter to used in QueryFilterNot to negate the result - -.PARAMETER Filters - List of filters to join using QueryFilterAnd or QueryFilterOr - - -.EXAMPLE - Get-HVQueryFilter data.name -Eq vmware - -.EXAMPLE - Get-HVQueryFilter -MemberName data.name -Eq -MemberValue vmware - -.EXAMPLE - Get-HVQueryFilter data.name -Ne vmware - -.EXAMPLE - Get-HVQueryFilter data.name -Contains vmware - -.EXAMPLE - Get-HVQueryFilter data.name -Startswith vmware - -.EXAMPLE - $filter = Get-HVQueryFilter data.name -Startswith vmware - Get-HVQueryFilter -Not $filter - -.EXAMPLE - $filter1 = Get-HVQueryFilter data.name -Startswith vmware - $filter2 = Get-HVQueryFilter data.name -Contains pool - Get-HVQueryFilter -And @($filter1, $filter2) - -.EXAMPLE - $filter1 = Get-HVQueryFilter data.name -Startswith vmware - $filter2 = Get-HVQueryFilter data.name -Contains pool - Get-HVQueryFilter -Or @($filter1, $filter2) - -.OUTPUTS - Returns the QueryFilter object - -.NOTES - Author : Kummara Ramamohan. - Author email : kramamohan@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()] - param( - # Type 1 parametersets which requires memberName, memberValue as input - [Parameter(ParameterSetName = 'eq',Mandatory = $true,Position = 0)] - [Parameter(ParameterSetName = 'contains',Mandatory = $true,Position = 0)] - [Parameter(ParameterSetName = 'startswith',Mandatory = $true,Position = 0)] - [Parameter(ParameterSetName = 'ne',Mandatory = $true,Position = 0)] - [string]$MemberName, - - [Parameter(ParameterSetName = "eq",Mandatory = $true,Position = 1)] - [switch]$Eq, - - [Parameter(ParameterSetName = "contains",Mandatory = $true,Position = 1)] - [switch]$Contains, - - [Parameter(ParameterSetName = "startswith",Mandatory = $true,Position = 1)] - [switch]$Startswith, - - [Parameter(ParameterSetName = "ne",Mandatory = $true,Position = 1)] - [switch]$Ne, - - [Parameter(ParameterSetName = 'eq',Mandatory = $true,Position = 2)] - [Parameter(ParameterSetName = 'contains',Mandatory = $true,Position = 2)] - [Parameter(ParameterSetName = 'startswith',Mandatory = $true,Position = 2)] - [Parameter(ParameterSetName = 'ne',Mandatory = $true,Position = 2)] - [System.Object]$MemberValue, - - # Negation # - [Parameter(ParameterSetName = "not",Mandatory = $true,Position = 0)] - [switch]$Not, - - [Parameter(ParameterSetName = 'not',Mandatory = $true,Position = 1)] - [VMware.Hv.QueryFilter]$Filter, - - # Aggregators to join more than 1 filters # - [Parameter(ParameterSetName = 'and',Mandatory = $true,Position = 0)] - [switch]$And, - - [Parameter(ParameterSetName = "or",Mandatory = $true,Position = 0)] - [switch]$Or, - - [Parameter(ParameterSetName = "and",Mandatory = $true,Position = 1)] - [Parameter(ParameterSetName = "or",Mandatory = $true,Position = 1)] - [VMware.Hv.QueryFilter[]]$Filters - ) - - begin { - $switchToClassName = @{ - 'eq' = 'QueryFilterEquals'; - 'startswith' = 'QueryFilterStartsWith'; - 'contains' = 'QueryFilterContains'; - 'ne' = 'QueryFilterNotEquals'; - 'not' = 'QueryFilterNot'; - 'and' = 'QueryFilterAnd'; - 'or' = 'QueryFilterOr'; - } - } - process { - $queryFilter = Get_New_Object -typeName $switchToClassName[$PsCmdlet.ParameterSetName] - - switch ($PsCmdlet.ParameterSetName) { - - { @( 'eq','startswith','contains','ne') -icontains $_ } { - $queryFilter.memberName = $memberName - $queryFilter.value = $membervalue - } - - { @( 'and','or') -icontains $_ } { - $queryFilter.filters = $filters - } - - { @( 'not') -icontains $_ } { - $queryFilter.filter = $filter - } - } - } - end { - return $queryFilter - } -} - -function Get-HVQueryResult { -<# -.Synopsis - Returns the query results from ViewApi Query Service - -.DESCRIPTION - Get-HVQueryResult is a API to query the results using ViewApi. The filtering of the returned - list would be done based on input parameters filter, sortDescending, sortyBy, limit - -.PARAMETER EntityType - ViewApi Queryable entity type which is being queried for.The return list would be containing objects of entityType - -.PARAMETER Filter - Filter to used for filtering the results, See Get-HVQueryFilter for more information - -.PARAMETER SortBy - Data field path used for sorting the results - -.PARAMETER SortDescending - If the value is set to true (default) then the results will be sorted in descending order - If the value is set to false then the results will be sorted in ascending order - -.PARAMETER Limit - Max number of objects to retrieve. Default would be 0 which means retieve all the results - -.PARAMETER HvServer - Reference to Horizon View Server to query the data from. If the value is not passed or null then - first element from global:DefaultHVServers would be considered inplace of hvServer - -.EXAMPLE - Get-HVQueryResult DesktopSummaryView - -.EXAMPLE - Get-HVQueryResult DesktopSummaryView (Get-HVQueryFilter data.name -Eq vmware) - -.EXAMPLE - Get-HVQueryResult -EntityType DesktopSummaryView -Filter (Get-HVQueryFilter desktopSummaryData.name -Eq vmware) - -.EXAMPLE - Get-HVQueryResult -EntityType DesktopSummaryView -Filter (Get-HVQueryFilter desktopSummaryData.name -Eq vmware) -SortBy desktopSummaryData.displayName - -.EXAMPLE - $myFilter = Get-HVQueryFilter data.name -Contains vmware - Get-HVQueryResult -EntityType DesktopSummaryView -Filter $myFilter -SortBy desktopSummaryData.displayName -SortDescending $false - -.EXAMPLE - Get-HVQueryResult DesktopSummaryView -Limit 10 - -.OUTPUTS - Returns the list of objects of entityType - -.NOTES - Author : Kummara Ramamohan. - Author email : kramamohan@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(Position = 0,Mandatory = $true)] - [ValidateSet('ADUserOrGroupSummaryView','ApplicationIconInfo','ApplicationInfo','DesktopSummaryView', - 'EntitledUserOrGroupGlobalSummaryView','EntitledUserOrGroupLocalSummaryView','FarmHealthInfo', - 'FarmSummaryView','GlobalApplicationEntitlementInfo','GlobalEntitlementSummaryView', - 'MachineNamesView','MachineSummaryView','PersistentDiskInfo','PodAssignmentInfo', - 'RDSServerInfo','RDSServerSummaryView','RegisteredPhysicalMachineInfo','SampleInfo', - 'SessionLocalSummaryView','TaskInfo','URLRedirectionInfo','UserHomeSiteInfo')] - [string]$EntityType, - - [Parameter(Position = 1,Mandatory = $false)] - [VMware.Hv.QueryFilter]$Filter = $null, - - [Parameter(Position = 2,Mandatory = $false)] - [string]$SortBy = $null, - - [Parameter(Position = 3,Mandatory = $false)] - [bool]$SortDescending = $true, - - [Parameter(Position = 4,Mandatory = $false)] - [int16]$Limit = 0, - - [Parameter(Position = 5,Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - $queryDef = New-Object VMware.Hv.QueryDefinition - $queryDef.queryEntityType = $entityType - $queryDef.sortDescending = $sortDescending - - if ($sortBy) { - $queryDef.sortBy = $sortBy - } - - if ($limit -gt 0) { - $queryDef.limit = $limit - } - - $queryDef.filter = $filter - - $returnList = @() - $query_service_helper = New-Object VMware.Hv.QueryServiceService - $queryResults = $query_service_helper.QueryService_Create($services,$queryDef) - $returnList += $queryResults.results - - while ($queryResults -and ($queryResults.RemainingCount -gt 0)) { - $queryResults = $query_service_helper.QueryService_GetNext($services,$queryResults.id) - $returnList += $queryResults.results - } - - if ($queryResults.id) { - $query_service_helper.QueryService_Delete($services,$queryResults.id) - } - } - - end { - return $returnList - } -} - -function New-HVFarm { -<# -.Synopsis - Creates a new farm. - -.DESCRIPTION - Creates a new farm, the type would be determined based on input parameters. - -.PARAMETER LinkedClone - Switch to Create Automated Linked Clone farm. - -.PARAMETER Manual - Switch to Create Manual farm. - -.PARAMETER FarmName - Name of the farm. - -.PARAMETER FarmDisplayName - Display name of the farm. - -.PARAMETER Description - Description of the farm. - -.PARAMETER AccessGroup - View access group can organize the servers in the farm. - Default Value is 'Root'. - -.PARAMETER Enable - Set true to enable the farm otherwise set to false. - -.PARAMETER Vcenter - Virtual Center server-address (IP or FQDN) where the farm RDS Servers are located. This should be same as provided to the Connection Server while adding the vCenter server. - -.PARAMETER ParentVM - Base image VM for RDS Servers. - Applicable only to Linked Clone farms. - -.PARAMETER SnapshotVM - Base image snapshot for RDS Servers. - -.PARAMETER VmFolder - VM folder to deploy the RDSServers to. - Applicable to Linked Clone farms. - -.PARAMETER HostOrCluster - Host or cluster to deploy the RDSServers in. - Applicable to Linked Clone farms. - -.PARAMETER ResourcePool - Resource pool to deploy the RDSServers. - Applicable to Linked Clone farms. - -.PARAMETER Datastores - Datastore names to store the RDSServer. - Applicable to Linked Clone farms. - -.PARAMETER UseVSAN - Whether to use vSphere VSAN. This is applicable for vSphere 5.5 or later. - Applicable to Linked Clone farms. - -.PARAMETER EnableProvisioning - Set to true to enable provision of RDSServers immediately in farm. - Applicable to Linked Clone farms. - -.PARAMETER StopOnProvisioningError - Set to true to stop provisioning of all RDSServers on error. - Applicable to Linked Clone farms. - -.PARAMETER TransparentPageSharingScope - The transparent page sharing scope. - The default value is 'VM'. - -.PARAMETER NamingMethod - Determines how the VMs in the farm are named. - Set PATTERN to use naming pattern. - The default value is PATTERN. Curentlly only PATTERN is allowed. - -.PARAMETER NamingPattern - RDS Servers will be named according to the specified naming pattern. - Value would be considered only when $namingMethod = PATTERN - The default value is farmName + '{n:fixed=4}'. - -.PARAMETER MinReady - Minimum number of ready (provisioned) Servers during View Composer maintenance operations. - The default value is 0. - Applicable to Linked Clone farms. - -.PARAMETER MaximumCount - Maximum number of Servers in the farm. - The default value is 1. - Applicable to Linked Clone farms. - -.PARAMETER AdContainer - This is the Active Directory container which the Servers will be added to upon creation. - The default value is 'CN=Computers'. - Applicable to Linked Clone farm. - -.PARAMETER NetBiosName - Domain Net Bios Name. - Applicable to Linked Clone farms. - -.PARAMETER DomainAdmin - Domain Administrator user name which will be used to join the domain. - Default value is null. - Applicable to Linked Clone farms. - -.PARAMETER SysPrepName - The customization spec to use. - Applicable to Linked Clone farms. - -.PARAMETER RdsServers - List of existing registered RDS server names to add into manual farm. - Applicable to Manual farms. - -.PARAMETER Spec - Path of the JSON specification file. - -.PARAMETER HvServer - Reference to Horizon View Server to query the farms from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. - -.EXAMPLE - New-HVFarm -LinkedClone -FarmName 'LCFarmTest' -ParentVM 'Win_Server_2012_R2' -SnapshotVM 'Snap_RDS' -VmFolder 'PoolVM' -HostOrCluster 'cls' -ResourcePool 'cls' -Datastores 'datastore1 (5)' -FarmDisplayName 'LC Farm Test' -Description 'created LC Farm from PS' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "LCFarmVM_PS" -MinReady 1 -MaximumCount 1 -SysPrepName "RDSH_Cust2" -NetBiosName "adviewdev" - -.EXAMPLE - New-HVFarm -Spec C:\VMWare\Specs\LinkedClone.json - -.EXAMPLE - New-HVFarm -Manual -FarmName "manualFarmTest" -FarmDisplayName "manualFarmTest" -Description "Manual PS Test" -RdsServers "vm-for-rds.eng.vmware.com","vm-for-rds-2.eng.vmware.com" - -.OUTPUTS - None - -.NOTES - Author : Ankit Gupta. - Author email : guptaa@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 = $true,ParameterSetName = "LINKED_CLONE")] - [switch] - $LinkedClone, - - [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] - [switch] - $Manual, - - #farmSpec.farmData.name - [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [string] - $FarmName, - - #farmSpec.farmData.displayName - [Parameter(Mandatory = $false)] - [string] - $FarmDisplayName = $farmName, - - #farmSpec.farmData.description - [Parameter(Mandatory = $false)] - [string] - $Description = ' ', - - #farmSpec.farmData.accessGroup - [Parameter(Mandatory = $false)] - [string] - $AccessGroup = 'Root', - - #farmSpec.farmData.enabled - [Parameter(Mandatory = $false)] - [boolean] - $Enable = $true, - - #farmSpec.automatedfarmSpec.virtualCenter if LINKED_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [string] - $Vcenter, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVM if LINKED_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [string] - $ParentVM, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshotVM if LINKED_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [string] - $SnapshotVM, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [string] - $VmFolder, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.hostOrCluster if LINKED_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [string] - $HostOrCluster, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.resourcePool if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [string] - $ResourcePool, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [string[]] - $Datastores, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.useVSAN if LINKED_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [string] - $UseVSAN, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [boolean] - $EnableProvisioning = $true, - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [boolean] - $StopOnProvisioningError = $true, - - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [string] - $TransparentPageSharingScope = 'VM', - - #farmSpec.automatedfarmSpec.rdsServerNamingSpec.namingMethod if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [ValidateSet('PATTERN')] - [string] - $NamingMethod = 'PATTERN', - - #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.namingPattern if LINKED_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [string] - $NamingPattern = $farmName + '{n:fixed=4}', - - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if LINKED_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [int] - $MinReady = 0, - - #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers if LINKED_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [int] - $MaximumCount = 1, - - #farmSpec.automatedfarmSpec.customizationSettings.adContainer if LINKED_CLONE - [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] - [string] - $AdContainer = 'CN=Computers', - - #farmSpec.automatedfarmSpec.customizationSettings.domainAdministrator - [Parameter(Mandatory = $true,ParameterSetName = 'LINKED_CLONE')] - [string] - $NetBiosName, - - #farmSpec.automatedfarmSpec.customizationSettings.domainAdministrator - [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] - [string] - $DomainAdmin = $null, - - #farmSpec.automatedfarmSpec.customizationSettings.sysprepCustomizationSettings.customizationSpec if LINKED_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [string] - $SysPrepName, - - ##farmSpec.manualfarmSpec.rdsServers - [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] - [string[]] - $RdsServers, - - [Parameter(Mandatory = $false,ParameterSetName = 'JSON_FILE')] - [string] - $Spec, - - [Parameter(Mandatory = $false)] - $HvServer = $null - - ) - # - # farmSpec/FarmInfo - # *farmData - # +AccessGroupId - # +FarmSessionSettings - # FarmAutomatedfarmSpec/FarmAutomatedFarmData - # */+VirtualCenterId - # FarmRDSServerNamingSpec/FarmVirtualMachineNamingSettings - # FarmPatternNamingSpec/FarmPatternNamingSettings - # FarmVirtualCenterProvisioningSettings - # FarmVirtualCenterProvisioningData/virtualCenterProvisioningData - # FarmVirtualCenterStorageSettings - # FarmVirtualCenterNetworkingSettings - # FarmVirtualCenterManagedCommonSettings - # FarmCustomizationSettings - # ViewComposerDomainAdministratorId - # ADContainerId - # FarmSysprepCustomizationSettings - # CustomizationSpecId - # FarmManualfarmSpec - # RDSServerId[] - # - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - - if ($farmName) { - try { - $sourceFarm = Get-HVFarm -farmName $farmName -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" - break - } - if ($sourceFarm) { - Write-Error "Farm with name [$farmName] already exists" - return - } - } - $farm_service_helper = New-Object VMware.Hv.FarmService - if ($spec) { - try { - $jsonObject = Get_Json_Object -specFile $spec - } catch { - Write-Error "Json file exception, $_" - break - } - if ($jsonObject.type -eq 'AUTOMATED') { - $farmType = 'AUTOMATED' - if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenter) { - $vCenter = $jsonObject.AutomatedFarmSpec.VirtualCenter - } - $linkedClone = $true - $netBiosName = $jsonObject.NetBiosName - $adContainer = $jsonObject.AutomatedFarmSpec.CustomizationSettings.AdContainer - - $namingMethod = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.NamingMethod - $namingPattern = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern - $maximumCount = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers - - $transparentPageSharingScope = $jsonObject.AutomatedFarmSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope - - if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm) { - $parentVM = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm - } - if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot) { - $snapshotVM = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot - } - $vmFolder = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.VmFolder - $hostOrCluster = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.HostOrCluster - $resourcePool = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ResourcePool - $dataStoreList = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores - foreach ($dtStore in $dataStoreList) { - $datastores += $dtStore.Datastore - } - $sysPrepName = $jsonObject.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec - } elseif ($jsonObject.type -eq 'MANUAL') { - $manual = $true - $farmType = 'MANUAL' - $RdsServersObjs = $jsonObject.ManualFarmSpec.RdsServers - - foreach ($RdsServerObj in $RdsServersObjs) { - $rdsServers += $RdsServerObj.rdsServer - } - } - $farmDisplayName = $jsonObject.data.DisplayName - $description = $jsonObject.data.Description - $accessGroup = $jsonObject.data.AccessGroup - $farmName = $jsonObject.data.name - } - - if ($linkedClone) { - $farmType = 'AUTOMATED' - $provisioningType = 'VIEW_COMPOSER' - } elseif ($manual) { - $farmType = 'MANUAL' - } - - $script:farmSpecObj = Get_Farm_Spec -farmType $farmType -provisioningType $provisioningType -namingMethod $namingMethod - - # - # build out the infrastructure based on type of provisioning - # - $handleException = $false - switch ($farmType) { - - 'MANUAL' { - try { - $serverList = Get-RegisteredRDSServers -services $services -serverList $rdsServers - $farmSpecObj.ManualFarmSpec.RdsServers = $serverList - } catch { - $handleException = $true - Write-Error "Failed to create Farm with error: $_" - break - } - } - default { - # - # accumulate properties that are shared among various type - # - - # - # vCenter: if $vcenterID is defined, then this is a clone - # if the user specificed the name, then find it from the list - # if none specified, then automatically use the vCenter if there is only one - # - - if (!$virtualCenterID) { - $virtualCenterID = Get_Vcenter_ID -services $services -vCenter $vCenter - } - - if ($null -eq $virtualCenterID) { - $handleException = $true - break - } - - # - # transparentPageSharingScope - # - - if (!$farmVirtualCenterManagedCommonSettings) { - if ($farmSpecObj.AutomatedFarmSpec) { - $farmSpecObj.AutomatedFarmSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope - } - $farmVirtualCenterManagedCommonSettings = $farmSpecObj.AutomatedFarmSpec.virtualCenterManagedCommonSettings - } - - if (!$farmVirtualMachineNamingSpec) { - $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.NamingMethod = $namingMethod - $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern = $namingPattern - $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers = $maximumCount - } else { - $vmNamingSpec = New-Object VMware.Hv.FarmRDSServerNamingSpec - $vmNamingSpec.NamingMethod = 'PATTERN' - - $vmNamingSpec.patternNamingSettings = New-Object VMware.Hv.FarmPatternNamingSettings - $vmNamingSpec.patternNamingSettings.namingPattern = $namingPattern - $vmNamingSpec.patternNamingSettings.maxNumberOfRDSServers = $maximumCount - } - - # - # build the VM LIST - # - try { - $farmVirtualCenterProvisioningData = Build_VM_List_Farm -vc $virtualCenterID -vmObject $farmVirtualCenterProvisioningData - $hostClusterId = $farmVirtualCenterProvisioningData.HostOrCluster - $farmVirtualCenterStorageSettings = Build_Datastore_List_Farm -hostclusterID $hostClusterId -storageObject $farmVirtualCenterStorageSettings - $farmVirtualCenterNetworkingSettings = Build_Network_List_Farm -networkObject $farmVirtualCenterNetworkingSettings - $farmCustomizationSettings = Build_Customization_Settings_Farm -vc $virtualCenterID -customObject $farmCustomizationSettings - } catch { - $handleException = $true - Write-Error "Failed to create Farm with error: $_" - break - } - - $farmSpecObj.AutomatedFarmSpec.RdsServerMaxSessionsData.MaxSessionsType = "UNLIMITED" - - if (!$FarmVirtualCenterProvisioningSettings) { - $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.enableProvisioning = $true - $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $true - $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = 0 - $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $farmVirtualCenterProvisioningData - $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $farmVirtualCenterStorageSettings - $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $FarmVirtualCenterNetworkingSettings - - $farmSpecObj.AutomatedFarmSpec.CustomizationSettings = $farmCustomizationSettings - $farmSpecObj.AutomatedFarmSpec.ProvisioningType = $provisioningType - $farmSpecObj.AutomatedFarmSpec.VirtualCenter = $virtualCenterID - } else { - $FarmVirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $farmVirtualCenterProvisioningData - $FarmVirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $farmVirtualCenterStorageSettings - $FarmVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $FarmVirtualCenterNetworkingSettings - - $FarmAutomatedFarmSpec = New-Object VMware.Hv.FarmAutomatedFarmSpec - $FarmAutomatedFarmSpec.ProvisioningType = $provisioningType - $FarmAutomatedFarmSpec.VirtualCenter = $virtualCenterID - $FarmAutomatedFarmSpec.VirtualCenterProvisioningSettings = $farmVirtualCenterProvisioningSettings - $FarmAutomatedFarmSpec.virtualCenterManagedCommonSettings = $farmVirtualCenterManagedCommonSettings - $FarmAutomatedFarmSpec.CustomizationSettings = $farmCustomizationSettings - } - } - } - - if ($handleException) { - break - } - - $farmData = $farmSpecObj.data - $AccessGroup_service_helper = New-Object VMware.Hv.AccessGroupService - $ag = $AccessGroup_service_helper.AccessGroup_List($services) | Where-Object { $_.base.name -eq $accessGroup } - $farmData.AccessGroup = $ag.id - - $farmData.name = $farmName - $farmData.DisplayName = $farmDisplayName - $farmData.Description = $description - $farmSpecObj.type = $farmType - - if ($FarmAutomatedFarmSpec) { - $farmSpecObj.AutomatedFarmSpec = $FarmAutomatedFarmSpec - } - if ($FarmManualFarmSpec) { - $farmSpecObj.ManualFarmSpec = $FarmManualFarmSpec - } - - # Please uncomment below code, if you want to save the json file - <# -$myDebug = convertto-json -InputObject $farmSpecObj -depth 12 -$myDebug | out-file -filepath c:\temp\copiedfarm.json -#> - $farm_service_helper.Farm_Create($services, $farmSpecObj) - } - - end { - [System.gc]::collect() - } - -} - -function Build_VM_List_Farm { - param( - [Parameter(Mandatory = $false)] - [VMware.Hv.FarmVirtualCenterProvisioningData]$VmObject, - - [Parameter(Mandatory = $true)] - [VMware.Hv.VirtualCenterId]$VcID - ) - if (!$vmObject) { - $vmObject = $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData - } - if ($parentVM) { - $BaseImage_service_helper = New-Object VMware.Hv.BaseImageVmService - $parentList = $BaseImage_service_helper.BaseImageVm_List($services, $vcID) - $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } - if ($null -eq $parentVMObj) { - throw "No Parent VM found with name: [$parentVM]" - } - $vmObject.ParentVm = $parentVMObj.id - $dataCenterID = $parentVMObj.datacenter - $vmObject.datacenter = $dataCenterID - } - if ($snapshotVM) { - $BaseImageSnapshot_service_helper = New-Object VMware.Hv.BaseImageSnapshotService - $snapshotList = $BaseImageSnapshot_service_helper.BaseImageSnapshot_List($services, $parentVMObj.id) - $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } - if ($null -eq $snapshotVMObj) { - throw "No Snapshot found with name: [$snapshotVM] for VM name: [$parentVM] " - } - $vmObject.Snapshot = $snapshotVMObj.id - } - if ($vmFolder) { - $VmFolder_service_helper = New-Object VMware.Hv.VmFolderService - $folders = $VmFolder_service_helper.VmFolder_GetVmFolderTree($services, $vmObject.datacenter) - $folderList = @() - $folderList += $folders - while ($folderList.Length -gt 0) { - $item = $folderList[0] - if ($item -and !$_.folderdata.incompatiblereasons.inuse -and !$_.folderdata.incompatiblereasons.viewcomposerreplicafolder -and ($item.folderdata.name -eq $vmFolder)) { - $vmObject.VmFolder = $item.id - break - } - foreach ($folderItem in $item.children) { - $folderList += $folderItem - } - $folderList = $folderList[1..$folderList.Length] - } - if ($null -eq $vmObject.VmFolder) { - throw "No VM Folder found with name: [$vmFolder]" - } - } - if ($hostOrCluster) { - $HostOrCluster_service_helper = New-Object VMware.Hv.HostOrClusterService - $hostClusterList = ($HostOrCluster_service_helper.HostOrCluster_GetHostOrClusterTree($services, $vmobject.datacenter)).treeContainer.children.info - $HostClusterObj = $hostClusterList | Where-Object { $_.name -eq $hostOrCluster } - if ($null -eq $HostClusterObj) { - throw "No host or cluster found with name: [$hostOrCluster]" - } - $vmObject.HostOrCluster = $HostClusterObj.id - } - if ($resourcePool) { - $ResourcePool_service_helper = New-Object VMware.Hv.ResourcePoolService - $resourcePoolList = $ResourcePool_service_helper.ResourcePool_GetResourcePoolTree($services, $vmobject.HostOrCluster) - $resourcePoolObj = $resourcePoolList | Where-Object { $_.resourcepooldata.name -eq $resourcePool } - if ($null -eq $resourcePoolObj) { - throw "No resource pool found with name: [$resourcePool]" - } - $vmObject.ResourcePool = $resourcePoolObj.id - } - return $vmObject -} - -function Build_Datastore_List_Farm { - param( - [Parameter(Mandatory = $false)] - [VMware.Hv.FarmVirtualCenterStorageSettings]$StorageObject, - - [Parameter(Mandatory = $true)] - [VMware.Hv.HostOrClusterId]$HostClusterID - ) - if (!$storageObject) { - $storageObject = New-Object VMware.Hv.FarmVirtualCenterStorageSettings - - $FarmSpaceReclamationSettings = New-Object VMware.Hv.FarmSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $false } - - $FarmViewComposerStorageSettingsList = @{ - 'useSeparateDatastoresReplicaAndOSDisks' = $false; - 'replicaDiskDatastore' = $FarmReplicaDiskDatastore - 'useNativeSnapshots' = $false; - 'spaceReclamationSettings' = $FarmSpaceReclamationSettings; - } - - $storageObject.ViewComposerStorageSettings = New-Object VMware.Hv.FarmViewComposerStorageSettings -Property $FarmViewComposerStorageSettingsList - } - - if ($datastores) { - $Datastore_service_helper = New-Object VMware.Hv.DatastoreService - $datastoreList = $Datastore_service_helper.Datastore_ListDatastoresByHostOrCluster($services, $hostClusterID) - $datastoresSelected = @() - foreach ($ds in $datastores) { - $datastoresSelected += ($datastoreList | Where-Object { $_.datastoredata.name -eq $ds }).id - } - foreach ($ds in $datastoresSelected) { - $datastoresObj = New-Object VMware.Hv.FarmVirtualCenterDatastoreSettings - $datastoresObj.Datastore = $ds - $datastoresObj.StorageOvercommit = 'UNBOUNDED' - $StorageObject.Datastores += $datastoresObj - } - } - if ($storageObject.Datastores.Count -eq 0) { - throw "No datastores found with name: [$datastores]" - } - if ($useVSAN) { $storageObject.useVSAN = $useVSAN } - return $storageObject -} - -function Build_Network_List_Farm { - param( - [Parameter(Mandatory = $false)] - [VMware.Hv.FarmVirtualCenterNetworkingSettings]$NetworkObject - ) - if (!$networkObject) { - $networkObject = $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings - } - return $networkObject -} - -function Build_Customization_Settings_Farm { - param( - [Parameter(Mandatory = $false)] - [VMware.Hv.FarmCustomizationSettings]$CustomObject, - - [Parameter(Mandatory = $true)] - [VMware.Hv.VirtualCenterId]$VcID - ) - if (!$customObject) { - $ViewComposerDomainAdministrator_service_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService - $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministrator_service_helper.ViewComposerDomainAdministrator_List($services, $vcID) | Where-Object { $_.base.domain -cmatch $netBiosName }) - if (! [string]::IsNullOrWhitespace($domainAdmin)) { - $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministratorID | Where-Object { $_.base.userName -ieq $domainAdmin }).id - } else { - $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id - } - if ($null -eq $ViewComposerDomainAdministratorID) { - throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" - } - $ADDomain_service_helper = New-Object VMware.Hv.ADDomainService - $adDomianId = ($ADDomain_service_helper.ADDomain_List($services) | Where-Object { $_.NetBiosName -eq $netBiosName } | Select-Object -Property id) - if ($null -eq $adDomianId) { - throw "No Domain found with netBiosName: [$netBiosName]" - } - $ad_containder_service_helper = New-Object VMware.Hv.AdContainerService - $adContainerId = ($ad_containder_service_helper.ADContainer_ListByDomain($services, $adDomianId.id) | Where-Object { $_.Rdn -eq $adContainer } | Select-Object -Property id).id - if ($null -eq $adContainerId) { - throw "No AdContainer found with name: [$adContainer]" - } - #Support only Sysprep Customization - $sysprepCustomizationSettings = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings - - # Get SysPrep CustomizationSpec ID - $CustomizationSpec_service_helper = New-Object VMware.Hv.CustomizationSpecService - $sysPrepIds = $CustomizationSpec_service_helper.CustomizationSpec_List($services, $vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id - if ($sysPrepIds.Count -eq 0) { - throw "No Sysprep Customization spec found with Name: [$sysPrepName]" - } - $sysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id - - $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' - $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.DomainAdministrator = $ViewComposerDomainAdministratorID - $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.AdContainer = $adContainerId - $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.ReusePreExistingAccounts = $false - $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings = $sysprepCustomizationSettings - - $customObject = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings - } - return $customObject -} - -function Get_Farm_Spec { - param( - [Parameter(Mandatory = $true)] - [string]$FarmType, - - [Parameter(Mandatory = $false)] - [string]$ProvisioningType, - - [Parameter(Mandatory = $false)] - [string]$NamingMethod - ) - - $farm_helper = New-Object VMware.Hv.FarmService - $farm_spec_helper = $farm_helper.getFarmSpecHelper() - $farm_spec_helper.setType($farmType) - if ($farmType -eq 'AUTOMATED') { - $farm_spec_helper.getDataObject().AutomatedFarmSpec.RdsServerNamingSpec.PatternNamingSettings = $farm_helper.getFarmPatternNamingSettingsHelper().getDataObject() - $farm_spec_helper.getDataObject().AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings = $farm_helper.getFarmViewComposerStorageSettingsHelper().getDataObject() - } elseif ($farmType -eq 'MANUAL') { - # No need to set - } - return $farm_spec_helper.getDataObject() -} - -function New-HVPool { -<# -.Synopsis - Creates new desktop pool. - -.DESCRIPTION - Creates new desktop pool, the type and user assignment type would be - determined based on input parameters. - -.PARAMETER InstantClone - Switch to Create Instant Clone pool. - -.PARAMETER LinkedClone - Switch to Create Linked Clone pool. - -.PARAMETER FullClone - Switch to Create Full Clone pool. - -.PARAMETER Manual - Switch to Create Manual Clone pool. - -.PARAMETER Rds - Switch to Create RDS pool. - -.PARAMETER PoolName - Name of the pool. - -.PARAMETER PoolDisplayName - Display name of pool. - -.PARAMETER Description - Description of pool. - -.PARAMETER AccessGroup - View access group can organize the desktops in the pool. - Default Value is 'Root'. - -.PARAMETER GlobalEntitlement - Description of pool. - Global entitlement to associate the pool. - -.PARAMETER UserAssignment - User Assignment type of pool. - Set to DEDICATED for dedicated desktop pool. - Set to FLOATING for floating desktop pool. - -.PARAMETER AutomaticAssignment - Automatic assignment of a user the first time they access the machine. - Applicable to dedicated desktop pool. - -.PARAMETER Enable - Set true to enable the pool otherwise set to false. - -.PARAMETER ConnectionServerRestrictions - Connection server restrictions. - This is a list of tags that access to the desktop is restricted to. - No list means that the desktop can be accessed from any connection server. - -.PARAMETER Vcenter - Virtual Center server-address (IP or FQDN) where the pool virtual machines are located. This should be same as provided to the Connection Server while adding the vCenter server. - -.PARAMETER Template - Virtual machine Template name to clone Virtual machines. - Applicable only to Full Clone pools. - -.PARAMETER ParentVM - Parent Virtual Machine to clone Virtual machines. - Applicable only to Linked Clone and Instant Clone pools. - -.PARAMETER SnapshotVM - Base image VM for Linked Clone pool and current Image for Instant Clone Pool. - -.PARAMETER VmFolder - VM folder to deploy the VMs to. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER HostOrCluster - Host or cluster to deploy the VMs in. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER ResourcePool - Resource pool to deploy the VMs. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER Datastores - Datastore names to store the VM - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER UseVSAN - Whether to use vSphere VSAN. This is applicable for vSphere 5.5 or later. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER StopOnProvisioningError - Set to true to stop provisioning of all VMs on error. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER TransparentPageSharingScope - The transparent page sharing scope. - The default value is 'VM'. - -.PARAMETER NamingMethod - Determines how the VMs in the desktop are named. - Set SPECIFIED to use specific name. - Set PATTERN to use naming pattern. - The default value is PATTERN. For Instant Clone pool the value must be PATTERN. - -.PARAMETER NamingPattern - Virtual machines will be named according to the specified naming pattern. - Value would be considered only when $namingMethod = PATTERN. - The default value is poolName + '{n:fixed=4}'. - -.PARAMETER MinReady - Minimum number of ready (provisioned) machines during View Composer maintenance operations. - The default value is 0. - Applicable to Linked Clone Pools. - -.PARAMETER MaximumCount - Maximum number of machines in the pool. - The default value is 1. - Applicable to Full, Linked, Instant Clone Pools - -.PARAMETER SpareCount - Number of spare powered on machines in the pool. - The default value is 1. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER ProvisioningTime - Determines when machines are provisioned. - Supported values are ON_DEMAND, UP_FRONT. - The default value is UP_FRONT. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER MinimumCount - The minimum number of machines to have provisioned if on demand provisioning is selected. - The default value is 0. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER SpecificNames - Specified names of VMs in the pool. - The default value is -1 - Applicable to Full, Linked and Cloned Pools. - -.PARAMETER StartInMaintenanceMode - Set this to true to allow virtual machines to be customized manually before users can log - in and access them. - the default value is false - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER NumUnassignedMachinesKeptPoweredOn - Number of unassigned machines kept powered on. value should be less than max number of vms in the pool. - The default value is 1. - Applicable to Full, Linked, Instant Clone Pools. - When JSON Spec file is used for pool creation, the value will be read from JSON spec. - -.PARAMETER AdContainer - This is the Active Directory container which the machines will be added to upon creation. - The default value is 'CN=Computers'. - Applicable to Instant Clone Pool. - -.PARAMETER NetBiosName - Domain Net Bios Name. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER DomainAdmin - Domain Administrator user name which will be used to join the domain. - Default value is null. - Applicable to Full, Linked, Instant Clone Pools. - -.PARAMETER CustType - Type of customization to use. - Supported values are 'CLONE_PREP','QUICK_PREP','SYS_PREP','NONE'. - Applicable to Full, Linked Clone Pools. - -.PARAMETER SysPrepName - The customization spec to use. - Applicable to Full, Linked Clone Pools. - -.PARAMETER Source - Source of the Virtual machines for manual pool. - Supported values are 'VIRTUAL_CENTER','UNMANAGED'. - Set VIRTUAL_CENTER for vCenter managed VMs. - Set UNMANAGED for Physical machines or VMs which are not vCenter managed VMs. - Applicable to Manual Pools. - -.PARAMETER VM - List of existing virtual machine names to add into manual pool. - Applicable to Manual Pools. - -.PARAMETER Farm - Farm to create RDS pools - Applicable to RDS Pools. - -.PARAMETER Spec - Path of the JSON specification file. - -.PARAMETER ClonePool - Existing pool info to clone a new pool. - -.PARAMETER HvServer - Reference to Horizon View Server to query the pools from. If the value is not passed or null then - first element from global:DefaultHVServers would be considered inplace of hvServer. - -.EXAMPLE - Create new automated linked clone pool with naming method pattern - New-HVPool -LinkedClone -PoolName 'vmwarepool' -UserAssignment FLOATING -ParentVM 'Agent_vmware' -SnapshotVM 'kb-hotfix' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -Datastores 'datastore1' -NamingMethod PATTERN -PoolDisplayName 'vmware linkedclone pool' -Description 'created linkedclone pool from ps' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "vmware2" -MinReady 1 -MaximumCount 1 -SpareCount 1 -ProvisioningTime UP_FRONT -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root - -.EXAMPLE - Create new automated linked clone pool by using JSON spec file - New-HVPool -Spec C:\VMWare\Specs\LinkedClone.json - -.EXAMPLE - Clone new pool from automated linked (or) full clone pool - Get-HVPool -PoolName 'vmwarepool' | New-HVPool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; - (OR) - $vmwarepool = Get-HVPool -PoolName 'vmwarepool'; New-HVPool -ClonePool $vmwarepool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; - -.EXAMPLE - Create new automated instant clone pool with naming method pattern - New-HVPool -InstantClone -PoolName "InsPoolvmware" -PoolDisplayName "insPool" -Description "create instant pool" -UserAssignment FLOATING -ParentVM 'Agent_vmware' -SnapshotVM 'kb-hotfix' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -NamingMethod PATTERN -Datastores 'datastore1' -NamingPattern "inspool2" -NetBiosName 'adviewdev' -DomainAdmin root - -.EXAMPLE - Create new automated full clone pool with naming method pattern - New-HVPool -FullClone -PoolName "FullClone" -PoolDisplayName "FullClonePra" -Description "create full clone" -UserAssignment DEDICATED -Template 'powerCLI-VM-TEMPLATE' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -Datastores 'datastore1' -NamingMethod PATTERN -NamingPattern 'FullCln1' -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root - -.EXAMPLE - Create new managed manual pool from virtual center managed VirtualMachines. - New-HVPool -MANUAL -PoolName 'manualVMWare' -PoolDisplayName 'MNLPUL' -Description 'Manual pool creation' -UserAssignment FLOATING -Source VIRTUAL_CENTER -VM 'PowerCLIVM1', 'PowerCLIVM2' - -.EXAMPLE - Create new unmanaged manual pool from unmanaged VirtualMachines. - New-HVPool -MANUAL -PoolName 'unmangedVMWare' -PoolDisplayName 'unMngPl' -Description 'unmanaged Manual Pool creation' -UserAssignment FLOATING -Source UNMANAGED -VM 'myphysicalmachine.vmware.com' - -.OUTPUTS - None - -.NOTES - Author : Praveen Mathamsetty. - Author email : pmathamsetty@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 = $true,ParameterSetName = 'INSTANT_CLONE')] - [switch] - $InstantClone, - - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [switch] - $LinkedClone, - - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [switch] - $FullClone, - - [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] - [switch] - $Manual, - - [Parameter(Mandatory = $true,ParameterSetName = 'RDS')] - [switch] - $Rds, - - [Parameter(Mandatory = $true,ParameterSetName = 'JSON_FILE')] - [string] - $Spec, - - [Parameter(Mandatory = $true,ValueFromPipeline = $true,ParameterSetName = 'CLONED_POOL')] - $ClonePool, - - #desktopSpec.desktopBase.name - [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [Parameter(Mandatory = $true,ParameterSetName = 'RDS')] - [Parameter(Mandatory = $true,ParameterSetName = 'CLONED_POOL')] - [string] - $PoolName, - - #desktopSpec.desktopBase.displayName - [Parameter(Mandatory = $false)] - [string] - $PoolDisplayName = $poolName, - - #desktopSpec.desktopBase.description - [Parameter(Mandatory = $false)] - [string] - $Description = ' ', - - #desktopSpec.desktopBase.accessGroup - [Parameter(Mandatory = $false)] - [string] - $AccessGroup = 'Root', - - #desktopSpec.globalEntitlement - [Parameter(Mandatory = $false)] - [string] - $GlobalEntitlement, - - #desktopSpec.automatedDesktopSpec.desktopUserAssignment.userAssigment if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - #desktopSpec.manualDesktopSpec.desktopUserAssignment.userAssigment if MANUAL - - [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [ValidateSet('FLOATING','DEDICATED')] - [string] - $UserAssignment, - - #desktopSpec.automatedDesktopSpec.desktopUserAssignment.automaticAssignment - [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [boolean] - $AutomaticAssignment = $true, - - #desktopSpec.desktopSettings.enabled - [Parameter(Mandatory = $false)] - [boolean] - $Enable = $true, - - #desktopSpec.desktopSettings.connectionServerRestrictions - [Parameter(Mandatory = $false)] - [string[]] - $ConnectionServerRestrictions, - - #desktopSpec.automatedDesktopSpec.virtualCenter if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - #desktopSpec.manualDesktopSpec.virtualCenter if MANUAL - [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [string] - $Vcenter, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.template if FULL_CLONE - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [string] - $Template, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVM if LINKED_CLONE, INSTANT_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [string] - $ParentVM, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshotVM if LINKED_CLONE, INSTANT_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [string] - $SnapshotVM, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [string] - $VmFolder, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.hostOrCluster if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [string] - $HostOrCluster, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.resourcePool if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [string] - $ResourcePool, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [string[]] - $Datastores, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.useVSAN if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [string] - $UseVSAN, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [boolean] - $EnableProvisioning = $true, - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [boolean] - $StopOnProvisioningError = $true, - - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] - [string] - $TransparentPageSharingScope = 'VM', - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.namingMethod if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] - [ValidateSet('SPECIFIED','PATTERN')] - [string] - $NamingMethod = 'PATTERN', - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.namingPattern if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] - [string] - $NamingPattern = $poolName + '{n:fixed=4}', - - #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [int] - $MinReady = 0, - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.maxNumberOfMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [int] - $MaximumCount = 1, - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.numberOfSpareMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [int] - $SpareCount = 1, - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.provisioningTime if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [ValidateSet('ON_DEMAND','UP_FRONT')] - [string] - $ProvisioningTime = 'UP_FRONT', - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.minimumNumberOfMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [int] - $MinimumCount = 0, - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.namingPattern if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] - [string[]] - $SpecificNames = $poolName + '-1', - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.startMachinesInMaintenanceMode if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [boolean] - $StartInMaintenanceMode = $false, - - #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.numUnassignedMachinesKeptPoweredOnif LINKED_CLONE, INSTANT_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = "JSON_FILE")] - [int] - $NumUnassignedMachinesKeptPoweredOn = 1, - - #desktopSpec.automatedDesktopSpec.customizationSettings.cloneprepCustomizationSettings.instantCloneEngineDomainAdministrator if INSTANT_CLONE - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - $AdContainer = 'CN=Computers', - - [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] - [string]$NetBiosName, - - [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] - [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] - [string]$DomainAdmin = $null, - - #desktopSpec.automatedDesktopSpec.customizationSettings.customizationType if LINKED_CLONE, FULL_CLONE - [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $true,ParameterSetName = "FULL_CLONE")] - [ValidateSet('CLONE_PREP','QUICK_PREP','SYS_PREP','NONE')] - [string] - $CustType, - - #desktopSpec.automatedDesktopSpec.customizationSettings.sysprepCustomizationSettings.customizationSpec if LINKED_CLONE, FULL_CLONE - [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [Parameter(Mandatory = $false,ParameterSetName = "FULL_CLONE")] - [string] - $SysPrepName, - - #manual desktop - [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] - [ValidateSet('VIRTUAL_CENTER','UNMANAGED')] - [string] - $Source, - - [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] - [Parameter(Mandatory = $false,ParameterSetName = "JSON_FILE")] - [string[]]$VM, - - #farm - [Parameter(Mandatory = $false,ParameterSetName = 'RDS')] - [string] - $Farm, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - # - # - # - # DesktopSpec/DesktopInfo - # *DesktopBase - # +AccessGroupId - # &DesktopSettings - # DesktopLogoffSettings - # DesktopDisplayProtocolSettings - # DesktopPCoIPDisplaySettings - # DesktopAdobeFlashSettings - # DesktopAdobeFlashSettings - # DesktopMirageConfigurationOverrides - # DesktopAutomatedDesktopSpec/DesktopAutomatedDesktopData - # */+VirtualCenterId - # DesktopUserAssignment - # DesktopVirtualMachineNamingSpec/DesktopVirtualMachineNamingSettings - # DesktopPatternNamingSpec/DesktopPatternNamingSettings - # DesktopSpecificNamingSettings/DesktopSpecificNamingSettings - # DesktopVirtualCenterProvisioningSettings - # DesktopVirtualCenterProvisioningData/virtualCenterProvisioningData - # DesktopVirtualCenterStorageSettings - # DesktopVirtualCenterNetworkingSettings - # DesktopVirtualCenterManagedCommonSettings - # DesktopCustomizationSettings - # ViewComposerDomainAdministratorId - # ADContainerId - # DesktopNoCustomizationSettings - # DesktopSysprepCustomizationSettings - # CustomizationSpecId - # DesktopQuickprepCustomizationSettings - # DesktopQuickprepCustomizationSettings - # DesktopCloneprepCustomizationSettings - # InstantCloneEngineDomainAdministratorId - # DesktopManualDesktopSpec - # DesktopUserAssignment - # MachineId[] - # VirtualCenterId - # DesktopViewStorageAcceleratorSettings - # DesktopBlackoutTime[] - # DesktopVirtualCenterManagedCommonSettings - # DesktopRDSDesktopSpec - # DesktopBlackoutTime[] - # DesktopGlobalEntitlementData - # GlobalEntitlementId - - - # retrieve values from the pipeline ... takes care of "get-hvpool -poolName | New-HVPool -poolName common parameters - # - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - - if ($poolName) { - try { - $sourcePool = Get-HVPool -poolName $poolName -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVPool advanced function is loaded, $_" - break - } - if ($sourcePool) { - Write-Error "Pool with name: [$poolName] already exists" - break - } - } - - if ($spec) { - try { - $jsonObject = Get_Json_Object -specFile $spec - } catch { - Write-Error "Json file exception, $_" - break - } - if ($jsonObject.type -eq "AUTOMATED") { - $poolType = 'AUTOMATED' - if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenter) { - $vCenter = $jsonObject.AutomatedDesktopSpec.VirtualCenter - } - $userAssignment = $jsonObject.AutomatedDesktopSpec.userAssignment.userAssignment - $automaticAssignment = $jsonObject.AutomatedDesktopSpec.userAssignment.AutomaticAssignment - $netBiosName = $jsonObject.NetBiosName - if (!$jsonObject.AutomatedDesktopSpec.CustomizationSettings.AdContainer) { - Write-Host "adContainer was empty using CN=Computers" - } else { - $adContainer = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.AdContainer - } - $custType = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CustomizationType - if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "INSTANT_CLONE_ENGINE") { - $InstantClone = $true - } else { - if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "VIEW_COMPOSER") { - $LinkedClone = $true - } else { - $FullClone = $true - } - $sysPrepName = $jsonObject.SysPrepName - } - $namingMethod = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.NamingMethod - $transparentPageSharingScope = $jsonObject.AutomatedDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope - if ($namingMethod -eq "PATTERN") { - $namingPattern = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.namingPattern - $maximumCount = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.maxNumberOfMachines - $spareCount = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.numberOfSpareMachines - $provisioningTime = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.provisioningTime - } else { - $specificNames = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.specifiedNames - $startInMaintenanceMode = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode - $numUnassignedMachinesKeptPoweredOn = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn - } - if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Template) { - $template = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Template - } - if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm) { - $parentVM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm - } - if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot) { - $snapshotVM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot - } - $vmFolder = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.VmFolder - $hostOrCluster = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.HostOrCluster - $resourcePool = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ResourcePool - $dataStoreList = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores - foreach ($dtStore in $dataStoreList) { - $datastores += $dtStore.Datastore - } - } elseif ($jsonObject.type -eq "MANUAL") { - $MANUAL = $true - $poolType = 'MANUAL' - $userAssignment = $jsonObject.ManualDesktopSpec.userAssignment.userAssignment - $automaticAssignment = $jsonObject.ManualDesktopSpec.userAssignment.AutomaticAssignment - $source = $jsonObject.ManualDesktopSpec.source - $VMs = $jsonObject.ManualDesktopSpec.Machines - foreach ($vmObj in $VMs) { - $VM += $vmObj.Machine - } - - } else { - $RDS = $true - $poolType = 'RDS' - $farm = $jsonObject.RdsDesktopSpec.farm - } - $poolDisplayName = $jsonObject.base.DisplayName - $description = $jsonObject.base.Description - $accessGroup = $jsonObject.base.AccessGroup - $poolName = $jsonObject.base.name - } - - if ($PSCmdlet.MyInvocation.ExpectingInput -or $clonePool) { - - if ($clonePool -and ($clonePool.GetType().name -eq 'DesktopSummaryView')) { - $clonePool = Get-HVPool -poolName $clonePool.desktopsummarydata.name -Full - } else { - Write-Error "In pipeline did not get object of expected type DesktopSummaryView" - return - } - $poolType = $clonePool.type - $desktopBase = $clonePool.base - $desktopSettings = $clonePool.DesktopSettings - $provisioningType = $null - if ($clonePool.AutomatedDesktopData) { - $provisioningType = $clonePool.AutomatedDesktopData.ProvisioningType - $virtualCenterID = $clonePool.AutomatedDesktopData.VirtualCenter - $desktopUserAssignment = $clonePool.AutomatedDesktopData.userAssignment - $desktopVirtualMachineNamingSpec = $clonePool.AutomatedDesktopData.VmNamingSettings - $DesktopVirtualCenterProvisioningSettings = $clonePool.AutomatedDesktopData.VirtualCenterProvisioningSettings - $DesktopVirtualCenterProvisioningData = $DesktopVirtualCenterProvisioningSettings.VirtualCenterProvisioningData - $DesktopVirtualCenterStorageSettings = $DesktopVirtualCenterProvisioningSettings.VirtualCenterStorageSettings - $DesktopVirtualCenterNetworkingSettings = $DesktopVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings - $desktopVirtualCenterManagedCommonSettings = $clonePool.AutomatedDesktopData.virtualCenterManagedCommonSettings - $desktopCustomizationSettings = $clonePool.AutomatedDesktopData.CustomizationSettings - } - if (($null -eq $provisioningType) -or ($provisioningType -eq 'INSTANT_CLONE_ENGINE')) { - Write-Error "Only Automated linked clone or full clone pool support cloning" - break - } - } else { - - if ($InstantClone) { - $poolType = 'AUTOMATED' - $provisioningType = 'INSTANT_CLONE_ENGINE' - } - elseif ($LinkedClone) { - $poolType = 'AUTOMATED' - $provisioningType = 'VIEW_COMPOSER' - } - elseif ($FullClone) { - $poolType = 'AUTOMATED' - $provisioningType = 'VIRTUAL_CENTER' - } - elseif ($Manual) { $poolType = 'MANUAL' } - elseif ($RDS) { $poolType = 'RDS' } - - } - $script:desktopSpecObj = Get_Desktop_Spec -poolType $poolType -provisioningType $provisioningType -namingMethod $namingMethod - - # - # accumulate properties that are shared among various type - # - - if ($poolType -ne 'RDS') { - # - # vCenter: if $vcenterID is defined, then this is a clone - # if the user specificed the name, then find it from the list - # if none specified, then automatically use the vCenter if there is only one - # - # skips Unmanged Manual pool for VC check - if (! (($poolType -eq 'MANUAL') -and ($source -eq 'UNMANAGED'))) { - - if (!$virtualCenterID) { - $virtualCenterID = Get_Vcenter_ID -services $services -vCenter $vCenter - } - if ($null -eq $virtualCenterID) { - $handleException = $true - break - } - } - # - # populate user assignment - # - if (!$desktopUserAssignment) { - if ($desktopSpecObj.AutomatedDesktopSpec) { - $desktopSpecObj.AutomatedDesktopSpec.userAssignment.userAssignment = $userAssignment - $desktopSpecObj.AutomatedDesktopSpec.userAssignment.AutomaticAssignment = $automaticAssignment - $desktopUserAssignment = $desktopSpecObj.AutomatedDesktopSpec.userAssignment - } else { - $desktopSpecObj.ManualDesktopSpec.userAssignment.userAssignment = $userAssignment - $desktopSpecObj.ManualDesktopSpec.userAssignment.AutomaticAssignment = $automaticAssignment - $desktopUserAssignment = $desktopSpecObj.ManualDesktopSpec.userAssignment - } - - } - # - # transparentPageSharingScope - # - if (!$desktopVirtualCenterManagedCommonSettings) { - if ($desktopSpecObj.AutomatedDesktopSpec) { - $desktopSpecObj.AutomatedDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope - $desktopVirtualCenterManagedCommonSettings = $desktopSpecObj.AutomatedDesktopSpec.virtualCenterManagedCommonSettings - } else { - $desktopSpecObj.ManualDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope - $desktopVirtualCenterManagedCommonSettings = $desktopSpecObj.ManualDesktopSpec.virtualCenterManagedCommonSettings - } - } - } - # - # build out the infrastructure based on type of provisioning - # - switch ($poolType) - { - 'RDS' { - <# - Query FarmId from Farm Name - #> - $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals - $QueryFilterEquals.memberName = 'data.name' - $QueryFilterEquals.value = $farm - $defn = New-Object VMware.Hv.QueryDefinition - $defn.queryEntityType = 'FarmSummaryView' - $defn.Filter = $QueryFilterEquals - $query_service_helper = New-Object VMware.Hv.QueryServiceService - $queryResults = $query_service_helper.QueryService_Query($services,$defn) - if ($queryResults.results.Count -eq 0) { - Write-Error "No farm found with name: [$farm]" - return - } - $farmID = $queryResults.results.id - $desktopSpecObj.RdsDesktopSpec.farm = $farmID - } - 'MANUAL' { - [VMware.Hv.MachineId[]]$machineList = $null - $desktopSpecObj.ManualDesktopSpec.source = $source - if ($source -eq 'VIRTUAL_CENTER') { - # Get vCenter VMs - $vmTable = @{} - $vm | ForEach-Object { $vmTable[$_] = $_ } - $virtual_machine_helper = New-Object VMware.Hv.VirtualMachineService - $machineId = ($virtual_machine_helper.VirtualMachine_List($services,$virtualCenterId) | Where-Object { $vmTable.Contains($_.name) } | Select-Object -Property Id) - $machineList += $machineId.id - $desktopSpecObj.ManualDesktopSpec.VirtualCenter = $virtualCenterID - } else { - # Get Physical Regstered VMs - $machineList = Get-RegisteredPhysicalMachines -services $services -machinesList $VM - } - $desktopSpecObj.ManualDesktopSpec.Machines = $machineList - } - default { - if (!$desktopVirtualMachineNamingSpec) { - $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.NamingMethod = $namingMethod - if ($namingMethod -eq 'PATTERN') { - $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.namingPattern = $namingPattern - $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.maxNumberOfMachines = $maximumCount - $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.numberOfSpareMachines = $spareCount - $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.provisioningTime = $provisioningTime - - if ($provisioningTime -eq 'ON_DEMAND') { $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.minNumberOfMachines = $minimumCount } - } else { - $desktopSpecifiedName = @() - $specificNames | ForEach-Object { $desktopSpecifiedName += New-Object VMware.Hv.DesktopSpecifiedName -Property @{ 'vmName' = $_; } } - $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.specifiedNames = $desktopSpecifiedName - $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode = $startInMaintenanceMode - $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn = $numUnassignedMachinesKeptPoweredOn - } - } else { - $vmNamingSpec = New-Object VMware.Hv.DesktopVirtualMachineNamingSpec - if ($desktopVirtualMachineNamingSpec.NamingMethod -eq 'PATTERN') { - $vmNamingSpec.NamingMethod = 'PATTERN' - $vmNamingSpec.patternNamingSettings = $desktopVirtualMachineNamingSpec.patternNamingSettings - $vmNamingSpec.patternNamingSettings.namingPattern = $namingPattern - } else { - $desktopSpecifiedName = @() - $specificNames | ForEach-Object { $desktopSpecifiedName += New-Object VMware.Hv.DesktopSpecifiedName -Property @{ 'vmName' = $_; } } - $vmNamingSpec.NamingMethod = 'SPECIFIED' - $vmNamingSpec.SpecificNamingSpec = New-Object VMware.Hv.DesktopSpecificNamingSpec - $vmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn = $desktopVirtualMachineNamingSpec.specificNamingSettings.numUnassignedMachinesKeptPoweredOn - $vmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode = $desktopVirtualMachineNamingSpec.specificNamingSettings.startMachinesInMaintenanceMode - $vmNamingSpec.SpecificNamingSpec.specifiedNames = $desktopSpecifiedName - } - - } - - # - # build the VM LIST - # - $handleException = $false - try { - $desktopVirtualCenterProvisioningData = Build_VM_List -vc $virtualCenterID -vmObject $desktopVirtualCenterProvisioningData - $hostClusterId = $desktopVirtualCenterProvisioningData.HostOrCluster - $desktopVirtualCenterStorageSettings = Build_Datastore_List -hostclusterID $hostClusterId -storageObject $desktopVirtualCenterStorageSettings - $DesktopVirtualCenterNetworkingSettings = Build_Network_List -networkObject $DesktopVirtualCenterNetworkingSettings - $desktopCustomizationSettings = Build_Customization_Settings -vc $virtualCenterID -customObject $desktopCustomizationSettings - } catch { - $handleException = $true - Write-Error "Failed to create Pool with error: $_" - break - } - - if (!$DesktopVirtualCenterProvisioningSettings) { - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.enableProvisioning = $true - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $true - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = 0 - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings = $desktopCustomizationSettings - $desktopSpecObj.AutomatedDesktopSpec.ProvisioningType = $provisioningType - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenter = $virtualCenterID - } - else { - $DesktopVirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData - $DesktopVirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings - $DesktopVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings - - $DesktopAutomatedDesktopSpec = New-Object VMware.Hv.DesktopAutomatedDesktopSpec - $DesktopAutomatedDesktopSpec.ProvisioningType = $provisioningType - $DesktopAutomatedDesktopSpec.VirtualCenter = $virtualCenterID - $DesktopAutomatedDesktopSpec.userAssignment = $desktopUserAssignment - $DesktopAutomatedDesktopSpec.VmNamingSpec = $vmNamingSpec - $DesktopAutomatedDesktopSpec.VirtualCenterProvisioningSettings = $desktopVirtualCenterProvisioningSettings - $DesktopAutomatedDesktopSpec.virtualCenterManagedCommonSettings = $desktopVirtualCenterManagedCommonSettings - $DesktopAutomatedDesktopSpec.CustomizationSettings = $desktopCustomizationSettings - } - } - } - - if ($handleException) { - break - } - if (!$desktopBase) { - $accessGroup_client = New-Object VMware.Hv.AccessGroupService - $ag = $accessGroup_client.AccessGroup_List($services) | Where-Object { $_.base.name -eq $accessGroup } - $desktopSpecObj.base.AccessGroup = $ag.id - } else { - $desktopSpecObj.base = $desktopBase - } - - $desktopSpecObj.base.name = $poolName - $desktopSpecObj.base.DisplayName = $poolDisplayName - $desktopSpecObj.base.Description = $description - $desktopSpecObj.type = $poolType - - if ($desktopSettings) { $desktopSpecObj.DesktopSettings = $desktopSettings } - - if ($desktopAutomatedDesktopSpec) { - $desktopSpecObj.AutomatedDesktopSpec = $desktopAutomatedDesktopSpec - } - if ($DesktopManualDesktopSpecList) { $desktopSpecObj.ManualDesktopSpec = $DesktopManualDesktopSpecList } - if ($desktopRDSDesktopSpec) { $desktopSpecObj.RdsDesktopSpec = $RDSDesktopSpec } - if ($desktopGlobalEntitlementData) { $desktopSpecObj.GlobalEntitlementData = $desktopGlobalEntitlementData } - - # Please uncomment below code, if you want save desktopSpec object to json file - <# - $myDebug = convertto-json -InputObject $desktopSpecObj -depth 12 - $myDebug | out-file -filepath c:\temp\copieddesktop.json - #> - $desktop_helper = New-Object VMware.Hv.DesktopService - $desktop_helper.Desktop_create($services,$desktopSpecObj) - } - - end { - $desktopSpecObj = $null - [System.gc]::collect() - } - -} - -function Build_VM_List { - param( - [Parameter(Mandatory = $false)] - [VMware.Hv.DesktopVirtualCenterProvisioningData]$VmObject, - - [Parameter(Mandatory = $true)] - [VMware.Hv.VirtualCenterId]$VcID - ) - if (!$vmObject) { $vmObject = $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData } - if ($template) { - $vm_template_helper = New-Object VMware.Hv.VmTemplateService - $templateList = $vm_template_helper.VmTemplate_List($services,$vcID) - $templateVM = $templateList | Where-Object { $_.name -eq $template } - if ($null -eq $templateVM) { - throw "No template VM found with Name: [$template]" - } - $vmObject.Template = $templateVM.id - $dataCenterID = $templateVM.datacenter - $vmObject.datacenter = $dataCenterID - } - if ($parentVM) { - $base_imageVm_helper = New-Object VMware.Hv.BaseImageVmService - $parentList = $base_imageVm_helper.BaseImageVm_List($services,$vcID) - $parentVmObj = $parentList | Where-Object { $_.name -eq $parentVM } - if ($null -eq $parentVMObj) { - throw "No parent VM found with Name: [$parentVM]" - } - $vmObject.ParentVm = $parentVmObj.id - $dataCenterID = $parentVmObj.datacenter - $vmObject.datacenter = $dataCenterID - } - if ($snapshotVM) { - $baseImageSnapshot_helper = New-Object VMware.Hv.BaseImageSnapshotService - $snapshotList = $baseImageSnapshot_helper.BaseImageSnapshot_List($services,$parentVmObj.id) - $snapshotVmObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } - if ($null -eq $snapshotVmObj) { - throw "No sanpshot found with Name: [$snapshotVM]" - } - $vmObject.Snapshot = $snapshotVmObj.id - } - if ($vmFolder) { - $vmFolder_helper = New-Object VMware.Hv.VmFolderService - $folders = $vmFolder_helper.VmFolder_GetVmFolderTree($services,$vmObject.datacenter) - $folderList = @() - $folderList += $folders - while ($folderList.Length -gt 0) { - $item = $folderList[0] - if ($item -and !$_.folderdata.incompatiblereasons.inuse -and !$_.folderdata.incompatiblereasons.viewcomposerreplicafolder -and ($item.folderdata.name -eq $vmFolder)) { - $vmObject.VmFolder = $item.id - break - } - foreach ($folderItem in $item.children) { - $folderList += $folderItem - } - $folderList = $folderList[1..$folderList.Length] - } - if ($null -eq $vmObject.VmFolder) { - throw "No vmfolder found with Name: [$vmFolder]" - } - } - if ($hostOrCluster) { - $vmFolder_helper = New-Object VMware.Hv.HostOrClusterService - $hostClusterList = ($vmFolder_helper.HostOrCluster_GetHostOrClusterTree($services,$vmobject.datacenter)).treeContainer.children.info - $hostClusterObj = $hostClusterList | Where-Object { $_.name -eq $hostOrCluster } - if ($null -eq $hostClusterObj) { - throw "No hostOrCluster found with Name: [$hostOrCluster]" - } - $vmObject.HostOrCluster = $hostClusterObj.id - } - if ($resourcePool) { - $resourcePool_helper = New-Object VMware.Hv.ResourcePoolService - $resourcePoolList = $resourcePool_helper.ResourcePool_GetResourcePoolTree($services,$vmobject.HostOrCluster) - $resourcePoolObj = $resourcePoolList | Where-Object { $_.resourcepooldata.name -eq $resourcePool } - if ($null -eq $resourcePoolObj) { - throw "No hostOrCluster found with Name: [$resourcePool]" - } - $vmObject.ResourcePool = $resourcePoolObj.id - } - return $vmObject -} - -function Build_Datastore_List { - param( - [Parameter(Mandatory = $false)] - [VMware.Hv.DesktopVirtualCenterStorageSettings]$StorageObject, - - [Parameter(Mandatory = $true)] - [VMware.Hv.HostOrClusterId]$HostClusterID - ) - if (!$storageObject) { - $storageObject = New-Object VMware.Hv.DesktopVirtualCenterStorageSettings - $storageAcceleratorList = @{ - 'useViewStorageAccelerator' = $false - } - $desktopViewStorageAcceleratorSettings = New-Object VMware.Hv.DesktopViewStorageAcceleratorSettings -Property $storageAcceleratorList - $storageObject.viewStorageAcceleratorSettings = $desktopViewStorageAcceleratorSettings - $desktopSpaceReclamationSettings = New-Object VMware.Hv.DesktopSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $false } - $desktopPersistentDiskSettings = New-Object VMware.Hv.DesktopPersistentDiskSettings -Property @{ 'redirectWindowsProfile' = $false } - $desktopNonPersistentDiskSettings = New-Object VMware.Hv.DesktopNonPersistentDiskSettings -Property @{ 'redirectDisposableFiles' = $false } - - $desktopViewComposerStorageSettingsList = @{ - 'useSeparateDatastoresReplicaAndOSDisks' = $false; - 'useNativeSnapshots' = $false; - 'spaceReclamationSettings' = $desktopSpaceReclamationSettings; - 'persistentDiskSettings' = $desktopPersistentDiskSettings; - 'nonPersistentDiskSettings' = $desktopNonPersistentDiskSettings - } - if (!$FullClone) { - $storageObject.ViewComposerStorageSettings = New-Object VMware.Hv.DesktopViewComposerStorageSettings -Property $desktopViewComposerStorageSettingsList - } - } - if ($datastores) { - $datastore_helper = New-Object VMware.Hv.DatastoreService - $datastoreList = $datastore_helper.Datastore_ListDatastoresByHostOrCluster($services,$hostClusterID) - $datastoresSelected = @() - foreach ($ds in $datastores) { - $datastoresSelected += ($datastoreList | Where-Object { $_.datastoredata.name -eq $ds }).id - } - foreach ($ds in $datastoresSelected) { - $myDatastores = New-Object VMware.Hv.DesktopVirtualCenterDatastoreSettings - $myDatastores.Datastore = $ds - $mydatastores.StorageOvercommit = 'UNBOUNDED' - $storageObject.Datastores += $myDatastores - } - } - if ($storageObject.Datastores.Count -eq 0) { - throw "No datastore found with Name: [$datastores]" - } - if ($useVSAN) { $storageObject.useVSAN = $useVSAN } - return $storageObject -} - -function Build_Network_List { - param( - [Parameter(Mandatory = $false)] - [VMware.Hv.DesktopVirtualCenterNetworkingSettings]$NetworkObject - ) - if (!$networkObject) { - $networkObject = $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings - } - return $networkObject -} - -function Build_Customization_Settings { - param( - [Parameter(Mandatory = $false)] - [VMware.Hv.DesktopCustomizationSettings]$CustomObject, - - [Parameter(Mandatory = $true)] - [VMware.Hv.VirtualCenterId]$VcID - ) - if (!$customObject) { - # View Composer and Instant Clone Engine Active Directory container for QuickPrep and ClonePrep. This must be set for Instant Clone Engine or SVI sourced desktops. - if ($InstantClone -or $LinkedClone) { - $ad_domain_helper = New-Object VMware.Hv.ADDomainService - $adDomianId = ($ad_domain_helper.ADDomain_List($services) | Where-Object { $_.NetBiosName -eq $netBiosName } | Select-Object -Property id) - if ($null -eq $adDomianId) { - throw "No Domain found with netBiosName: [$netBiosName]" - } - $ad_container_helper = New-Object VMware.Hv.AdContainerService - $adContainerId = ($ad_container_helper.ADContainer_ListByDomain($services,$adDomianId.id) | Where-Object { $_.Rdn -eq $adContainer } | Select-Object -Property id).id - if ($null -eq $adContainerId) { - throw "No AdContainer found with name: [$adContainer]" - } - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.AdContainer = $adContainerId - } - if ($InstantClone) { - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'CLONE_PREP' - $instantCloneEngineDomainAdministrator_helper = New-Object VMware.Hv.InstantCloneEngineDomainAdministratorService - $instantCloneEngineDomainAdministrator = ($instantCloneEngineDomainAdministrator_helper.InstantCloneEngineDomainAdministrator_List($services) | Where-Object { $_.namesData.dnsName -match $netBiosName }) - if (![string]::IsNullOrWhitespace($domainAdmin)) { - $instantCloneEngineDomainAdministrator = ($instantCloneEngineDomainAdministrator | Where-Object { $_.base.userName -eq $domainAdmin }).id - } else { - $instantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator[0].id - } - if ($null -eq $instantCloneEngineDomainAdministrator) { - throw "No Instant Clone Engine Domain Administrator found with netBiosName: [$netBiosName]" - } - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings = Get_CustomizationSettings_Objects - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator - } - else { - if ($LinkedClone) { - $viewComposerDomainAdministrator_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService - $ViewComposerDomainAdministratorID = ($viewComposerDomainAdministrator_helper.ViewComposerDomainAdministrator_List($services,$vcID) | Where-Object { $_.base.domain -match $netBiosName }) - if (![string]::IsNullOrWhitespace($domainAdmin)) { - $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministratorID | Where-Object { $_.base.userName -ieq $domainAdmin }).id - } else { - $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id - } - if ($null -eq $ViewComposerDomainAdministratorID) { - throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" - } - if ($custType -eq 'SYS_PREP') { - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings = Get_CustomizationSettings_Objects - - # Get SysPrep CustomizationSpec ID - $customization_spec_helper = New-Object VMware.Hv.CustomizationSpecService - $sysPrepIds = $customization_spec_helper.CustomizationSpec_List($services,$vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id - if ($sysPrepIds.Count -eq 0) { - throw "No Sysprep Customization Spec found with Name: [$sysPrepName]" - } - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id - } elseif ($custType -eq 'QUICK_PREP') { - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'QUICK_PREP' - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings = Get_CustomizationSettings_Objects - } else { - throw "The customization type: [$custType] is not supported for LinkedClone Pool" - } - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.DomainAdministrator = $ViewComposerDomainAdministratorID - } elseif ($FullClone) { - if ($custType -eq 'SYS_PREP') { - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings = Get_CustomizationSettings_Objects - # Get SysPrep CustomizationSpec ID - $customization_spec_helper = New-Object VMware.Hv.CustomizationSpecService - $sysPrepIds = $customization_spec_helper.CustomizationSpec_List($services,$vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id - if ($sysPrepIds.Count -eq 0) { - throw "No Sysprep Customization Spec found with Name: [$sysPrepName]" - } - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id - } elseif ($custType -eq 'NONE') { - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings = Get_CustomizationSettings_Objects - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings.DoNotPowerOnVMsAfterCreation = $false - $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = "NONE" - } else { - throw "The customization type: [$custType] is not supported for FullClone Pool." - } - } - } - $customObject = $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings - } - return $customObject -} - -function Get_CustomizationSettings_Objects { - if ($InstantClone) { - return New-Object VMware.Hv.DesktopCloneprepCustomizationSettings - } elseif ($LinkedClone) { - if ($custType -eq 'QUICK_PREP') { - return New-Object VMware.Hv.DesktopQuickPrepCustomizationSettings - } else { - return New-Object VMware.Hv.DesktopSysPrepCustomizationSettings - } - } else { - if ($custType -eq 'SYS_PREP') { - return New-Object VMware.Hv.DesktopSysPrepCustomizationSettings - } else { - return New-Object VMware.Hv.DesktopNoCustomizationSettings - } - } -} - -function Get_Desktop_Spec { - - param( - [Parameter(Mandatory = $true)] - [string]$PoolType, - - [Parameter(Mandatory = $false)] - [string]$ProvisioningType, - - [Parameter(Mandatory = $false)] - [string]$NamingMethod - ) - $desktop_helper = New-Object VMware.Hv.DesktopService - $desktop_spec_helper = $desktop_helper.getDesktopSpecHelper() - $desktop_spec_helper.setType($poolType) - if ($poolType -eq $desktop_spec_helper.TYPE_AUTOMATED) { - if ($namingMethod -eq 'PATTERN') { - $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings = $desktop_helper.getDesktopPatternNamingSettingsHelper().getDataObject() - } else { - $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec = $desktop_helper.getDesktopSpecificNamingSpecHelper().getDataObject() - } - if ($provisioningType -ne 'VIRTUAL_CENTER') { - $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings = $desktop_helper.getDesktopViewComposerStorageSettingsHelper().getDataObject() - } - } elseif ($poolType -eq 'MANUAL') { - $desktop_spec_helper.getDataObject().ManualDesktopSpec.userAssignment = $desktop_helper.getDesktopUserAssignmentHelper().getDataObject() - $desktop_spec_helper.getDataObject().ManualDesktopSpec.viewStorageAcceleratorSettings = $desktop_helper.getDesktopViewStorageAcceleratorSettingsHelper().getDataObject() - $desktop_spec_helper.getDataObject().ManualDesktopSpec.virtualCenterManagedCommonSettings = $desktop_helper.getDesktopVirtualCenterManagedCommonSettingsHelper().getDataObject() - } else { - $desktop_spec_helper.getDataObject().RdsDesktopSpec = $desktop_helper.getDesktopRDSDesktopSpecHelper().getDataObject() - } - return $desktop_spec_helper.getDataObject() - -} - -function Remove-HVFarm { -<# -.SYNOPSIS - Deletes specified farm(s). - -.DESCRIPTION - This function deletes the farm(s) with the specified name/object(s) from the Connection Server. Optionally, user can pipe the farm object(s) as input to this function. - -.PARAMETER FarmName - Name of the farm to be deleted. - -.PARAMETER Farm - Object(s) of the farm to be deleted. Object(s) should be of type FarmSummaryView/FarmInfo. - -.PARAMETER HvServer - Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. - -.EXAMPLE - Remove-HVFarm -FarmName 'Farm-01' -HvServer $hvServer - -.EXAMPLE - $farm_array | Remove-HVFarm -HvServer $hvServer - -.EXAMPLE - $farm1 = Get-HVFarm -FarmName 'Farm-01' - Remove-HVFarm -Farm $farm1 - -.OUTPUTS - None - -.NOTES - Author : Ankit Gupta. - Author email : guptaa@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 = $true,ParameterSetName = 'option')] - [string] - [ValidateNotNullOrEmpty()] $FarmName, - - # Farmobject - [Parameter(ValueFromPipeline = $true,Mandatory = $true,ParameterSetName = 'pipeline')] - [ValidateNotNullOrEmpty()] $Farm, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - process { - $farmList = @() - if ($farmName) { - try { - $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" - break - } - if ($farmSpecObj) { - foreach ($farmObj in $farmSpecObj) { - $farmList += $farmObj.id - } - } else { - Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farmName]" - break - } - } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { - foreach ($item in $farm) { - if ($item.GetType().name -eq 'FarmInfo' -or $item.GetType().name -eq 'FarmSummaryView') { - $farmList += $item.id - } - else { - Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" - [System.gc]::collect() - return - } - } - } - $farm_service_helper = New-Object VMware.Hv.FarmService - foreach ($item in $farmList) { - $farm_service_helper.Farm_Delete($services, $item) - } - Write-Host "Farm Deleted" - - } - end { - [System.gc]::collect() - } -} - -function Remove-HVPool { -<# -.SYNOPSIS - Deletes specified pool(s). - -.DESCRIPTION - This function deletes the pool(s) with the specified name/object(s) from Connection Server. This can be used for deleting any pool irrespective of its type. - Optionally, user can pipe the pool object(s) as input to this function. - -.PARAMETER PoolName - Name of the pool to be deleted. - -.PARAMETER Pool - Object(s) of the pool to be deleted. - -.PARAMETER DeleteFromDisk - Switch parameter to delete the virtual machine(s) from the disk. - -.PARAMETER HvServer - View API service object of Connect-HVServer cmdlet. - -.PARAMETER TerminateSession - Logs off a session forcibly to virtual machine(s). This operation will also log off a locked session. - -.EXAMPLE - Remove-HVPool -HvServer $hvServer -PoolName 'FullClone' -DeleteFromDisk - -.EXAMPLE - $pool_array | Remove-HVPool -HvServer $hvServer -DeleteFromDisk - -.EXAMPLE - Remove-HVPool -Pool $pool1 - -.OUTPUTS - None - -.NOTES - Author : Praveen Mathamsetty. - Author email : pmathamsetty@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,ParameterSetName = 'option')] - [string] $poolName, - - # PoolObject - [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] - $Pool, - - [Parameter(Mandatory = $false)] - [switch] $TerminateSession = $false, - - [Parameter(Mandatory = $false)] - [switch] $DeleteFromDisk, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - $poolList = @() - if ($poolName) { - try { - $myPools = get-hvpool -poolName $poolName -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVPool advanced function is loaded, $_" - break - } - if ($myPools) { - foreach ($poolObj in $myPools) { - $poolList += $poolObj.id - } - } else { - Write-Error "No desktopsummarydata found with pool name: [$pool]" - break - } - } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { - foreach ($item in $pool) { - if (($item.GetType().name -eq 'DesktopInfo') -or ($item.GetType().name -eq 'DesktopSummaryView')) { - $poolList += $item.id - } - else { - Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" - [System.gc]::collect() - return - } - } - } - $desktop_service_helper = New-Object VMware.Hv.DesktopService - $deleteSpec = New-Object VMware.Hv.DesktopDeleteSpec - $deleteSpec.DeleteFromDisk = $deleteFromDisk - foreach ($item in $poolList) { - if ($terminateSession) { - #Terminate session - $queryResults = Get-HVQueryResults MachineSummaryView (Get-HVQueryFilter base.desktop -eq $item) - $sessions += $queryResults.base.session - - if ($null -ne $sessions) { - $session_service_helper = New-Object VMware.Hv.SessionService - try { - Write-Host "Terminating Sessions, it may take few seconds..." - $session_service_helper.Session_LogoffSessionsForced($services,$sessions) - } catch { - Write-Host "Warning: Terminate Session failed." - } - } else { - Write-Host "No session found." - } - } - Write-Host "Deleting Pool" - $desktop_service_helper.Desktop_Delete($services,$item,$deleteSpec) - } - } - - end { - [System.gc]::collect() - } -} - -function Set-HVFarm { -<# -.SYNOPSIS - Edit farm configuration by passing key/values as parameters/json. - -.DESCRIPTION - This function allows user to edit farm configuration by passing key/value pairs. Optionally, user can pass a JSON spec file. User can also pipe the farm object(s) as input to this function. - -.PARAMETER FarmName - Name of the farm to edit. - -.PARAMETER Farm - Object(s) of the farm to edit. Object(s) should be of type FarmSummaryView/FarmInfo. - -.PARAMETER Key - Property names path separated by . (dot) from the root of desktop spec. - -.PARAMETER Value - Property value corresponds to above key name. - -.PARAMETER Spec - Path of the JSON specification file containing key/value pair. - -.PARAMETER HvServer - Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. - -.EXAMPLE - Set-HVFarm -FarmName 'Farm-o1' -Spec 'C:\Edit-HVFarm\ManualEditFarm.json' - -.EXAMPLE - Set-HVFarm -FarmName 'Farm-o1' -Key 'base.description' -Value 'updated description' - -.EXAMPLE - $farm_array | Set-HVFarm -Key 'base.description' -Value 'updated description' - -.OUTPUTS - None - -.NOTES - Author : Ankit Gupta. - Author email : guptaa@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,ParameterSetName = 'option')] - [string]$FarmName, - - [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] - $Farm, - - [Parameter(Mandatory = $false)] - [string]$Key, - - [Parameter(Mandatory = $false)] - $Value, - - [Parameter(Mandatory = $false)] - [string]$Spec, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - $farmList = @() - if ($farmName) { - try { - $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" - break - } - if ($farmSpecObj) { - foreach ($farmObj in $farmSpecObj) { - $farmList += $farmObj.id - } - } else { - Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farmName]" - break - } - } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { - foreach ($item in $farm) { - if ($item.GetType().name -eq 'FarmInfo' -or $item.GetType().name -eq 'FarmSummaryView') { - $farmList += $item.id - } - else { - Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" - [System.gc]::collect() - return - } - } - } - - $updates = @() - if ($key -and $value) { - $updates += Get_MapEntry -key $key -value $value - } elseif ($key -or $value) { - Write-Error "Both key:[$key] and value:[$value] need to be specified" - } - if ($spec) { - $specObject = Get_Json_Object -specFile $spec - foreach ($member in ($specObject.PSObject.Members | Where-Object { $_.MemberType -eq 'NoteProperty' })) { - $updates += Get_MapEntry -key $member.name -value $member.value - } - } - $farm_service_helper = New-Object VMware.Hv.FarmService - foreach ($item in $farmList) { - $farm_service_helper.Farm_Update($services,$item,$updates) - } - } - - end { - $updates = $null - [System.gc]::collect() - } -} - -function Set-HVPool { -<# -.SYNOPSIS - Sets the existing pool properties. - -.DESCRIPTION - This cmdlet allows user to edit pool configuration by passing key/value pair. Optionally, user can pass a JSON spec file. - -.PARAMETER PoolName - Name of the pool to edit. - -.PARAMETER Pool - Object(s) of the pool to edit. - -.PARAMETER Key - Property names path separated by . (dot) from the root of desktop spec. - -.PARAMETER Value - Property value corresponds to above key name. - -.PARAMETER HvServer - View API service object of Connect-HVServer cmdlet. - -.PARAMETER Spec - Path of the JSON specification file containing key/value pair. - -.EXAMPLE - Set-HVPool -PoolName 'ManualPool' -Spec 'C:\Edit-HVPool\EditPool.json' - -.EXAMPLE - Set-HVPool -PoolName 'RDSPool' -Key 'base.description' -Value 'update description' - -.OUTPUTS - None - -.NOTES - Author : Praveen Mathamsetty. - Author email : pmathamsetty@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,ParameterSetName = 'option')] - [string]$PoolName, - - #pool object - [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] - $Pool, - - [Parameter(Mandatory = $false)] - [string]$Key, - - [Parameter(Mandatory = $false)] - $Value, - - [Parameter(Mandatory = $false)] - [string]$Spec, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - $poolList = @() - if ($poolName) { - try { - $desktopPools = Get-HVPool -poolName $poolName -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVPool advanced function is loaded, $_" - break - } - if ($desktopPools) { $poolList += $desktopPools.id } - } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { - foreach ($item in $pool) { - if (($item.GetType().name -eq 'DesktopInfo') -or ($item.GetType().name -eq 'DesktopSummaryView')) { - $poolList += $item.id - } - else { - Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" - [System.gc]::collect() - return - } - } - } - $updates = @() - if ($key -and $value) { - $updates += Get_MapEntry -key $key -value $value - } elseif ($key -or $value) { - Write-Error "Both key:[$key] and value:[$value] needs to be specified" - } - if ($spec) { - try { - $specObject = Get_Json_Object -specFile $spec - } catch { - Write-Error "Json file exception, $_" - return - } - foreach ($member in ($specObject.PSObject.Members | Where-Object { $_.MemberType -eq 'NoteProperty' })) { - $updates += Get_MapEntry -key $member.name -value $member.value - } - } - - $desktop_helper = New-Object VMware.Hv.DesktopService - foreach ($item in $poolList) { - $desktop_helper.Desktop_Update($services,$item,$updates) - } - } - - end { - [System.gc]::collect() - } -} - -function Start-HVFarm { -<# -.SYNOPSIS - Perform maintenance tasks on the farm(s). - -.DESCRIPTION - This function is used to perform maintenance tasks like enable/disable, start/stop and recompose the farm. - -.PARAMETER Farm - Name/Object(s) of the farm. Object(s) should be of type FarmSummaryView/FarmInfo. - -.PARAMETER Enable - Switch to enable the farm(s). - -.PARAMETER Disable - Switch to disable the farm(s). - -.PARAMETER Start - Switch to enable provisioning immediately for the farm(s). It's applicable only for 'AUTOMATED' farm type. - -.PARAMETER Stop - Switch to disable provisioning immediately for the farm(s). It's applicable only for 'AUTOMATED' farm type. - -.PARAMETER Recompose - Switch for recompose operation. Requests a recompose of RDS Servers in the specified 'AUTOMATED' farm. This marks the RDS Servers for recompose, which is performed asynchronously. - -.PARAMETER StartTime - Specifies when to start the operation. If unset, the operation will begin immediately. - -.PARAMETER LogoffSetting - Determines when to perform the operation on machines which have an active session. This property will be one of: - "FORCE_LOGOFF" - Users will be forced to log off when the system is ready to operate on their RDS Servers. Before being forcibly logged off, users may have a grace period in which to save their work (Global Settings). - "WAIT_FOR_LOGOFF" - Wait for connected users to disconnect before the task starts. The operation starts immediately on RDS Servers without active sessions. - -.PARAMETER StopOnFirstError - Indicates that the operation should stop on first error. - -.PARAMETER Servers - The RDS Server(s) id to recompose. Provide a comma separated list for multiple RDSServerIds. - -.PARAMETER ParentVM - New base image VM for automated farm's RDS Servers. This must be in the same datacenter as the base image of the RDS Server. - -.PARAMETER SnapshotVM - Base image snapshot for the Automated Farm's RDS Servers. - -.PARAMETER Vcenter - Virtual Center server-address (IP or FQDN) of the given farm. This should be same as provided to the Connection Server while adding the vCenter server. - -.PARAMETER HvServer - Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. - -.EXAMPLE - Start-HVFarm -Recompose -Farm 'Farm-01' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' - -.EXAMPLE - Start-HVFarm -Farm 'Farm-01' -Enable - -.EXAMPLE - Start-HVFarm -Farm 'Farm-01' -Disable - -.EXAMPLE - Start-HVFarm -Farm 'Farm-01' -Start - -.EXAMPLE - Start-HVFarm -Farm 'Farm-01' -Stop - -.EXAMPLE - $myTime = Get-Date '10/03/2016 12:30:00' - Start-HVFarm -Farm 'Farm-01' -Recompose -LogoffSetting 'FORCE_LOGOFF' -ParentVM 'ParentVM' -SnapshotVM 'SnapshotVM' -StartTime $myTime - -.OUTPUTS - None - -.NOTES - Author : Ankit Gupta. - Author email : guptaa@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 = $true,ValueFromPipeline = $true)] - $Farm, - - [Parameter(Mandatory = $false,ParameterSetName = 'ENABLE')] - [switch]$Enable, - - [Parameter(Mandatory = $false,ParameterSetName = 'DISABLE')] - [switch]$Disable, - - [Parameter(Mandatory = $false,ParameterSetName = 'START')] - [switch]$Start, - - [Parameter(Mandatory = $false,ParameterSetName = 'STOP')] - [switch]$Stop, - - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [switch]$Recompose, - - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [System.DateTime]$StartTime, - - [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] - [ValidateSet('FORCE_LOGOFF','WAIT_FOR_LOGOFF')] - [string]$LogoffSetting, - - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [boolean]$StopOnFirstError = $true, - - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [string []]$Servers, - - [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] - [string]$ParentVM, - - [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] - [string]$SnapshotVM, - - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [string]$Vcenter, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - $farmList = @{} - $farmType = @{} - $farmSource = @{} - $farm_service_helper = New-Object VMware.Hv.FarmService - if ($farm) { - if ($farm.GetType().name -eq 'FarmInfo') { - $id = $farm.id - $name = $farm.data.name - $type = $farm.type - } - elseif ($farm.GetType().name -eq 'FarmSummaryView') { - $id = $farm.id - $name = $farm.data.name - $type = $farm.data.type - } - elseif ($farm.GetType().name -eq 'String') { - try { - $farmSpecObj = Get-HVFarm -farmName $farm -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" - break - } - if ($farmSpecObj) { - $id = $farmSpecObj.id - $name = $farmSpecObj.data.name - $type = $farmSpecObj.data.type - } else { - Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farm]" - break - } - } else { - Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" - break - } - if ($type -eq 'AUTOMATED') { - $source = 'VIEW_COMPOSER' - } - $farmList.Add($id,$name) - $farmType.Add($id,$type) - $farmSource.Add($id,$source) - } - } - - - end { - foreach ($item in $farmList.Keys) { - $operation = $PsCmdlet.ParameterSetName - Write-Host "Performing $operation" on $farmList.$item - switch ($operation) { - 'RECOMPOSE' { - if ($farmSource.$item -ne 'VIEW_COMPOSER') { - Write-Error "RECOMPOSE operation is not supported for farm with name [$farmList.$item]" - break - } else { - $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter - if ($null -eq $vcId) { - break - } - $serverList = Get-AllRDSServersInFarm -services $services -farm $item -serverList $servers - if ($null -eq $serverList) { - Write-Error "No servers found for the farm [$item]" - } - $spec = New-Object VMware.Hv.FarmRecomposeSpec - $spec.LogoffSetting = $logoffSetting - $spec.StopOnFirstError = $stopOnFirstError - $spec.RdsServers = $serverList - try { - $spec = Set_Spec_Vms_Farm -vcId $vcId -spec $spec - } catch { - Write-Error "RECOMPOSE task failed with error: $_" - break - } - if ($startTime) { $spec.startTime = $startTime } - # Update Base Image VM and Snapshot in Farm - $updates = @() - $updates += Get_MapEntry -key 'automatedFarmData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVm' -value $spec.ParentVM - $updates += Get_MapEntry -key 'automatedFarmData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshot' -value $spec.Snapshot - $farm_service_helper.Farm_Update($services,$item,$updates) - - $farm_service_helper.Farm_Recompose($services,$item,$spec) - } - } - 'ENABLE' { - $map = New-Object VMware.Hv.MapEntry - $map.key = 'data.enabled' - $map.value = $true - $farm_service_helper.Farm_Update($services,$item,$map) - } - 'DISABLE' { - $map = New-Object VMware.Hv.MapEntry - $map.key = 'data.enabled' - $map.value = $false - $farm_service_helper.Farm_Update($services,$item,$map) - } - 'START' { - if ($farmType.$item -ne 'AUTOMATED') { - Write-Error "Start operation is not supported for farm with name [$farmList.$item]" - break - } else { - $map = New-Object VMware.Hv.MapEntry - $map.key = 'automatedFarmData.virtualCenterProvisioningSettings.enableProvisioning' - $map.value = $true - $farm_service_helper.Farm_Update($services,$item,$map) - } - } - 'STOP' { - if ($farmType.$item -ne 'AUTOMATED') { - Write-Error "STOP operation is not supported for farm with name [$farmList.$item]" - break - } else { - $map = New-Object VMware.Hv.MapEntry - $map.key = 'automatedFarmData.virtualCenterProvisioningSettings.enableProvisioning' - $map.value = $false - $farm_service_helper.Farm_Update($services,$item,$map) - } - } - } - return - } - } - -} - -function Get-AllRDSServersInFarm ($Services,$Farm,$ServerList) { - [VMware.Hv.RDSServerId[]]$servers = @() - $query_service_helper = New-Object VMware.Hv.QueryServiceService - $remainingCount = 1 # run through loop at least once - $query = New-Object VMware.Hv.QueryDefinition - $query.queryEntityType = 'RDSServerSummaryView' - $farmFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'MemberName' = 'base.farm'; 'value' = $farm } - if ($serverList) { - $serverFilters = [VMware.Hv.queryFilter[]]@() - foreach ($name in $serverList) { - $serverFilters += (New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $name }) - } - $serverList = New-Object VMware.Hv.QueryFilterOr -Property @{ 'filters' = $serverFilters } - $treeList = @() - $treeList += $serverList - $treelist += $farmFilter - $query.Filter = New-Object VMware.Hv.QueryFilterAnd -Property @{ 'filters' = $treeList } - } else { - $query.Filter = $farmFilter - } - while ($remainingCount -ge 1) { - $queryResults = $query_service_helper.QueryService_Query($services,$query) - $results = $queryResults.results - $servers += $results.id - $query.StartingOffset = $query.StartingOffset + $queryResults.results.Count - $remainingCount = $queryResults.RemainingCount - } - return $servers -} - -function Set_Spec_Vms_Farm { - param( - [Parameter(Mandatory = $true)] - [VMware.Hv.VirtualCenterId]$VcID, - - [Parameter(Mandatory = $true)] - $Spec - ) - if ($parentVM) { - $baseImage_service_helper = New-Object VMware.Hv.BaseImageVmService - $parentList = $baseImage_service_helper.BaseImageVm_List($services, $vcID) - $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } - if ($null -eq $parentVMObj) { - throw "No Parent VM found with name: [$parentVM]" - } - $spec.ParentVm = $parentVMObj.id - } - if ($snapshotVM) { - $parentVM = $spec.ParentVm.id - $baseImageSnapshot_service_helper = New-Object VMware.Hv.BaseImageSnapshotService - $snapshotList = $baseImageSnapshot_service_helper.BaseImageSnapshot_List($services, $spec.ParentVm) - $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } - if ($null -eq $snapshotVMObj) { - throw "No Snapshot found with name: [$snapshotVM] for VM name: [$parentVM] " - } - $spec.Snapshot = $snapshotVMObj.id - } - return $spec -} - -function Start-HVPool { -<# -.SYNOPSIS - Perform maintenance tasks on Pool. - -.DESCRIPTION - This cmdlet is used to perform maintenance tasks like enable/disable the pool, enable/disable the provisioning of a pool, refresh, rebalance, recompose, push image and cancel image. Push image and Cancel image tasks only applies for instant clone pool. - -.PARAMETER Pool - Name/Object(s) of the pool. - -.PARAMETER Enable - Switch parameter to enable the pool. - -.PARAMETER Disable - Switch parameter to disable the pool. - -.PARAMETER Start - Switch parameter to start the pool. - -.PARAMETER Stop - Switch parameter to stop the pool. - -.PARAMETER Refresh - Switch parameter to refresh operation. - -.PARAMETER Recompose - Switch parameter to recompose operation. - -.PARAMETER Rebalance - Switch parameter to rebalance operation. - -.PARAMETER SchedulePushImage - Switch parameter to push image operation. - -.PARAMETER CancelPushImage - Switch parameter to cancel push image operation. - -.PARAMETER StartTime - Specifies when to start the operation. If unset, the operation will begin immediately. - -.PARAMETER LogoffSetting - Determines when to perform the operation on machines which have an active session. This property will be one of: - 'FORCE_LOGOFF' - Users will be forced to log off when the system is ready to operate on their virtual machines. - 'WAIT_FOR_LOGOFF' - Wait for connected users to disconnect before the task starts. The operation starts immediately on machines without active sessions. - -.PARAMETER StopOnFirstError - Indicates that the operation should stop on first error. - -.PARAMETER Machines - The machine names to recompose. These must be associated with the pool. - -.PARAMETER ParentVM - New base image VM for the desktop. This must be in the same datacenter as the base image of the desktop. - -.PARAMETER SnapshotVM - Name of the snapshot used in pool deployment. - -.PARAMETER Vcenter - Virtual Center server-address (IP or FQDN) of the given pool. This should be same as provided to the Connection Server while adding the vCenter server. - -.PARAMETER HvServer - View API service object of Connect-HVServer cmdlet. - -.EXAMPLE - Start-HVPool -Recompose -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' - -.EXAMPLE - Start-HVPool -Refresh -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF - -.EXAMPLE - $myTime = Get-Date '10/03/2016 12:30:00' - Start-HVPool -Eebalance -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -StartTime $myTime - -.EXAMPLE - Start-HVPool -SchedulePushImage -Pool 'InstantPool' -LogoffSetting FORCE_LOGOFF -ParentVM 'InsParentVM' -SnapshotVM 'InsSnapshotVM' - -.EXAMPLE - Start-HVPool -CancelPushImage -Pool 'InstantPool' - -.EXAMPLE - Start-HVPool -Pool 'TestPool' -Enable - -.OUTPUTS - None - -.NOTES - Author : Praveen Mathamsetty. - Author email : pmathamsetty@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( - # handles both objects and string - [Parameter(Mandatory = $true,ValueFromPipeline = $true)] - $Pool, - - [Parameter(Mandatory = $false,ParameterSetName = 'ENABLE')] - [switch]$Enable, - - [Parameter(Mandatory = $false,ParameterSetName = 'DISABLE')] - [switch]$Disable, - - [Parameter(Mandatory = $false,ParameterSetName = 'START')] - [switch]$Start, - - [Parameter(Mandatory = $false,ParameterSetName = 'STOP')] - [switch]$Stop, - - [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] - [switch]$Refresh, - - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [switch]$Recompose, - - [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] - [switch]$Rebalance, - - [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] - [switch]$SchedulePushImage, - - [Parameter(Mandatory = $false,ParameterSetName = 'CANCEL_PUSH_IMAGE')] - [switch]$CancelPushImage, - - [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] - [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] - [System.DateTime]$StartTime, - - [Parameter(Mandatory = $true,ParameterSetName = 'REBALANCE')] - [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] - [Parameter(Mandatory = $true,ParameterSetName = 'REFRESH')] - [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] - [ValidateSet('FORCE_LOGOFF','WAIT_FOR_LOGOFF')] - [string]$LogoffSetting, - - [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] - [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] - [boolean]$StopOnFirstError = $true, - - [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] - [string []]$Machines, - - [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] - [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] - [string]$ParentVM, - - [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] - [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] - [string]$SnapshotVM, - - [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] - [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] - [string]$Vcenter, - - [Parameter(Mandatory = $false)] - $HvServer = $null - ) - - - begin { - $services = Get_ViewAPI_Service -hvServer $hvServer - if ($null -eq $services) { - Write-Error "Could not retrieve ViewApi services from connection object" - break - } - } - - process { - - $poolList = @{} - $poolType = @{} - $poolSource = @{} - if ($pool) { - foreach ($item in $pool) { - if ($item.GetType().name -eq 'DesktopInfo') { - $id = $item.id - $name = $item.base.name - $source = $item.source - $type = $item.type - } elseif ($item.GetType().name -eq 'DesktopSummaryView') { - $id = $item.id - $name = $item.desktopsummarydata.name - $source = $item.desktopsummarydata.source - $type = $item.desktopsummarydata.type - } elseif ($item.GetType().name -eq 'String') { - try { - $poolObj = Get-HVPool -poolName $item -hvServer $hvServer - } catch { - Write-Error "Make sure Get-HVPool advanced function is loaded, $_" - break - } - if ($poolObj) { - $id = $poolObj.id - $name = $poolObj.desktopsummarydata.name - $source = $poolObj.desktopsummarydata.source - $type = $poolObj.desktopsummarydata.type - } else { - Write-Error "No desktopsummarydata found with pool name: [$item]" - break - } - } else { - Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" - break - } - $poolList.Add($id,$name) - $poolType.Add($id,$type) - $poolSource.Add($id,$source) - } - } - } - - end { - foreach ($item in $poolList.Keys) { - $operation = $PsCmdlet.ParameterSetName - Write-Host "Performing $operation on" $poolList.$item - $desktop_helper = New-Object VMware.Hv.DesktopService - switch ($operation) { - 'REBALANCE' { - $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRebalanceSpec' -desktopId $item - if ($null -ne $spec) { - # make sure current task on VMs, must be None - $desktop_helper.Desktop_Rebalance($services,$item,$spec) - } - } - 'REFRESH' { - $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRefreshSpec' -desktopId $item - if ($null -ne $spec) { - # make sure current task on VMs, must be None - $desktop_helper.Desktop_Refresh($services,$item,$spec) - } - } - 'RECOMPOSE' { - $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRecomposeSpec' -desktopId $item - if ($null -ne $spec) { - $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter - $spec = Set_Spec_Vms -vcId $vcId -spec $spec - - # make sure current task on VMs, must be None - $desktop_helper.Desktop_Recompose($services,$item,$spec) - - # Update Base Image VM and Snapshot in Pool - $updates = @() - $updates += Get_MapEntry -key 'automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVm' -value $spec.ParentVM - $updates += Get_MapEntry -key 'automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshot' -value $spec.Snapshot - $desktop_helper.Desktop_Update($services,$item,$updates) - - } - } - 'PUSH_IMAGE' { - if ($poolSource.$item -ne 'INSTANT_CLONE_ENGINE') { - Write-Error "$poolList.$item is not a INSTANT CLONE pool" - break - } else { - $spec = New-Object VMware.Hv.DesktopPushImageSpec - $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter - $spec = Set_Spec_Vms -vcId $vcId -spec $spec - $spec.Settings = New-Object VMware.Hv.DesktopPushImageSettings - $spec.Settings.LogoffSetting = $logoffSetting - $spec.Settings.StopOnFirstError = $stopOnFirstError - if ($startTime) { $spec.Settings.startTime = $startTime } - $desktop_helper.Desktop_SchedulePushImage($services,$item,$spec) - } - } - 'CANCEL_PUSH_IMAGE' { - if ($poolSource.$item -ne 'INSTANT_CLONE_ENGINE') { - Write-Error "$poolList.$item is not a INSTANT CLONE pool" - break - } else { - $desktop_helper.Desktop_CancelScheduledPushImage($services,$item) - } - } - 'ENABLE' { - $map = New-Object VMware.Hv.MapEntry - $map.key = 'desktopSettings.enabled' - $map.value = $true - $desktop_helper.Desktop_Update($services,$item,$map) - } - 'DISABLE' { - $map = New-Object VMware.Hv.MapEntry - $map.key = 'desktopSettings.enabled' - $map.value = $false - $desktop_helper.Desktop_Update($services,$item,$map) - } - 'START' { - if ($poolType.$item -ne 'Automated') { - Write-Error "$poolList.$item is not a Automated pool" - break - } else { - $map = New-Object VMware.Hv.MapEntry - $map.key = 'automatedDesktopData.virtualCenterProvisioningSettings.enableProvisioning' - $map.value = $true - $desktop_helper.Desktop_Update($services,$item,$map) - } - } - 'STOP' { - if ($poolType.$item -ne 'Automated') { - Write-Error "$poolList.$item is not a Automated pool" - break - } else { - $map = New-Object VMware.Hv.MapEntry - $map.key = 'automatedDesktopData.virtualCenterProvisioningSettings.enableProvisioning' - $map.value = $false - $desktop_helper.Desktop_Update($services,$item,$map) - } - } - } - } - } -} - -function Get-Machines ($Pool,$MachineList) { - [VMware.Hv.MachineId[]]$machines = @() - $remainingCount = 1 # run through loop at least once - $query = New-Object VMware.Hv.QueryDefinition - $query.queryEntityType = 'MachineSummaryView' - $poolFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'MemberName' = 'base.desktop'; 'value' = $pool } - if ($machineList) { - $machineFilters = [vmware.hv.queryFilter[]]@() - foreach ($name in $machineList) { - $machineFilters += (New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $name }) - } - $machineList = New-Object VMware.Hv.QueryFilterOr -Property @{ 'filters' = $machineFilters } - $treeList = @() - $treeList += $machineList - $treelist += $poolFilter - $query.Filter = New-Object VMware.Hv.QueryFilterAnd -Property @{ 'filters' = $treeList } - } else { - $query.Filter = $poolFilter - } - while ($remainingCount -ge 1) { - $query_service_helper = New-Object VMware.Hv.QueryServiceService - $queryResults = $query_service_helper.QueryService_Query($services, $query) - $results = $queryResults.results - $machines += $results.id - $query.StartingOffset = $query.StartingOffset + $queryResults.results.Count - $remainingCount = $queryResults.RemainingCount - } - return $machines -} - -function Set_Spec_Vms { - param( - [Parameter(Mandatory = $true)] - [VMware.Hv.VirtualCenterId]$VcID, - - [Parameter(Mandatory = $true)] - $Spec - ) - if ($parentVM) { - $baseimage_helper = New-Object VMware.Hv.BaseImageVmService - $parentList = $baseimage_helper.BaseImageVm_List($services,$vcID) - $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } - $spec.ParentVm = $parentVMObj.id - } - if ($snapshotVM) { - $baseimage_snapshot_helper = New-Object VMware.Hv.BaseImageSnapshotService - $snapshotList = $baseimage_snapshot_helper.BaseImageSnapshot_List($services,$spec.ParentVm) - $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } - $spec.Snapshot = $snapshotVMObj.id - } - return $spec -} - -function Get_TaskSpec { - param( - [Parameter(Mandatory = $true)] - [string]$Source, - - [Parameter(Mandatory = $true)] - [string]$PoolName, - - [Parameter(Mandatory = $true)] - [string]$Operation, - - [Parameter(Mandatory = $true)] - [string]$TaskSpecName, - - [Parameter(Mandatory = $true)] - $DesktopId - - ) - if ($source -ne 'VIEW_COMPOSER') { - Write-Error "$operation task is not supported for pool type: [$source]" - return $null - } - $machineList = Get-Machines $desktopId $machines - if ($machineList.Length -eq 0) { - Write-Error "Failed to get any Virtual Center machines with the given pool name: [$poolName]" - return $null - } - $spec = Get_New_Object -TypeName $taskSpecName - $spec.LogoffSetting = $logoffSetting - $spec.StopOnFirstError = $stopOnFirstError - $spec.Machines = $machineList - if ($startTime) { $spec.startTime = $startTime } - return $spec -} - -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVEvent,Get-HVFarm,Get-HVPool,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool From df5e47ac67e16a6c78d4093a508e0ed16afbf80e Mon Sep 17 00:00:00 2001 From: praveenmathamsetty Date: Thu, 17 Nov 2016 17:47:19 +0530 Subject: [PATCH 15/20] Horizon API PowerShell Advanced Functions for Horizon Connection Server VSM@CLN 4610015 --- .../New-HVFarm/AutomatedLinkedCloneFarm.json | 80 + .../New-HVFarm/ManualFarm.json | 24 + .../New-HVPool/FullClone.json | 82 + .../New-HVPool/InstantClone.json | 105 + .../New-HVPool/LinkedClone.json | 105 + .../New-HVPool/ManualSpec.json | 35 + .../VMware.Hv.Helper/New-HVPool/RdsSpec.json | 16 + .../Set-HVFarm/AutomatedEditFarm.json | 6 + .../Set-HVFarm/ManualEditFarm.json | 5 + .../Set-HVPool/AutomatedEditPool.Json | 8 + .../Set-HVPool/ManualEditPool.json | 8 + .../Set-HVPool/RdsEditPool.json | 6 + .../VMware.Hv.Helper/VMware.HV.Helper.psd1 | 95 + .../VMware.Hv.Helper/VMware.HV.Helper.psm1 | 4743 +++++++++++++++++ 14 files changed, 5318 insertions(+) create mode 100644 Modules/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json create mode 100644 Modules/VMware.Hv.Helper/New-HVFarm/ManualFarm.json create mode 100644 Modules/VMware.Hv.Helper/New-HVPool/FullClone.json create mode 100644 Modules/VMware.Hv.Helper/New-HVPool/InstantClone.json create mode 100644 Modules/VMware.Hv.Helper/New-HVPool/LinkedClone.json create mode 100644 Modules/VMware.Hv.Helper/New-HVPool/ManualSpec.json create mode 100644 Modules/VMware.Hv.Helper/New-HVPool/RdsSpec.json create mode 100644 Modules/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json create mode 100644 Modules/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json create mode 100644 Modules/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json create mode 100644 Modules/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json create mode 100644 Modules/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json create mode 100644 Modules/VMware.Hv.Helper/VMware.HV.Helper.psd1 create mode 100644 Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 diff --git a/Modules/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json b/Modules/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json new file mode 100644 index 0000000..3706374 --- /dev/null +++ b/Modules/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json @@ -0,0 +1,80 @@ +{ + "Type": "AUTOMATED", + "Data": { + "Name": "LCFarmTest", + "DisplayName": "Ankit LC Farm Test", + "AccessGroup": "Root", + "Description": "created LC Farm from PS", + "Enabled": null, + "Deleting": false, + "Settings": null, + "Desktop": null, + "DisplayProtocolSettings": null, + "ServerErrorThreshold": null, + "MirageConfigurationOverrides": null + }, + "AutomatedFarmSpec": { + "ProvisioningType": "VIEW_COMPOSER", + "VirtualCenter": null, + "RdsServerNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "LCFarmVM_PS", + "MaxNumberOfRDSServers": 1 + } + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "ParentVm": "Win_Server_2012_R2", + "Snapshot": "Snap_RDS", + "Datacenter": null, + "VmFolder": "AnkitPoolVM", + "HostOrCluster": "cls", + "ResourcePool": "cls" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "datastore1 (5)", + "StorageOvercommit": "UNBOUNDED" + } + ], + "UseVSan": false, + "ViewComposerStorageSettings": { + "UseSeparateDatastoresReplicaAndOSDisks": false, + "ReplicaDiskDatastore": null, + "UseNativeSnapshots": false, + "SpaceReclamationSettings": { + "ReclaimVmDiskSpace": false, + "ReclamationThresholdGB": null, + "BlackoutTimes": null + } + } + }, + "VirtualCenterNetworkingSettings": { + "Nics": null + } + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + }, + "CustomizationSettings": { + "CustomizationType": "SYS_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "SysprepCustomizationSettings": { + "CustomizationSpec": "RDSH_Cust2" + } + }, + "RdsServerMaxSessionsData": { + "MaxSessionsType": "UNLIMITED", + "MaxSessions": null + } + }, + "ManualFarmSpec": null, + "NetBiosName" : "adankit" +} diff --git a/Modules/VMware.Hv.Helper/New-HVFarm/ManualFarm.json b/Modules/VMware.Hv.Helper/New-HVFarm/ManualFarm.json new file mode 100644 index 0000000..cf674c1 --- /dev/null +++ b/Modules/VMware.Hv.Helper/New-HVFarm/ManualFarm.json @@ -0,0 +1,24 @@ +{ + "Type": "MANUAL", + "Data": { + "Name": "manualFarmTest", + "DisplayName": "manualFarmTest", + "AccessGroup": "Root", + "Description": "Manual PS Test", + "Enabled": null, + "Deleting": false, + "Settings": null, + "Desktop": null, + "DisplayProtocolSettings": null, + "ServerErrorThreshold": null, + "MirageConfigurationOverrides": null + }, + "AutomatedFarmSpec": null, + "ManualFarmSpec": { + "RdsServers": [ + { + "rdsServer": "WIN-ORKA1Q8B0P7" + } + ] + } +} diff --git a/Modules/VMware.Hv.Helper/New-HVPool/FullClone.json b/Modules/VMware.Hv.Helper/New-HVPool/FullClone.json new file mode 100644 index 0000000..2ae9539 --- /dev/null +++ b/Modules/VMware.Hv.Helper/New-HVPool/FullClone.json @@ -0,0 +1,82 @@ +{ + "Base": { + "Name" : "FulClnJSON", + "DisplayName": "FullClonePraJSON", + "AccessGroup": "Root", + "Description": "create full clone via JSON" + }, + "DesktopSettings": null, + "Type": "AUTOMATED", + "AutomatedDesktopSpec": { + "ProvisioningType": "VIRTUAL_CENTER", + "VirtualCenter": null, + "UserAssignment": { + "UserAssignment": "DEDICATED", + "AutomaticAssignment": true + }, + "VmNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "FullClnJson1", + "MaxNumberOfMachines": 1, + "NumberOfSpareMachines": 1, + "ProvisioningTime": "UP_FRONT", + "MinNumberOfMachines": null + }, + "SpecificNamingSpec": null + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "Template": "powerCLI-VM-TEMPLATE", + "ParentVm": null, + "Snapshot": null, + "Datacenter": null, + "VmFolder": "Praveen", + "HostOrCluster": "CS-1", + "ResourcePool": "CS-1" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "datastore1", + "StorageOvercommit": "UNBOUNDED" + } + ], + "UseVSan": false, + "ViewComposerStorageSettings": null, + "ViewStorageAcceleratorSettings": { + "UseViewStorageAccelerator": false, + "ViewComposerDiskTypes": null, + "RegenerateViewStorageAcceleratorDays": null, + "BlackoutTimes": null + } + }, + "VirtualCenterNetworkingSettings": { + "Nics": null + } + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + }, + "CustomizationSettings": { + "CustomizationType": "SYS_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "NoCustomizationSettings": { + "DoNotPowerOnVMsAfterCreation": false + }, + "SysprepCustomizationSettings": null, + "QuickprepCustomizationSettings": null, + "CloneprepCustomizationSettings": null + } + }, + "ManualDesktopSpec": null, + "RdsDesktopSpec": null, + "GlobalEntitlementData": null, + "NetBiosName" : "adviewdev", + "SysPrepName" : "praveencust" +} diff --git a/Modules/VMware.Hv.Helper/New-HVPool/InstantClone.json b/Modules/VMware.Hv.Helper/New-HVPool/InstantClone.json new file mode 100644 index 0000000..a8da482 --- /dev/null +++ b/Modules/VMware.Hv.Helper/New-HVPool/InstantClone.json @@ -0,0 +1,105 @@ +{ + "Base": { + "Name" : "InsClnJSON", + "DisplayName": "insPoolPr", + "AccessGroup": "ROOT", + "Description": "create instant pool" + }, + "DesktopSettings": null, + "Type": "AUTOMATED", + "AutomatedDesktopSpec": { + "ProvisioningType": "INSTANT_CLONE_ENGINE", + "VirtualCenter": null, + "UserAssignment": { + "UserAssignment": "FLOATING", + "AutomaticAssignment": true + }, + "VmNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "inspoolJson1", + "MaxNumberOfMachines": 1, + "NumberOfSpareMachines": 1, + "ProvisioningTime": "UP_FRONT", + "MinNumberOfMachines": null + }, + "SpecificNamingSpec": null + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "Template": null, + "ParentVm": "Agent_pra", + "Snapshot": "kb-hotfix", + "Datacenter": null, + "VmFolder": "Praveen", + "HostOrCluster": "CS-1", + "ResourcePool": "CS-1" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "datastore1", + "StorageOvercommit": "UNBOUNDED" + } + ], + "UseVSan": false, + "ViewComposerStorageSettings": { + "UseSeparateDatastoresReplicaAndOSDisks": false, + "ReplicaDiskDatastore": null, + "UseNativeSnapshots": false, + "SpaceReclamationSettings": { + "ReclaimVmDiskSpace": false, + "ReclamationThresholdGB": null + }, + "PersistentDiskSettings": { + "RedirectWindowsProfile": false, + "UseSeparateDatastoresPersistentAndOSDisks": null, + "PersistentDiskDatastores": null, + "DiskSizeMB": null, + "DiskDriveLetter": null + }, + "NonPersistentDiskSettings": { + "RedirectDisposableFiles": false, + "DiskSizeMB": null, + "DiskDriveLetter": null + } + }, + "ViewStorageAcceleratorSettings": { + "UseViewStorageAccelerator": false, + "ViewComposerDiskTypes": null, + "RegenerateViewStorageAcceleratorDays": null, + "BlackoutTimes": null + } + }, + "VirtualCenterNetworkingSettings": { + "Nics": null + } + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + }, + "CustomizationSettings": { + "CustomizationType": "CLONE_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "NoCustomizationSettings": null, + "SysprepCustomizationSettings": null, + "QuickprepCustomizationSettings": null, + "CloneprepCustomizationSettings": { + "InstantCloneEngineDomainAdministrator": null, + "PowerOffScriptName": null, + "PowerOffScriptParameters": null, + "PostSynchronizationScriptName": null, + "PostSynchronizationScriptParameters": null + } + } + }, + "ManualDesktopSpec": null, + "RdsDesktopSpec": null, + "GlobalEntitlementData": null, + "NetBiosName" : "adviewdev" +} diff --git a/Modules/VMware.Hv.Helper/New-HVPool/LinkedClone.json b/Modules/VMware.Hv.Helper/New-HVPool/LinkedClone.json new file mode 100644 index 0000000..53171a6 --- /dev/null +++ b/Modules/VMware.Hv.Helper/New-HVPool/LinkedClone.json @@ -0,0 +1,105 @@ +{ + "Base": { + "Name" : "LnkClnJSon", + "DisplayName": "praveen linkedclone pool", + "AccessGroup": "Root", + "Description": "created linkedclone pool from ps" + }, + "DesktopSettings": null, + "Type": "AUTOMATED", + "AutomatedDesktopSpec": { + "ProvisioningType": "VIEW_COMPOSER", + "VirtualCenter": null, + "UserAssignment": { + "UserAssignment": "FLOATING", + "AutomaticAssignment": true + }, + "VmNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "patternPra1", + "MaxNumberOfMachines": 1, + "NumberOfSpareMachines": 1, + "ProvisioningTime": "UP_FRONT", + "MinNumberOfMachines": null + }, + "SpecificNamingSpec": null + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "Template": null, + "ParentVm": "Agent_pra", + "Snapshot": "kb-hotfix", + "Datacenter": null, + "VmFolder": "Praveen", + "HostOrCluster": "CS-1", + "ResourcePool": "CS-1" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "datastore1", + "StorageOvercommit": "UNBOUNDED" + } + ], + "UseVSan": false, + "ViewComposerStorageSettings": { + "UseSeparateDatastoresReplicaAndOSDisks": false, + "ReplicaDiskDatastore": null, + "UseNativeSnapshots": false, + "SpaceReclamationSettings": { + "ReclaimVmDiskSpace": false, + "ReclamationThresholdGB": null + }, + "PersistentDiskSettings": { + "RedirectWindowsProfile": false, + "UseSeparateDatastoresPersistentAndOSDisks": null, + "PersistentDiskDatastores": null, + "DiskSizeMB": null, + "DiskDriveLetter": null + }, + "NonPersistentDiskSettings": { + "RedirectDisposableFiles": false, + "DiskSizeMB": null, + "DiskDriveLetter": null + } + }, + "ViewStorageAcceleratorSettings": { + "UseViewStorageAccelerator": false, + "ViewComposerDiskTypes": null, + "RegenerateViewStorageAcceleratorDays": null, + "BlackoutTimes": null + } + }, + "VirtualCenterNetworkingSettings": { + "Nics": null + } + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + }, + "CustomizationSettings": { + "CustomizationType": "QUICK_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "NoCustomizationSettings": null, + "SysprepCustomizationSettings": null, + "QuickprepCustomizationSettings": { + "PowerOffScriptName": null, + "PowerOffScriptParameters": null, + "PostSynchronizationScriptName": null, + "PostSynchronizationScriptParameters": null + }, + "CloneprepCustomizationSettings": null + } + }, + "ManualDesktopSpec": null, + "RdsDesktopSpec": null, + "GlobalEntitlementData": null, + "NetBiosName" : "adviewdev", + "SysPrepName" : "praveencust" +} diff --git a/Modules/VMware.Hv.Helper/New-HVPool/ManualSpec.json b/Modules/VMware.Hv.Helper/New-HVPool/ManualSpec.json new file mode 100644 index 0000000..b302bba --- /dev/null +++ b/Modules/VMware.Hv.Helper/New-HVPool/ManualSpec.json @@ -0,0 +1,35 @@ +{ + "Base": { + "Name" : "MnlJson", + "DisplayName": "MNLPUL", + "AccessGroup": "ROOT", + "Description": "Manual pool creation" + }, + "DesktopSettings": null, + "Type": "MANUAL", + "AutomatedDesktopSpec": null, + "ManualDesktopSpec": { + "UserAssignment": { + "UserAssignment": "FLOATING", + "AutomaticAssignment": true + }, + "Source": "VIRTUAL_CENTER", + "Machines": [ + { + "Machine" : "PowerCLI-VM" + } + ], + "VirtualCenter": null, + "ViewStorageAcceleratorSettings": { + "UseViewStorageAccelerator": false, + "ViewComposerDiskTypes": null, + "RegenerateViewStorageAcceleratorDays": null, + "BlackoutTimes": null + }, + "VirtualCenterManagedCommonSettings": { + "TransparentPageSharingScope": "VM" + } + }, + "RdsDesktopSpec": null, + "GlobalEntitlementData": null +} diff --git a/Modules/VMware.Hv.Helper/New-HVPool/RdsSpec.json b/Modules/VMware.Hv.Helper/New-HVPool/RdsSpec.json new file mode 100644 index 0000000..86b3571 --- /dev/null +++ b/Modules/VMware.Hv.Helper/New-HVPool/RdsSpec.json @@ -0,0 +1,16 @@ +{ + "Base": { + "Name" : "RdsJson", + "DisplayName": "TestRDSPS", + "AccessGroup": "Root", + "Description": "Testing PS" + }, + "DesktopSettings": null, + "Type": "RDS", + "AutomatedDesktopSpec": null, + "ManualDesktopSpec": null, + "RdsDesktopSpec": { + "Farm": "Farm2" + }, + "GlobalEntitlementData": null +} diff --git a/Modules/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json b/Modules/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json new file mode 100644 index 0000000..cad9343 --- /dev/null +++ b/Modules/VMware.Hv.Helper/Set-HVFarm/AutomatedEditFarm.json @@ -0,0 +1,6 @@ +{ + "data.description" : "update through edit farm function", + "data.displayName" : "LCFarmTestUpdated1", + "data.displayProtocolSettings.defaultDisplayProtocol" : "PCOIP", + "automatedFarmData.virtualCenterManagedCommonSettings.transparentPageSharingScope" : "FARM" +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json b/Modules/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json new file mode 100644 index 0000000..533c39f --- /dev/null +++ b/Modules/VMware.Hv.Helper/Set-HVFarm/ManualEditFarm.json @@ -0,0 +1,5 @@ +{ + "data.description" : "update through edit farm function", + "data.displayName" : "ManualFarmTestUpdated1", + "data.displayProtocolSettings.defaultDisplayProtocol" : "PCOIP" +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json b/Modules/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json new file mode 100644 index 0000000..9654b14 --- /dev/null +++ b/Modules/VMware.Hv.Helper/Set-HVPool/AutomatedEditPool.Json @@ -0,0 +1,8 @@ +{ + "base.description" : "update through edit pool function", + "base.displayName" : "Henry2DspNm", + "desktopSettings.displayProtocolSettings.defaultDisplayProtocol" : "BLAST", + "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.useViewStorageAccelerator" : true, + "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.viewComposerDiskTypes" : "OS_DISKS", + "automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.regenerateViewStorageAcceleratorDays" : 8 +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json b/Modules/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json new file mode 100644 index 0000000..6fc8adc --- /dev/null +++ b/Modules/VMware.Hv.Helper/Set-HVPool/ManualEditPool.json @@ -0,0 +1,8 @@ +{ + "base.description" : "update through edit pool", + "base.displayName" : "pooldisp", + "desktopSettings.displayProtocolSettings.defaultDisplayProtocol" : "BLAST", + "manualDesktopData.viewStorageAcceleratorSettings.useViewStorageAccelerator" : true, + "manualDesktopData.viewStorageAcceleratorSettings.viewComposerDiskTypes" : "OS_DISKS", + "manualDesktopData.viewStorageAcceleratorSettings.regenerateViewStorageAcceleratorDays" : 8 +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json b/Modules/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json new file mode 100644 index 0000000..58bf859 --- /dev/null +++ b/Modules/VMware.Hv.Helper/Set-HVPool/RdsEditPool.json @@ -0,0 +1,6 @@ +{ + "base.description" : "update through edit pool function", + "base.displayName" : "RDS2DspNm", + "desktopSettings.flashSettings.quality" : "LOW", + "desktopSettings.flashSettings.throttling" : "CONSERVATIVE" +} \ No newline at end of file diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psd1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psd1 new file mode 100644 index 0000000..7d9e262 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psd1 @@ -0,0 +1,95 @@ +# +# Module manifest for module 'VMware.HV' +# +# Generated by: "VMware" +# +# Generated on: 9/20/2016 +# + +@{ + +# Script module or binary module file associated with this manifest. +# RootModule = '' + +# Version number of this module. +ModuleVersion = '1.0' + +# ID used to uniquely identify this module +GUID = '6d3f7fb5-4e52-43d8-91e1-f65f72532a1d' + +# Author of this module +Author = 'VMware' + +# Company or vendor of this module +CompanyName = 'VMware, Inc.' + +# Copyright statement for this module +Copyright = 'Copyright (c) 2016 VMware, Inc. All rights reserved.' + +# Description of the functionality provided by this module +# Description = 'This Windows PowerShell script module contains Advanced functions of VIEW API Service.' + +# Minimum version of the Windows PowerShell engine required by this module +# PowerShellVersion = '' + +# 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 the .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 = @('VMware.VimAutomation.HorizonView') + +# 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 = @('VMware.HV.Helper.psm1') + +# 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 = '*' + +# 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 +# PrivateData = '' + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 new file mode 100644 index 0000000..3d533f5 --- /dev/null +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -0,0 +1,4743 @@ +#Script Module : VMware.Hv.Helper +#Version : 1.0 + +#Copyright 2016 VMware, Inc. All Rights Reserved. + +#Permission is hereby granted, free of charge, to any person obtaining a copy of +#this software and associated documentation files (the "Software"), to deal in +#the Software without restriction, including without limitation the rights to +#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +#of the Software, and to permit persons to whom the Software is furnished to do +#so, subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in all +#copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +#SOFTWARE. + + +function Get_New_Object { + param( + [Parameter(Mandatory = $true)] + [string]$TypeName, + + [Parameter(Mandatory = $false)] + [System.Collections.Hashtable]$PropertyName + ) + $objStr = 'VMware.Hv.' + $typeName + return New-Object $objStr -Property $propertyName +} + +function Get_ViewAPI_Service { + param( + [Parameter(Mandatory = $false)] + $HvServer + ) + if ($null -ne $hvServer) { + if ($hvServer.GetType().name -ne 'ViewServerImpl') { + $type = $hvServer.GetType().name + Write-Error "Expected hvServer type is ViewServerImpl, but received: [$type]" + return $null + } + elseif ($hvServer.IsConnected) { + return $hvServer.ExtensionData + } + } elseif ($global:DefaultHVServers.Length -gt 0) { + if ($pscmdlet.ShouldProcess($global:DefaultHVServers[0].uid,'hvServer not specified, use default hvServer connection?')) { + $hvServer = $global:DefaultHVServers[0] + return $hvServer.ExtensionData + } + } + return $null +} + +function Get_Vcenter_ID { + param( + [Parameter(Mandatory = $true)] + $Services, + + [Parameter(Mandatory = $false)] + [string] + $Vcenter + ) + $vc_service_helper = New-Object VMware.Hv.VirtualCenterService + $vcList = $vc_service_helper.VirtualCenter_List($services) + if ($vCenter) { + #ServerSpec.ServerName is IP/FQDN of the vCenter server. Input vCenter will be IP/FQDN of the vcenter server + $virtualCenterId = ($vcList | Where-Object { $_.ServerSpec.ServerName -eq $vCenter }).id + if ($virtualCenterId.Count -ne 1) { + Write-Error "vCenter Server not found: [$vCenter], please make sure vCenter is added in Connection Server" + return $null + } + } + else { + if ($vcList.Count -ne 1) { + Write-Error "Multiple Vcenter servers found, please specify the vCenter Name" + return $null + } + else { $virtualCenterId = $vcList.id } + } + return $virtualCenterId +} + +function Get_Json_Object { + param( + [Parameter(Mandatory = $true)] + [string]$SpecFile + ) + try { + return Get-Content -Raw $specFile | ConvertFrom-Json + } catch { + throw "Failed to read json file [$specFile], $_" + } +} + +function Get_MapEntry { + param( + [Parameter(Mandatory = $true)] + $Key, + + [Parameter(Mandatory = $true)] + $Value + ) + + $update = New-Object VMware.Hv.MapEntry + $update.key = $key + $update.value = $value + return $update +} + +function Get-RegisteredPhysicalMachines ($Services,$MachinesList) { + [VMware.Hv.MachineId[]]$machines = $null + $query_service_helper = New-Object VMware.Hv.QueryServiceService + foreach ($machineName in $machinesList) { + $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals + $QueryFilterEquals.memberName = 'machineBase.name' + $QueryFilterEquals.value = $machineName + + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'RegisteredPhysicalMachineInfo' + $defn.Filter = $QueryFilterEquals + + $queryResults = $query_service_helper.QueryService_Query($services,$defn) + $res = $queryResults.results + $machines += $res.id + } + return $machines +} + +function Get-RegisteredRDSServers ($Services,$ServerList) { + [VMware.Hv.RDSServerId[]]$servers = $null + $query_service_helper = New-Object VMware.Hv.QueryServiceService + foreach ($serverName in $serverList) { + $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals + $QueryFilterEquals.memberName = 'base.name' + $QueryFilterEquals.value = $serverName + + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'RDSServerInfo' + $defn.Filter = $QueryFilterEquals + + $queryResults = $query_service_helper.QueryService_Query($services,$defn) + + $servers += $queryResults.results.id + } + if ($null -eq $servers) { + throw "No Registered RDS server found with name: [$serverList]" + } + return $servers +} +function Add-HVDesktop { +<# +.SYNOPSIS +Adds virtual machine to existing pool + +.DESCRIPTION +The Add-HVDesktop adds virtual machines to already exiting pools by using view API service object(hvServer) of Connect-HVServer cmdlet. VMs can be added to any of unmanaged manual, managed manual or Specified name. This advanced function do basic checks for pool and view API service connection existance, hvServer object is bound to specific connection server. + +.PARAMETER PoolName + Pool name to which new VMs are to be added. + +.PARAMETER Machines + List of virtual machine names which need to be added to the given pool. + +.PARAMETER Users + List of virtual machine users for given machines. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) of the given pool. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.EXAMPLE + Add managed manual VMs to existing manual pool + Add-HVDesktop -PoolName 'ManualPool' -Machines 'manualPool1', 'manualPool2'. + +.EXAMPLE + Add virtual machines to automated specific named dedicated pool + Add-HVDesktop -PoolName 'SpecificNamed' -Machines 'vm-01', 'vm-02' -Users 'user1', 'user2' + +.EXAMPLE + Add machines to automated specific named Floating pool + Add-HVDesktop -PoolName 'SpecificNamed' -Machines 'vm-03', 'vm-04' + +.EXAMPLE + Add machines to unmanged manual pool + Add-HVDesktop -PoolName 'Unmanaged' -Machines 'desktop-1.eng.vmware.com' + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.0 + Dependencies : Make sure pool already exists before adding VMs to it. + + ===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 = $true)] + [string] + $PoolName, + + [Parameter(Mandatory = $true)] + [string[]] + $Machines, + + [Parameter(Mandatory = $false)] + [string[]] + $Users, + + [Parameter(Mandatory = $false)] + [string] + $Vcenter, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + try { + $desktopPool = Get-HVPool -poolName $poolName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($desktopPool) { + $id = $desktopPool.id + $type = $desktopPool.desktopsummarydata.type + $source = $desktopPool.desktopsummarydata.source + $userAssignment = $desktopPool.desktopsummarydata.userAssignment + } else { + Write-Error "Unable to retrieve DesktopSummaryView with given poolName: [$poolName]" + break + } + + $desktop_service_helper = New-Object VMware.Hv.DesktopService + $user_assignement_helper = $desktop_service_helper.getDesktopUserAssignmentHelper() + switch ($type) { + 'AUTOMATED' { + if (($userAssignment -eq $user_assignement_helper.USER_ASSIGNMENT_DEDICATED) -and ($machines.Length -ne $users.Length)) { + Write-Error "Parameters machines length: [$machines.Length] and users length: [$users.Length] should be of same size" + return + } + [VMware.Hv.DesktopSpecifiedName[]]$desktopSpecifiedNameArray = @() + $cnt = 0 + foreach ($machine in $machines) { + $specifiedNames = New-Object VMware.Hv.DesktopSpecifiedName + $specifiedNames.vmName = $machine + if ($userAssignment -eq $user_assignement_helper.USER_ASSIGNMENT_DEDICATED -and $users) { + try { + $specifiedNames.user = Get_UserId -user $users[$cnt] + } catch { + Write-Error "Unable to retrieve UserOrGroupId for user: [$users[$cnt]], $_" + return + } + } + $desktopSpecifiedNameArray += $specifiedNames + $cnt += 1 + } + $desktop_service_helper.Desktop_AddMachinesToSpecifiedNamingDesktop($services,$id,$desktopSpecifiedNameArray) + } + 'MANUAL' { + if ($source -eq 'UNMANAGED') { + $machineList = Get-RegisteredPhysicalMachines -services $services -machinesList $machines + if ($machineList.Length -eq 0) { + Write-Error "Failed to retrieve registerd physical machines with the given machines parameter" + return + } + } else { + $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter + $machineList = Get-MachinesByVCenter -machineList $machines -vcId $vcId + if ($machineList.Length -eq 0) { + Write-Error "Failed to get any Virtual Center machines with the given machines parameter" + return + } + } + $desktop_service_helper.Desktop_AddMachinesToManualDesktop($services,$id,$machineList) + } + default { + Write-Error "Only Automated/Manual pool types support this add operation" + break + } + } + } + + end { + [System.gc]::collect() + } +} + +function Get_UserId ($User) { + + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'ADUserOrGroupSummaryView' + [VMware.Hv.QueryFilter[]]$filters = $null + $groupfilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.group'; 'value' = $false } + $userNameFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $user } + $treeList = @() + $treeList += $userNameFilter + $treelist += $groupfilter + $filterAnd = New-Object VMware.Hv.QueryFilterAnd + $filterAnd.Filters = $treelist + $defn.Filter = $filterAnd + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $res = $query_service_helper.QueryService_Query($services,$defn) + if ($null -eq $res.results) { + throw "Query service did not return any users with given user name: [$user]" + } + return $res.results.id +} + +function Get-MachinesByVCenter ($MachineList,$VcId) { + + [VMware.Hv.MachineId[]]$machines = $null + $virtualMachine_helper = New-Object VMware.Hv.VirtualMachineService + $vcMachines = $virtualMachine_helper.VirtualMachine_List($services,$vcId) + $machineDict = @{} + foreach ($vMachine in $vcMachines) { + $machineDict.Add($vMachine.name,$vMachine.id) + } + foreach ($machineName in $machineList) { + if ($machineDict.Contains($machineName)) { + $machines += $machineDict.$machineName + } + } + return $machines +} +function Add-HVRDSServer { +<# +.SYNOPSIS + Add RDS Servers to an existing farm. + +.DESCRIPTION + The Add-HVRDSServer adds RDS Servers to already exiting farms by using view API service object(hvServer) of Connect-HVServer cmdlet. We can add RDSServers to manual farm type only. This advanced function do basic checks for farm and view API service connection existance. This hvServer is bound to specific connection server. + +.PARAMETER FarmName + farm name to which new RDSServers are to be added. + +.PARAMETER RdsServers + RDS servers names which need to be added to the given farm. Provide a comma separated list for multiple names. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.EXAMPLE + Add RDSServers to manual farm + Add-HVRDSServer -Farm "manualFarmTest" -RdsServers "vm-for-rds","vm-for-rds-2" + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@vmware.com + Version : 1.0 + Dependencies : Make sure farm already exists before adding RDSServers to it. + + ===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 = $true,ValueFromPipeline = $true)] + $FarmName, + + [Parameter(Mandatory = $true)] + [string[]] + $RdsServers, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + try { + $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($farmSpecObj) { + $id = $farmSpecObj.id + $type = $farmSpecObj.data.type + + } else { + Write-Error "Unable to retrieve FarmSummaryView with given farmName: [$farmName]" + break + } + $farm_service_helper = New-Object VMware.Hv.FarmService + switch ($type) { + 'AUTOMATED' { + Write-Error "Only Manual farm types supported for this add operation" + break + } + 'MANUAL' { + try { + $serverList = Get-RegisteredRDSServers -services $services -serverList $rdsServers + $farm_service_helper.Farm_AddRDSServers($services, $id, $serverList) + } catch { + Write-Error "Failed to Add RDS Server to Farm with error: $_" + break + } + } + } + } + + end { + [System.gc]::collect() + } +} +[System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient") | Out-Null + +function Connect-HVEvent { +<# +.SYNOPSIS + This function is used to connect to the event database configured on Connection Server. + +.DESCRIPTION + This function queries the specified Connection Server for event database configuration and returns the connection object to it. If event database is not configured on specified connection server, it will return null. + Currently, Horizon 7 is supporting SQL server and Oracle 12c as event database servers. To configure event database, goto 'Event Database Configuration' tab in Horizon admin UI. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER DbUserName + User name to be used in database connection. If not passed, default database user name on the Connection Server will be used. + +.PARAMETER DbPassword + Password corresponds to 'dbUserName' user. + +.EXAMPLE + Connecting to the database with default username configured on Connection Server $hvServer. + Connect-HVEvent -HvServer $hvServer + +.EXAMPLE + Connecting to the database configured on Connection Server $hvServer with customised user name 'system'. + $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' + +.EXAMPLE + Connecting to the database with customised user name and password. + $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' -DbPassword 'censored' + +.EXAMPLE + Connecting to the database with customised user name and password, with password being a SecureString. + $password = Read-Host 'Database Password' -AsSecureString + $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' -DbPassword $password + +.OUTPUTS + Returns a custom object that has database connection as 'dbConnection' property. + +.NOTES + Author : Paramesh Oddepally. + Author email : poddepally@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()] + param( + [Parameter(Mandatory = $false)] + $DbPassword = $null, + + [Parameter(Mandatory = $false)] + $HvServer = $null, + + [Parameter(Mandatory = $false)] + [string]$DbUserName = $null + ) + + begin { + # Connect to Connection Server and call the View API service + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + $EventDatabaseHelper = New-Object VMware.Hv.EventDatabaseService + $EventDatabaseInfo = $EventDatabaseHelper.EventDatabase_Get($services) + + # Check whether event database is configured on the connection server + # If not, return empty + if (!$EventDatabaseInfo.EventDatabaseSet) { + Write-Error "Event Database is not configured on Connection Server. To configure Event DB, go to 'Events Configuration' Tab in Horizon Admin UI" + break + } + + $dbServer = $EventDatabaseInfo.Database.server + $dbType = $EventDatabaseInfo.Database.type + $dbPort = $EventDatabaseInfo.Database.port + $dbName = $EventDatabaseInfo.Database.name + if (!$dbUserName) { $dbUserName = $EventDatabaseInfo.Database.userName } + $dbTablePrefix = $EventDatabaseInfo.Database.tablePrefix + + if (!$dbPassword) { $dbPassword = Read-Host 'Database Password for' $dbUserName@$dbServer -AsSecureString } + + if ($dbType -eq "SQLSERVER") { + if ($dbPassword.GetType().name -eq 'String'){ + $password = ConvertTo-SecureString $dbPassword -AsPlainText -Force + } elseif ($dbPassword.GetType().name -eq 'SecureString') { + $password = $dbPassword + } else { + Write-Error "Unsupported type recieved for dbPassword: [$dbPassword]. dbpassword should either be String or SecureString type. " + break + } + $connectionString = "Data Source=$dbServer, $dbPort; Initial Catalog=$dbName;" + $connection = New-Object System.Data.SqlClient.SqlConnection ($connectionString) + $password.MakeReadOnly() + $connection.Credential = New-Object System.Data.SqlClient.SqlCredential($dbUserName, $password); + } elseif ($dbType -eq "ORACLE") { + if ($dbPassword.GetType().name -eq 'SecureString'){ + $password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($dbPassword)) + } elseif ($dbPassword.GetType().name -eq 'String') { + $password = $dbPassword + } else { + Write-Error "Unsupported type recieved for dbPassword: [$dbPassword]. dbpassword should either be String or SecureString type. " + break + } + $dataSource = "(DESCRIPTION = " + + "(ADDRESS = (PROTOCOL = TCP)(HOST = $dbServer)(PORT = $dbPort))" + + "(CONNECT_DATA =" + + "(SERVICE_NAME = $dbName))" + + ");" + $connectionString = "Data Source=$dataSource;User Id=$dbUserName;Password=$password;" + $connection = New-Object System.Data.OracleClient.OracleConnection ($connectionString) + } else { + Write-Error "Unsupported DB type received: [$dbType]" + break + } + } + + process { + try { + $connection.Open() + } catch { + Write-Error "Failed to connect to database server: [$dbServer], $_" + break + } + Write-Host "Successfully connected to $dbType database: [$dbServer]" + return New-Object pscustomobject -Property @{ dbConnection = $connection; dbTablePrefix = $dbTablePrefix; } + } + + end { + [System.gc]::collect() + } +} + +function Disconnect-HVEvent { +<# +.SYNOPSIS + This function is used to disconnect the database connection. + +.DESCRIPTION + This function will disconnect the database connection made earlier during Connect-HVEvent function. + +.PARAMETER HvDbServer + Connection object returned by Connect-HVEvent advanced function. This is a mandatory input. + +.EXAMPLE + Disconnecting the database connection on $hvDbServer. + Disconnect-HVEvent -HvDbServer $hvDbServer + +.OUTPUTS + None + +.NOTES + Author : Paramesh Oddepally. + Author email : poddepally@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()] + param( + [Parameter(Mandatory = $true)] + [pscustomobject]$HvDbServer + ) + + begin { + $dbConnection = $hvDbServer.dbConnection + + # Validate the hvDbServer type. If not of expected type, dbConnection will be null. + if ($null -eq $dbConnection) { + Write-Error "No valid connection object found on hvDbServer parameter: [$hvDbServer]" + break + } + + # validate the user connection type of dbConnection + if (!$dbConnection.GetType().name.Equals("SqlConnection") -and !$dbConnection.GetType().name.Equals("OracleConnection")) { + Write-Error "The dbConnection object in hvDbServer parameter is not an SQL/Oracle DB connection: [$hvDbServer.GetType().Name]" + break + } + } + + process { + $dbConnection.Close() + Write-Host "Successfully closed the database connection" + } + + end { + [System.gc]::collect() + } +} + +function Get-HVEvent { +<# +.SYNOPSIS + Queries the events from event database configured on Connection Server. + +.DESCRIPTION + This function is used to query the events information from event database. It returns the object that has events in five columns as UserName, Severity, EventTime, Module and Message. EventTime will show the exact time when the event got registered in the database and it follows timezone on database server. + User can apply different filters on the event columns using the filter parameters userFilter, severityFilter, timeFilter, moduleFilter, messageFilter. Mention that when multiple filters are provided then rows which satisify all the filters will be returned. + +.PARAMETER HvDbServer + Connection object returned by Connect-HVEvent advanced function. + +.PARAMETER TimePeriod + Timeperiod of the events that user is interested in. It can take following four values: + 'day' - Lists last one day events from database + 'week' - Lists last 7 days events from database + 'month' - Lists last 30 days events from database + 'all' - Lists all the events stored in database + +.PARAMETER FilterType + Type of filter action to be applied. The parameters userfilter, severityfilter, timefilter, modulefilter, messagefilter can be used along with this. It can take following values: + 'contains' - Retrieves the events that contains the string specified in filter parameters + 'startsWith' - Retrieves the events that starts with the string specified in filter parameters + 'isExactly' - Retrieves the events that exactly match with the string specified in filter parameters + +.PARAMETER UserFilter + String that can applied in filtering on 'UserName' column. + +.PARAMETER SeverityFilter + String that can applied in filtering on 'Severity' column. + +.PARAMETER TimeFilter + String that can applied in filtering on 'EventTime' column. + +.PARAMETER ModuleFilter + String that can applied in filtering on 'Module' column. + +.PARAMETER MessageFilter + String that can applied in filtering on 'Message' column. + +.EXAMPLE + Querying all the database events on database $hvDbServer. + $e = Get-HVEvent -hvDbServer $hvDbServer + $e.Events + +.EXAMPLE + Querying all the database events where user name startswith 'aduser', severity is of 'err' type, having module name as 'broker', message starting with 'aduser' and time starting with 'HH:MM:SS.fff'. + The resulting events will be exported to a csv file 'myEvents.csv'. + $e = Get-HVEvent -HvDbServer $hvDbServer -TimePeriod 'all' -FilterType 'startsWith' -UserFilter 'aduser' -SeverityFilter 'err' -TimeFilter 'HH:MM:SS.fff' -ModuleFilter 'broker' -MessageFilter 'aduser' + $e.Events | Export-Csv -Path 'myEvents.csv' -NoTypeInformation + +.OUTPUTS + Returns a custom object that has events information in 'Events' property. Events property will have events information with five columns: UserName, Severity, EventTime, Module and Message. + +.NOTES + Author : Paramesh Oddepally. + Author email : poddepally@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()] + param( + [Parameter(Mandatory = $true)] + [pscustomobject]$HvDbServer, + + [Parameter(Mandatory = $false)] + [ValidateSet('day','week','month','all')] + [string]$TimePeriod = 'all', + + [Parameter(Mandatory = $false)] + [ValidateSet('contains','startsWith','isExactly')] + [string]$FilterType = 'contains', + + [Parameter(Mandatory = $false)] + [string]$UserFilter = "", + + [Parameter(Mandatory = $false)] + [string]$SeverityFilter = "", + + [Parameter(Mandatory = $false)] + [string]$TimeFilter = "", + + [Parameter(Mandatory = $false)] + [string]$ModuleFilter = "", + + [Parameter(Mandatory = $false)] + [string]$MessageFilter = "" + ) + + begin { + $dbConnection = $hvDbServer.dbConnection + $dbTablePrefix = $hvDbServer.dbTablePrefix + + # database table names + $eventTable = $dbTablePrefix + "event" + $eventDataTable = $dbTablePrefix + "event_data" + + # Verify the connection type in connectObject type + $isSqlType = $dbConnection.GetType().name.Equals("SqlConnection") + $isOracleType = $dbConnection.GetType().name.Equals("OracleConnection") + + if ($isSqlType) { + $command = New-Object System.Data.Sqlclient.Sqlcommand + $adapter = New-Object System.Data.SqlClient.SqlDataAdapter + } elseif ($isOracleType) { + $command = New-Object System.Data.OracleClient.OracleCommand + $adapter = New-Object System.Data.OracleClient.OracleDataAdapter + } else { + Write-Error "The dbConnection object in hvDbServer parameter is not an SQL/Oracle DB connection:[$dbConnection.GetType().Name] " + break + } + } + + process { + $command.Connection = $dbConnection + + # Extract the filter parameters and build the filterQuery string + $filterQuery = "" + + if ($userFilter -ne "") { + $filterQuery = $filterQuery + " UserSID.StrValue" + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$userFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$userFilter%'" } + else { $filterQuery = $filterQuery + " LIKE '$userFilter'" } + } + + if ($severityFilter -ne "") { + if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } + $filterQuery = $filterQuery + " Severity" + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$severityFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$severityFilter%'" } + else { $filterQuery = " LIKE '$severityFilter'" } + } + + if ($moduleFilter -ne "") { + if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } + $filterQuery = $filterQuery + " Module" + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$moduleFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$moduleFilter%'" } + else { $filterQuery = " LIKE '$moduleFilter'" } + } + + if ($messageFilter -ne "") { + if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } + $filterQuery = $filterQuery + " ModuleAndEventText" + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$messageFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$messageFilter%'" } + else { $filterQuery = " LIKE '$messageFilter'" } + } + + if ($timeFilter -ne "") { + if ($filterQuery -ne "") { $filterQuery = $filterQuery + " AND" } + + if ($isSqlType) { $filterQuery = $filterQuery + " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff')" } + else { $timePeriodQuery = $filterQuery = $filterQuery + " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3')" } + + if ($filterType -eq 'contains') { $filterQuery = $filterQuery + " LIKE '%$timeFilter%'" } + elseif ($filterType -eq 'startsWith') { $filterQuery = $filterQuery + " LIKE '$timeFilter%'" } + else { $filterQuery = " LIKE '$timeFilter'" } + } + + + # Calculate the Timeperiod and build the timePeriodQuery string + # It queries the current time from database server and calculates the time range + if ($timePeriod -eq 'day') { + $timeInDays = 1 + } elseif ($timePeriod -eq 'week') { + $timeInDays = 7 + } elseif ($timePeriod -eq 'month') { + $timeInDays = 30 + } else { + $timeInDays = 0 + } + + if ($isSqlType) { + $query = "SELECT CURRENT_TIMESTAMP" + } else { + $query = "SELECT CURRENT_TIMESTAMP from dual" + } + + $command.CommandText = $query + $adapter.SelectCommand = $command + $DataTable = New-Object System.Data.DataTable + $adapter.Fill($DataTable) + + $toDate = $DataTable.Rows[0][0] + $fromDate = $toDate.AddDays(- ($timeInDays)) + + if ($timePeriod -eq 'all') { + if ($isSqlType) { $timePeriodQuery = " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') < '" + $toDate + "'" } + else { $timePeriodQuery = " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') < '" + $toDate + "'" } + } else { + if ($isSqlType) { $timePeriodQuery = " FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') BETWEEN '" + $fromDate + "' AND '" + $toDate + "'" } + else { $timePeriodQuery = " TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') BETWEEN '" + $fromDate + "' AND '" + $toDate + "'" } + } + + + # Build the Query string based on the database type and filter parameters + if ($isSqlType) { + $query = "SELECT UserSID.StrValue AS UserName, Severity, FORMAT(Time, 'MM/dd/yyyy HH:mm:ss.fff') as EventTime, Module, ModuleAndEventText AS Message FROM $eventTable " + + " LEFT OUTER JOIN (SELECT EventID, StrValue FROM $eventDataTable WITH (NOLOCK) WHERE (Name = 'UserDisplayName')) UserSID ON $eventTable.EventID = UserSID.EventID " + $query = $query + " WHERE $timePeriodQuery" + if ($filterQuery -ne "") { $query = $query + " AND $filterQuery" } + $query = $query + " ORDER BY EventTime DESC" + } else { + $query = " SELECT UserSID.StrValue AS UserName, Severity, TO_CHAR(Time, 'MM/DD/YYYY HH24:MI:SS.FF3') AS EventTime, Module, ModuleAndEventText AS Message FROM $eventTable " + + " LEFT OUTER JOIN (SELECT EventID, StrValue FROM $eventDataTable WHERE (Name = 'UserDisplayName')) UserSID ON $eventTable.EventID = UserSID.EventID" + $query = $query + " WHERE $timePeriodQuery" + if ($filterQuery -ne "") { $query = $query + " AND $filterQuery" } + $query = $query + " ORDER BY EventTime DESC" + } + + $command.CommandText = $query + $adapter.SelectCommand = $command + + $DataTable = New-Object System.Data.DataTable + $adapter.Fill($DataTable) + + Write-Host "Number of records found : " $DataTable.Rows.Count + + <# + # This code allows the events to get printed on console + Write-Host " User Time Severity Module ModuleAndEventText " + Foreach($row in $DataTable.Rows) { + Write-Host $row[0] " " $row[1] " " $row[2] " " $row[3] " " $row[4] " " + }#> + + return New-Object pscustomobject -Property @{ Events = $DataTable; } + } + + end { + [System.gc]::collect() + } +} + +function Get-HVFarm { +<# +.SYNOPSIS + This function is used to find farms based on the search criteria provided by the user. + +.DESCRIPTION + This function queries the specified Connection Server for farms which are configured on the server. If no farm is configured on the specified connection server or no farm matches the given search criteria, it will return null. + +.PARAMETER FarmName + farmName to be searched + +.PARAMETER FarmDisplayName + farmDisplayName to be searched + +.PARAMETER FarmType + farmType to be searched. It can take following values: + "AUTOMATED" - search for automated farms only + 'MANUAL' - search for manual farms only + +.PARAMETER Enabled + search for farms which are enabled + +.PARAMETER Full + Switch to get list of FarmSummaryView or FarmInfo objects in the result. If it is true a list of FarmInfo objects is returned ohterwise a list of FarmSummaryView objects is returned. + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' -FarmDisplayName 'Sales RDS Farm' + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' -Enabled $true + +.EXAMPLE + Get-HVFarm -FarmName 'Farm-01' -Full + +.OUTPUTs + Returns the list of FarmSummaryView or FarmInfo object matching the query criteria. + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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)] + [string] + $FarmName, + + [Parameter(Mandatory = $false)] + [string] + $FarmDisplayName, + + [Parameter(Mandatory = $false)] + [ValidateSet('MANUAL','AUTOMATED')] + [string] + $FarmType, + + [Parameter(Mandatory = $false)] + [boolean] + $Enabled, + + [Parameter(Mandatory = $false)] + [switch] + $Full, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + # + # This translates the function arguments into the View API properties that must be queried + $farmSelectors = @{ + 'farmName' = 'data.name'; + 'farmDisplayName' = 'data.displayName'; + 'enabled' = 'data.enabled'; + 'farmType' = 'data.type'; + } + + $parms = $psboundparameters + + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $query = New-Object VMware.Hv.QueryDefinition + + # build the query values + + $query.queryEntityType = 'FarmSummaryView' + [VMware.Hv.queryfilter[]]$filterSet = @() + foreach ($setting in $farmSelectors.Keys) { + if ($null -ne $parms[$setting]) { + $equalsFilter = New-Object VMware.Hv.QueryFilterEquals + $equalsFilter.memberName = $farmSelectors[$setting] + $equalsFilter.value = $parms[$setting] + $filterSet += $equalsFilter + } + } + if ($filterSet.Count -gt 0) { + $queryList = New-Object VMware.Hv.QueryFilterAnd + $queryList.Filters = $filterset + $query.Filter = $queryList + } + + $queryResults = $query_service_helper.QueryService_Query($services, $query) + $farmList = $queryResults.results + if ($full) { + $farm_service_helper = New-Object VMware.Hv.FarmService + $queryResults = @() + foreach ($id in $farmList.id) { + $info = $farm_service_helper.Farm_Get($services,$id) + $queryResults += $info + } + $farmList = $queryResults + } + return $farmList +} + +function Get-HVPool { +<# +.Synopsis + Gets pool(s) information with given search parameters. + +.DESCRIPTION + Queries and returns pools information, the pools list would be determined based on + queryable fields poolName, poolDisplayName, poolType, userAssignment, enabled, + provisioningEnabled. When more than one fields are used for query the pools which + satisfy all fields criteria would be returned. + +.PARAMETER PoolName + Pool name to query for. + If the value is null or not provided then filter will not be applied, + otherwise the pools which has name same as value will be returned. + +.PARAMETER PoolDisplayName + Pool display name to query for. + If the value is null or not provided then filter will not be applied, + otherwise the pools which has display name same as value will be returned. + +.PARAMETER PoolType + Pool type to filter with. + If the value is null or not provided then filter will not be applied. + If the value is MANUAL then only manual pools would be returned. + If the value is AUTOMATED then only automated pools would be returned + If the value is RDS then only Remote Desktop Service Pool pools would be returned + +.PARAMETER UserAssignment + User Assignment of pool to filter with. + If the value is null or not provided then filter will not be applied. + If the value is DEDICATED then only dedicated pools would be returned. + If the value is FLOATING then only floating pools would be returned + +.PARAMETER Enabled + Pool enablement to filter with. + If the value is not provided then then filter will not be applied. + If the value is true then only pools which are enabled would be returned. + If the value is false then only pools which are disabled would be returned. + +.PARAMETER Full + Switch to get full information about the pool. + Use this switch only when you require complete information about pool. + +.PARAMETER HvServer + Reference to Horizon View Server to query the pools from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer + +.EXAMPLE + Get-HVPool -PoolName 'mypool' -PoolType MANUAL -UserAssignment FLOATING -Enabled $true -ProvisioningEnabled $true + +.EXAMPLE + Get-HVPool -PoolType AUTOMATED -UserAssignment FLOATING -full + +.EXAMPLE + Get-HVPool -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false + +.EXAMPLE + Get-HVPool -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false -HvServer $mycs + +.OUTPUTS + If switch -Full is used then returns list of DesktopSummaryView + else returns list of objects of type Desktop + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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)] + [string] + $PoolName, + + [Parameter(Mandatory = $false)] + [string] + $PoolDisplayName, + + [Parameter(Mandatory = $false)] + [ValidateSet('MANUAL','AUTOMATED','RDS')] + [string] + $PoolType, + + [Parameter(Mandatory = $false)] + [ValidateSet('FLOATING','DEDICATED')] + [string] + $UserAssignment, + + [Parameter(Mandatory = $false)] + [boolean] + $Enabled, + + [Parameter(Mandatory = $false)] + [boolean] + $ProvisioningEnabled, + + [Parameter(Mandatory = $false)] + [switch] + $Full, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + + # + # This translates the function arguments into the View API properties that must be queried + $poolSelectors = @{ + 'poolName' = 'desktopSummaryData.name'; + 'poolDisplayName' = 'desktopSummaryData.displayName'; + 'enabled' = 'desktopSummaryData.enabled'; + 'poolType' = 'desktopSummaryData.type'; + 'userAssignment' = 'desktopSummaryData.userAssignment'; + 'provisioningEnabled' = 'desktopSummaryData.provisioningEnabled' + } + + $parms = $psboundparameters + + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $query = New-Object VMware.Hv.QueryDefinition + + $wildCard = $false + #Only supports wild card '*' + if ($parms['PoolName'] -and $parms['PoolName'].contains('*')) { + $wildcard = $true + } + if ($parms['PoolDisplayName'] -and $parms['PoolDisplayName'].contains('*')) { + $wildcard = $true + } + # build the query values + $query.queryEntityType = 'DesktopSummaryView' + if (! $wildcard) { + [VMware.Hv.queryfilter[]]$filterSet = @() + foreach ($setting in $poolSelectors.Keys) { + if ($null -ne $parms[$setting]) { + $equalsFilter = New-Object VMware.Hv.QueryFilterEquals + $equalsFilter.memberName = $poolSelectors[$setting] + $equalsFilter.value = $parms[$setting] + $filterSet += $equalsFilter + } + } + if ($filterSet.Count -gt 0) { + $andFilter = New-Object VMware.Hv.QueryFilterAnd + $andFilter.Filters = $filterset + $query.Filter = $andFilter + } + $queryResults = $query_service_helper.QueryService_Query($services,$query) + $poolList = $queryResults.results + } + if ($wildcard -or [string]::IsNullOrEmpty($poolList)) { + $query.Filter = $null + $queryResults = $query_service_helper.QueryService_Query($services,$query) + $strFilterSet = @() + foreach ($setting in $poolSelectors.Keys) { + if ($null -ne $parms[$setting]) { + if ($wildcard -and (($setting -eq 'PoolName') -or ($setting -eq 'PoolDisplayName')) ) { + $strFilterSet += '($_.' + $poolSelectors[$setting] + ' -like "' + $parms[$setting] + '")' + } else { + $strFilterSet += '($_.' + $poolSelectors[$setting] + ' -eq "' + $parms[$setting] + '")' + } + } + } + $whereClause = [string]::Join(' -and ', $strFilterSet) + $scriptBlock = [Scriptblock]::Create($whereClause) + $poolList = $queryResults.results | where $scriptBlock + } + if ($full) { + $queryResults = @() + $desktop_helper = New-Object VMware.Hv.DesktopService + foreach ($id in $poolList.id) { + $info = $desktop_helper.Desktop_Get($services,$id) + $queryResults += $info + } + $poolList = $queryResults + } + return $poolList +} + +function Get-HVQueryFilter { +<# +.Synopsis + Creates a VMware.Hv.QueryFilter based on input provided. + +.DESCRIPTION + This is a factory method to create a VMware.Hv.QueryFilter. The type of the QueryFilter would be determined based on switch used. + +.PARAMETER MemberName + Property path separated by . (dot) from the root of queryable data object which is being queried for + +.PARAMETER MemberValue + Value of property (memberName) which is used for filtering + +.PARAMETER Eq + Switch to create QueryFilterEquals filter + +.PARAMETER Ne + Switch to create QueryFilterNotEquals filter + +.PARAMETER Contains + Switch to create QueryFilterContains filter + +.PARAMETER Startswith + Switch to create QueryFilterStartsWith filter + +.PARAMETER Not + Switch to create QueryFilterNot filter, used for negating existing filter + +.PARAMETER And + Switch to create QueryFilterAnd filter, used for joing two or more filters + +.PARAMETER Or + Switch to create QueryFilterOr filter, used for joing two or more filters + +.PARAMETER Filter + Filter to used in QueryFilterNot to negate the result + +.PARAMETER Filters + List of filters to join using QueryFilterAnd or QueryFilterOr + + +.EXAMPLE + Get-HVQueryFilter data.name -Eq vmware + +.EXAMPLE + Get-HVQueryFilter -MemberName data.name -Eq -MemberValue vmware + +.EXAMPLE + Get-HVQueryFilter data.name -Ne vmware + +.EXAMPLE + Get-HVQueryFilter data.name -Contains vmware + +.EXAMPLE + Get-HVQueryFilter data.name -Startswith vmware + +.EXAMPLE + $filter = Get-HVQueryFilter data.name -Startswith vmware + Get-HVQueryFilter -Not $filter + +.EXAMPLE + $filter1 = Get-HVQueryFilter data.name -Startswith vmware + $filter2 = Get-HVQueryFilter data.name -Contains pool + Get-HVQueryFilter -And @($filter1, $filter2) + +.EXAMPLE + $filter1 = Get-HVQueryFilter data.name -Startswith vmware + $filter2 = Get-HVQueryFilter data.name -Contains pool + Get-HVQueryFilter -Or @($filter1, $filter2) + +.OUTPUTS + Returns the QueryFilter object + +.NOTES + Author : Kummara Ramamohan. + Author email : kramamohan@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()] + param( + # Type 1 parametersets which requires memberName, memberValue as input + [Parameter(ParameterSetName = 'eq',Mandatory = $true,Position = 0)] + [Parameter(ParameterSetName = 'contains',Mandatory = $true,Position = 0)] + [Parameter(ParameterSetName = 'startswith',Mandatory = $true,Position = 0)] + [Parameter(ParameterSetName = 'ne',Mandatory = $true,Position = 0)] + [string]$MemberName, + + [Parameter(ParameterSetName = "eq",Mandatory = $true,Position = 1)] + [switch]$Eq, + + [Parameter(ParameterSetName = "contains",Mandatory = $true,Position = 1)] + [switch]$Contains, + + [Parameter(ParameterSetName = "startswith",Mandatory = $true,Position = 1)] + [switch]$Startswith, + + [Parameter(ParameterSetName = "ne",Mandatory = $true,Position = 1)] + [switch]$Ne, + + [Parameter(ParameterSetName = 'eq',Mandatory = $true,Position = 2)] + [Parameter(ParameterSetName = 'contains',Mandatory = $true,Position = 2)] + [Parameter(ParameterSetName = 'startswith',Mandatory = $true,Position = 2)] + [Parameter(ParameterSetName = 'ne',Mandatory = $true,Position = 2)] + [System.Object]$MemberValue, + + # Negation # + [Parameter(ParameterSetName = "not",Mandatory = $true,Position = 0)] + [switch]$Not, + + [Parameter(ParameterSetName = 'not',Mandatory = $true,Position = 1)] + [VMware.Hv.QueryFilter]$Filter, + + # Aggregators to join more than 1 filters # + [Parameter(ParameterSetName = 'and',Mandatory = $true,Position = 0)] + [switch]$And, + + [Parameter(ParameterSetName = "or",Mandatory = $true,Position = 0)] + [switch]$Or, + + [Parameter(ParameterSetName = "and",Mandatory = $true,Position = 1)] + [Parameter(ParameterSetName = "or",Mandatory = $true,Position = 1)] + [VMware.Hv.QueryFilter[]]$Filters + ) + + begin { + $switchToClassName = @{ + 'eq' = 'QueryFilterEquals'; + 'startswith' = 'QueryFilterStartsWith'; + 'contains' = 'QueryFilterContains'; + 'ne' = 'QueryFilterNotEquals'; + 'not' = 'QueryFilterNot'; + 'and' = 'QueryFilterAnd'; + 'or' = 'QueryFilterOr'; + } + } + process { + $queryFilter = Get_New_Object -typeName $switchToClassName[$PsCmdlet.ParameterSetName] + + switch ($PsCmdlet.ParameterSetName) { + + { @( 'eq','startswith','contains','ne') -icontains $_ } { + $queryFilter.memberName = $memberName + $queryFilter.value = $membervalue + } + + { @( 'and','or') -icontains $_ } { + $queryFilter.filters = $filters + } + + { @( 'not') -icontains $_ } { + $queryFilter.filter = $filter + } + } + } + end { + return $queryFilter + } +} + +function Get-HVQueryResult { +<# +.Synopsis + Returns the query results from ViewApi Query Service + +.DESCRIPTION + Get-HVQueryResult is a API to query the results using ViewApi. The filtering of the returned + list would be done based on input parameters filter, sortDescending, sortyBy, limit + +.PARAMETER EntityType + ViewApi Queryable entity type which is being queried for.The return list would be containing objects of entityType + +.PARAMETER Filter + Filter to used for filtering the results, See Get-HVQueryFilter for more information + +.PARAMETER SortBy + Data field path used for sorting the results + +.PARAMETER SortDescending + If the value is set to true (default) then the results will be sorted in descending order + If the value is set to false then the results will be sorted in ascending order + +.PARAMETER Limit + Max number of objects to retrieve. Default would be 0 which means retieve all the results + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer + +.EXAMPLE + Get-HVQueryResult DesktopSummaryView + +.EXAMPLE + Get-HVQueryResult DesktopSummaryView (Get-HVQueryFilter data.name -Eq vmware) + +.EXAMPLE + Get-HVQueryResult -EntityType DesktopSummaryView -Filter (Get-HVQueryFilter desktopSummaryData.name -Eq vmware) + +.EXAMPLE + Get-HVQueryResult -EntityType DesktopSummaryView -Filter (Get-HVQueryFilter desktopSummaryData.name -Eq vmware) -SortBy desktopSummaryData.displayName + +.EXAMPLE + $myFilter = Get-HVQueryFilter data.name -Contains vmware + Get-HVQueryResult -EntityType DesktopSummaryView -Filter $myFilter -SortBy desktopSummaryData.displayName -SortDescending $false + +.EXAMPLE + Get-HVQueryResult DesktopSummaryView -Limit 10 + +.OUTPUTS + Returns the list of objects of entityType + +.NOTES + Author : Kummara Ramamohan. + Author email : kramamohan@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(Position = 0,Mandatory = $true)] + [ValidateSet('ADUserOrGroupSummaryView','ApplicationIconInfo','ApplicationInfo','DesktopSummaryView', + 'EntitledUserOrGroupGlobalSummaryView','EntitledUserOrGroupLocalSummaryView','FarmHealthInfo', + 'FarmSummaryView','GlobalApplicationEntitlementInfo','GlobalEntitlementSummaryView', + 'MachineNamesView','MachineSummaryView','PersistentDiskInfo','PodAssignmentInfo', + 'RDSServerInfo','RDSServerSummaryView','RegisteredPhysicalMachineInfo','SampleInfo', + 'SessionLocalSummaryView','TaskInfo','URLRedirectionInfo','UserHomeSiteInfo')] + [string]$EntityType, + + [Parameter(Position = 1,Mandatory = $false)] + [VMware.Hv.QueryFilter]$Filter = $null, + + [Parameter(Position = 2,Mandatory = $false)] + [string]$SortBy = $null, + + [Parameter(Position = 3,Mandatory = $false)] + [bool]$SortDescending = $true, + + [Parameter(Position = 4,Mandatory = $false)] + [int16]$Limit = 0, + + [Parameter(Position = 5,Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $queryDef = New-Object VMware.Hv.QueryDefinition + $queryDef.queryEntityType = $entityType + $queryDef.sortDescending = $sortDescending + + if ($sortBy) { + $queryDef.sortBy = $sortBy + } + + if ($limit -gt 0) { + $queryDef.limit = $limit + } + + $queryDef.filter = $filter + + $returnList = @() + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $queryResults = $query_service_helper.QueryService_Create($services,$queryDef) + $returnList += $queryResults.results + + while ($queryResults -and ($queryResults.RemainingCount -gt 0)) { + $queryResults = $query_service_helper.QueryService_GetNext($services,$queryResults.id) + $returnList += $queryResults.results + } + + if ($queryResults.id) { + $query_service_helper.QueryService_Delete($services,$queryResults.id) + } + } + + end { + return $returnList + } +} + +function New-HVFarm { +<# +.Synopsis + Creates a new farm. + +.DESCRIPTION + Creates a new farm, the type would be determined based on input parameters. + +.PARAMETER LinkedClone + Switch to Create Automated Linked Clone farm. + +.PARAMETER Manual + Switch to Create Manual farm. + +.PARAMETER FarmName + Name of the farm. + +.PARAMETER FarmDisplayName + Display name of the farm. + +.PARAMETER Description + Description of the farm. + +.PARAMETER AccessGroup + View access group can organize the servers in the farm. + Default Value is 'Root'. + +.PARAMETER Enable + Set true to enable the farm otherwise set to false. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) where the farm RDS Servers are located. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER ParentVM + Base image VM for RDS Servers. + Applicable only to Linked Clone farms. + +.PARAMETER SnapshotVM + Base image snapshot for RDS Servers. + +.PARAMETER VmFolder + VM folder to deploy the RDSServers to. + Applicable to Linked Clone farms. + +.PARAMETER HostOrCluster + Host or cluster to deploy the RDSServers in. + Applicable to Linked Clone farms. + +.PARAMETER ResourcePool + Resource pool to deploy the RDSServers. + Applicable to Linked Clone farms. + +.PARAMETER Datastores + Datastore names to store the RDSServer. + Applicable to Linked Clone farms. + +.PARAMETER UseVSAN + Whether to use vSphere VSAN. This is applicable for vSphere 5.5 or later. + Applicable to Linked Clone farms. + +.PARAMETER EnableProvisioning + Set to true to enable provision of RDSServers immediately in farm. + Applicable to Linked Clone farms. + +.PARAMETER StopOnProvisioningError + Set to true to stop provisioning of all RDSServers on error. + Applicable to Linked Clone farms. + +.PARAMETER TransparentPageSharingScope + The transparent page sharing scope. + The default value is 'VM'. + +.PARAMETER NamingMethod + Determines how the VMs in the farm are named. + Set PATTERN to use naming pattern. + The default value is PATTERN. Curentlly only PATTERN is allowed. + +.PARAMETER NamingPattern + RDS Servers will be named according to the specified naming pattern. + Value would be considered only when $namingMethod = PATTERN + The default value is farmName + '{n:fixed=4}'. + +.PARAMETER MinReady + Minimum number of ready (provisioned) Servers during View Composer maintenance operations. + The default value is 0. + Applicable to Linked Clone farms. + +.PARAMETER MaximumCount + Maximum number of Servers in the farm. + The default value is 1. + Applicable to Linked Clone farms. + +.PARAMETER AdContainer + This is the Active Directory container which the Servers will be added to upon creation. + The default value is 'CN=Computers'. + Applicable to Linked Clone farm. + +.PARAMETER NetBiosName + Domain Net Bios Name. + Applicable to Linked Clone farms. + +.PARAMETER DomainAdmin + Domain Administrator user name which will be used to join the domain. + Default value is null. + Applicable to Linked Clone farms. + +.PARAMETER SysPrepName + The customization spec to use. + Applicable to Linked Clone farms. + +.PARAMETER RdsServers + List of existing registered RDS server names to add into manual farm. + Applicable to Manual farms. + +.PARAMETER Spec + Path of the JSON specification file. + +.PARAMETER HvServer + Reference to Horizon View Server to query the farms from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + New-HVFarm -LinkedClone -FarmName 'LCFarmTest' -ParentVM 'Win_Server_2012_R2' -SnapshotVM 'Snap_RDS' -VmFolder 'PoolVM' -HostOrCluster 'cls' -ResourcePool 'cls' -Datastores 'datastore1 (5)' -FarmDisplayName 'LC Farm Test' -Description 'created LC Farm from PS' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "LCFarmVM_PS" -MinReady 1 -MaximumCount 1 -SysPrepName "RDSH_Cust2" -NetBiosName "adviewdev" + +.EXAMPLE + New-HVFarm -Spec C:\VMWare\Specs\LinkedClone.json + +.EXAMPLE + New-HVFarm -Manual -FarmName "manualFarmTest" -FarmDisplayName "manualFarmTest" -Description "Manual PS Test" -RdsServers "vm-for-rds.eng.vmware.com","vm-for-rds-2.eng.vmware.com" + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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 = $true,ParameterSetName = "LINKED_CLONE")] + [switch] + $LinkedClone, + + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [switch] + $Manual, + + #farmSpec.farmData.name + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $FarmName, + + #farmSpec.farmData.displayName + [Parameter(Mandatory = $false)] + [string] + $FarmDisplayName = $farmName, + + #farmSpec.farmData.description + [Parameter(Mandatory = $false)] + [string] + $Description = ' ', + + #farmSpec.farmData.accessGroup + [Parameter(Mandatory = $false)] + [string] + $AccessGroup = 'Root', + + #farmSpec.farmData.enabled + [Parameter(Mandatory = $false)] + [boolean] + $Enable = $true, + + #farmSpec.automatedfarmSpec.virtualCenter if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $Vcenter, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVM if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $ParentVM, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshotVM if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $SnapshotVM, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $VmFolder, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.hostOrCluster if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $HostOrCluster, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.resourcePool if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $ResourcePool, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string[]] + $Datastores, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.useVSAN if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $UseVSAN, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean] + $EnableProvisioning = $true, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean] + $StopOnProvisioningError = $true, + + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $TransparentPageSharingScope = 'VM', + + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.namingMethod if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('PATTERN')] + [string] + $NamingMethod = 'PATTERN', + + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.namingPattern if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $NamingPattern = $farmName + '{n:fixed=4}', + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [int] + $MinReady = 0, + + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [int] + $MaximumCount = 1, + + #farmSpec.automatedfarmSpec.customizationSettings.adContainer if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string] + $AdContainer = 'CN=Computers', + + #farmSpec.automatedfarmSpec.customizationSettings.domainAdministrator + [Parameter(Mandatory = $true,ParameterSetName = 'LINKED_CLONE')] + [string] + $NetBiosName, + + #farmSpec.automatedfarmSpec.customizationSettings.domainAdministrator + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string] + $DomainAdmin = $null, + + #farmSpec.automatedfarmSpec.customizationSettings.sysprepCustomizationSettings.customizationSpec if LINKED_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [string] + $SysPrepName, + + ##farmSpec.manualfarmSpec.rdsServers + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [string[]] + $RdsServers, + + [Parameter(Mandatory = $false,ParameterSetName = 'JSON_FILE')] + [string] + $Spec, + + [Parameter(Mandatory = $false)] + $HvServer = $null + + ) + # + # farmSpec/FarmInfo + # *farmData + # +AccessGroupId + # +FarmSessionSettings + # FarmAutomatedfarmSpec/FarmAutomatedFarmData + # */+VirtualCenterId + # FarmRDSServerNamingSpec/FarmVirtualMachineNamingSettings + # FarmPatternNamingSpec/FarmPatternNamingSettings + # FarmVirtualCenterProvisioningSettings + # FarmVirtualCenterProvisioningData/virtualCenterProvisioningData + # FarmVirtualCenterStorageSettings + # FarmVirtualCenterNetworkingSettings + # FarmVirtualCenterManagedCommonSettings + # FarmCustomizationSettings + # ViewComposerDomainAdministratorId + # ADContainerId + # FarmSysprepCustomizationSettings + # CustomizationSpecId + # FarmManualfarmSpec + # RDSServerId[] + # + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + + if ($farmName) { + try { + $sourceFarm = Get-HVFarm -farmName $farmName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($sourceFarm) { + Write-Error "Farm with name [$farmName] already exists" + return + } + } + $farm_service_helper = New-Object VMware.Hv.FarmService + if ($spec) { + try { + $jsonObject = Get_Json_Object -specFile $spec + } catch { + Write-Error "Json file exception, $_" + break + } + if ($jsonObject.type -eq 'AUTOMATED') { + $farmType = 'AUTOMATED' + if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenter) { + $vCenter = $jsonObject.AutomatedFarmSpec.VirtualCenter + } + $linkedClone = $true + $netBiosName = $jsonObject.NetBiosName + $adContainer = $jsonObject.AutomatedFarmSpec.CustomizationSettings.AdContainer + + $namingMethod = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.NamingMethod + $namingPattern = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern + $maximumCount = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers + + $transparentPageSharingScope = $jsonObject.AutomatedFarmSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope + + if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm) { + $parentVM = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm + } + if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot) { + $snapshotVM = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot + } + $vmFolder = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.VmFolder + $hostOrCluster = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.HostOrCluster + $resourcePool = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ResourcePool + $dataStoreList = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores + foreach ($dtStore in $dataStoreList) { + $datastores += $dtStore.Datastore + } + $sysPrepName = $jsonObject.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec + } elseif ($jsonObject.type -eq 'MANUAL') { + $manual = $true + $farmType = 'MANUAL' + $RdsServersObjs = $jsonObject.ManualFarmSpec.RdsServers + + foreach ($RdsServerObj in $RdsServersObjs) { + $rdsServers += $RdsServerObj.rdsServer + } + } + $farmDisplayName = $jsonObject.data.DisplayName + $description = $jsonObject.data.Description + $accessGroup = $jsonObject.data.AccessGroup + $farmName = $jsonObject.data.name + } + + if ($linkedClone) { + $farmType = 'AUTOMATED' + $provisioningType = 'VIEW_COMPOSER' + } elseif ($manual) { + $farmType = 'MANUAL' + } + + $script:farmSpecObj = Get_Farm_Spec -farmType $farmType -provisioningType $provisioningType -namingMethod $namingMethod + + # + # build out the infrastructure based on type of provisioning + # + $handleException = $false + switch ($farmType) { + + 'MANUAL' { + try { + $serverList = Get-RegisteredRDSServers -services $services -serverList $rdsServers + $farmSpecObj.ManualFarmSpec.RdsServers = $serverList + } catch { + $handleException = $true + Write-Error "Failed to create Farm with error: $_" + break + } + } + default { + # + # accumulate properties that are shared among various type + # + + # + # vCenter: if $vcenterID is defined, then this is a clone + # if the user specificed the name, then find it from the list + # if none specified, then automatically use the vCenter if there is only one + # + + if (!$virtualCenterID) { + $virtualCenterID = Get_Vcenter_ID -services $services -vCenter $vCenter + } + + if ($null -eq $virtualCenterID) { + $handleException = $true + break + } + + # + # transparentPageSharingScope + # + + if (!$farmVirtualCenterManagedCommonSettings) { + if ($farmSpecObj.AutomatedFarmSpec) { + $farmSpecObj.AutomatedFarmSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope + } + $farmVirtualCenterManagedCommonSettings = $farmSpecObj.AutomatedFarmSpec.virtualCenterManagedCommonSettings + } + + if (!$farmVirtualMachineNamingSpec) { + $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.NamingMethod = $namingMethod + $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern = $namingPattern + $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers = $maximumCount + } else { + $vmNamingSpec = New-Object VMware.Hv.FarmRDSServerNamingSpec + $vmNamingSpec.NamingMethod = 'PATTERN' + + $vmNamingSpec.patternNamingSettings = New-Object VMware.Hv.FarmPatternNamingSettings + $vmNamingSpec.patternNamingSettings.namingPattern = $namingPattern + $vmNamingSpec.patternNamingSettings.maxNumberOfRDSServers = $maximumCount + } + + # + # build the VM LIST + # + try { + $farmVirtualCenterProvisioningData = Build_VM_List_Farm -vc $virtualCenterID -vmObject $farmVirtualCenterProvisioningData + $hostClusterId = $farmVirtualCenterProvisioningData.HostOrCluster + $farmVirtualCenterStorageSettings = Build_Datastore_List_Farm -hostclusterID $hostClusterId -storageObject $farmVirtualCenterStorageSettings + $farmVirtualCenterNetworkingSettings = Build_Network_List_Farm -networkObject $farmVirtualCenterNetworkingSettings + $farmCustomizationSettings = Build_Customization_Settings_Farm -vc $virtualCenterID -customObject $farmCustomizationSettings + } catch { + $handleException = $true + Write-Error "Failed to create Farm with error: $_" + break + } + + $farmSpecObj.AutomatedFarmSpec.RdsServerMaxSessionsData.MaxSessionsType = "UNLIMITED" + + if (!$FarmVirtualCenterProvisioningSettings) { + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.enableProvisioning = $true + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $true + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = 0 + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $farmVirtualCenterProvisioningData + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $farmVirtualCenterStorageSettings + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $FarmVirtualCenterNetworkingSettings + + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings = $farmCustomizationSettings + $farmSpecObj.AutomatedFarmSpec.ProvisioningType = $provisioningType + $farmSpecObj.AutomatedFarmSpec.VirtualCenter = $virtualCenterID + } else { + $FarmVirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $farmVirtualCenterProvisioningData + $FarmVirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $farmVirtualCenterStorageSettings + $FarmVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $FarmVirtualCenterNetworkingSettings + + $FarmAutomatedFarmSpec = New-Object VMware.Hv.FarmAutomatedFarmSpec + $FarmAutomatedFarmSpec.ProvisioningType = $provisioningType + $FarmAutomatedFarmSpec.VirtualCenter = $virtualCenterID + $FarmAutomatedFarmSpec.VirtualCenterProvisioningSettings = $farmVirtualCenterProvisioningSettings + $FarmAutomatedFarmSpec.virtualCenterManagedCommonSettings = $farmVirtualCenterManagedCommonSettings + $FarmAutomatedFarmSpec.CustomizationSettings = $farmCustomizationSettings + } + } + } + + if ($handleException) { + break + } + + $farmData = $farmSpecObj.data + $AccessGroup_service_helper = New-Object VMware.Hv.AccessGroupService + $ag = $AccessGroup_service_helper.AccessGroup_List($services) | Where-Object { $_.base.name -eq $accessGroup } + $farmData.AccessGroup = $ag.id + + $farmData.name = $farmName + $farmData.DisplayName = $farmDisplayName + $farmData.Description = $description + $farmSpecObj.type = $farmType + + if ($FarmAutomatedFarmSpec) { + $farmSpecObj.AutomatedFarmSpec = $FarmAutomatedFarmSpec + } + if ($FarmManualFarmSpec) { + $farmSpecObj.ManualFarmSpec = $FarmManualFarmSpec + } + + # Please uncomment below code, if you want to save the json file + <# +$myDebug = convertto-json -InputObject $farmSpecObj -depth 12 +$myDebug | out-file -filepath c:\temp\copiedfarm.json +#> + $farm_service_helper.Farm_Create($services, $farmSpecObj) + } + + end { + [System.gc]::collect() + } + +} + +function Build_VM_List_Farm { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmVirtualCenterProvisioningData]$VmObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID + ) + if (!$vmObject) { + $vmObject = $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData + } + if ($parentVM) { + $BaseImage_service_helper = New-Object VMware.Hv.BaseImageVmService + $parentList = $BaseImage_service_helper.BaseImageVm_List($services, $vcID) + $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } + if ($null -eq $parentVMObj) { + throw "No Parent VM found with name: [$parentVM]" + } + $vmObject.ParentVm = $parentVMObj.id + $dataCenterID = $parentVMObj.datacenter + $vmObject.datacenter = $dataCenterID + } + if ($snapshotVM) { + $BaseImageSnapshot_service_helper = New-Object VMware.Hv.BaseImageSnapshotService + $snapshotList = $BaseImageSnapshot_service_helper.BaseImageSnapshot_List($services, $parentVMObj.id) + $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } + if ($null -eq $snapshotVMObj) { + throw "No Snapshot found with name: [$snapshotVM] for VM name: [$parentVM] " + } + $vmObject.Snapshot = $snapshotVMObj.id + } + if ($vmFolder) { + $VmFolder_service_helper = New-Object VMware.Hv.VmFolderService + $folders = $VmFolder_service_helper.VmFolder_GetVmFolderTree($services, $vmObject.datacenter) + $folderList = @() + $folderList += $folders + while ($folderList.Length -gt 0) { + $item = $folderList[0] + if ($item -and !$_.folderdata.incompatiblereasons.inuse -and !$_.folderdata.incompatiblereasons.viewcomposerreplicafolder -and ($item.folderdata.name -eq $vmFolder)) { + $vmObject.VmFolder = $item.id + break + } + foreach ($folderItem in $item.children) { + $folderList += $folderItem + } + $folderList = $folderList[1..$folderList.Length] + } + if ($null -eq $vmObject.VmFolder) { + throw "No VM Folder found with name: [$vmFolder]" + } + } + if ($hostOrCluster) { + $HostOrCluster_service_helper = New-Object VMware.Hv.HostOrClusterService + $hostClusterList = ($HostOrCluster_service_helper.HostOrCluster_GetHostOrClusterTree($services, $vmobject.datacenter)).treeContainer.children.info + $HostClusterObj = $hostClusterList | Where-Object { $_.name -eq $hostOrCluster } + if ($null -eq $HostClusterObj) { + throw "No host or cluster found with name: [$hostOrCluster]" + } + $vmObject.HostOrCluster = $HostClusterObj.id + } + if ($resourcePool) { + $ResourcePool_service_helper = New-Object VMware.Hv.ResourcePoolService + $resourcePoolList = $ResourcePool_service_helper.ResourcePool_GetResourcePoolTree($services, $vmobject.HostOrCluster) + $resourcePoolObj = $resourcePoolList | Where-Object { $_.resourcepooldata.name -eq $resourcePool } + if ($null -eq $resourcePoolObj) { + throw "No resource pool found with name: [$resourcePool]" + } + $vmObject.ResourcePool = $resourcePoolObj.id + } + return $vmObject +} + +function Build_Datastore_List_Farm { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmVirtualCenterStorageSettings]$StorageObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.HostOrClusterId]$HostClusterID + ) + if (!$storageObject) { + $storageObject = New-Object VMware.Hv.FarmVirtualCenterStorageSettings + + $FarmSpaceReclamationSettings = New-Object VMware.Hv.FarmSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $false } + + $FarmViewComposerStorageSettingsList = @{ + 'useSeparateDatastoresReplicaAndOSDisks' = $false; + 'replicaDiskDatastore' = $FarmReplicaDiskDatastore + 'useNativeSnapshots' = $false; + 'spaceReclamationSettings' = $FarmSpaceReclamationSettings; + } + + $storageObject.ViewComposerStorageSettings = New-Object VMware.Hv.FarmViewComposerStorageSettings -Property $FarmViewComposerStorageSettingsList + } + + if ($datastores) { + $Datastore_service_helper = New-Object VMware.Hv.DatastoreService + $datastoreList = $Datastore_service_helper.Datastore_ListDatastoresByHostOrCluster($services, $hostClusterID) + $datastoresSelected = @() + foreach ($ds in $datastores) { + $datastoresSelected += ($datastoreList | Where-Object { $_.datastoredata.name -eq $ds }).id + } + foreach ($ds in $datastoresSelected) { + $datastoresObj = New-Object VMware.Hv.FarmVirtualCenterDatastoreSettings + $datastoresObj.Datastore = $ds + $datastoresObj.StorageOvercommit = 'UNBOUNDED' + $StorageObject.Datastores += $datastoresObj + } + } + if ($storageObject.Datastores.Count -eq 0) { + throw "No datastores found with name: [$datastores]" + } + if ($useVSAN) { $storageObject.useVSAN = $useVSAN } + return $storageObject +} + +function Build_Network_List_Farm { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmVirtualCenterNetworkingSettings]$NetworkObject + ) + if (!$networkObject) { + $networkObject = $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings + } + return $networkObject +} + +function Build_Customization_Settings_Farm { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmCustomizationSettings]$CustomObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID + ) + if (!$customObject) { + $ViewComposerDomainAdministrator_service_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService + $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministrator_service_helper.ViewComposerDomainAdministrator_List($services, $vcID) | Where-Object { $_.base.domain -cmatch $netBiosName }) + if (! [string]::IsNullOrWhitespace($domainAdmin)) { + $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministratorID | Where-Object { $_.base.userName -ieq $domainAdmin }).id + } else { + $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id + } + if ($null -eq $ViewComposerDomainAdministratorID) { + throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" + } + $ADDomain_service_helper = New-Object VMware.Hv.ADDomainService + $adDomianId = ($ADDomain_service_helper.ADDomain_List($services) | Where-Object { $_.NetBiosName -eq $netBiosName } | Select-Object -Property id) + if ($null -eq $adDomianId) { + throw "No Domain found with netBiosName: [$netBiosName]" + } + $ad_containder_service_helper = New-Object VMware.Hv.AdContainerService + $adContainerId = ($ad_containder_service_helper.ADContainer_ListByDomain($services, $adDomianId.id) | Where-Object { $_.Rdn -eq $adContainer } | Select-Object -Property id).id + if ($null -eq $adContainerId) { + throw "No AdContainer found with name: [$adContainer]" + } + #Support only Sysprep Customization + $sysprepCustomizationSettings = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings + + # Get SysPrep CustomizationSpec ID + $CustomizationSpec_service_helper = New-Object VMware.Hv.CustomizationSpecService + $sysPrepIds = $CustomizationSpec_service_helper.CustomizationSpec_List($services, $vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id + if ($sysPrepIds.Count -eq 0) { + throw "No Sysprep Customization spec found with Name: [$sysPrepName]" + } + $sysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id + + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.DomainAdministrator = $ViewComposerDomainAdministratorID + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.AdContainer = $adContainerId + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.ReusePreExistingAccounts = $false + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings = $sysprepCustomizationSettings + + $customObject = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings + } + return $customObject +} + +function Get_Farm_Spec { + param( + [Parameter(Mandatory = $true)] + [string]$FarmType, + + [Parameter(Mandatory = $false)] + [string]$ProvisioningType, + + [Parameter(Mandatory = $false)] + [string]$NamingMethod + ) + + $farm_helper = New-Object VMware.Hv.FarmService + $farm_spec_helper = $farm_helper.getFarmSpecHelper() + $farm_spec_helper.setType($farmType) + if ($farmType -eq 'AUTOMATED') { + $farm_spec_helper.getDataObject().AutomatedFarmSpec.RdsServerNamingSpec.PatternNamingSettings = $farm_helper.getFarmPatternNamingSettingsHelper().getDataObject() + $farm_spec_helper.getDataObject().AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings = $farm_helper.getFarmViewComposerStorageSettingsHelper().getDataObject() + } elseif ($farmType -eq 'MANUAL') { + # No need to set + } + return $farm_spec_helper.getDataObject() +} + +function New-HVPool { +<# +.Synopsis + Creates new desktop pool. + +.DESCRIPTION + Creates new desktop pool, the type and user assignment type would be + determined based on input parameters. + +.PARAMETER InstantClone + Switch to Create Instant Clone pool. + +.PARAMETER LinkedClone + Switch to Create Linked Clone pool. + +.PARAMETER FullClone + Switch to Create Full Clone pool. + +.PARAMETER Manual + Switch to Create Manual Clone pool. + +.PARAMETER Rds + Switch to Create RDS pool. + +.PARAMETER PoolName + Name of the pool. + +.PARAMETER PoolDisplayName + Display name of pool. + +.PARAMETER Description + Description of pool. + +.PARAMETER AccessGroup + View access group can organize the desktops in the pool. + Default Value is 'Root'. + +.PARAMETER GlobalEntitlement + Description of pool. + Global entitlement to associate the pool. + +.PARAMETER UserAssignment + User Assignment type of pool. + Set to DEDICATED for dedicated desktop pool. + Set to FLOATING for floating desktop pool. + +.PARAMETER AutomaticAssignment + Automatic assignment of a user the first time they access the machine. + Applicable to dedicated desktop pool. + +.PARAMETER Enable + Set true to enable the pool otherwise set to false. + +.PARAMETER ConnectionServerRestrictions + Connection server restrictions. + This is a list of tags that access to the desktop is restricted to. + No list means that the desktop can be accessed from any connection server. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) where the pool virtual machines are located. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER Template + Virtual machine Template name to clone Virtual machines. + Applicable only to Full Clone pools. + +.PARAMETER ParentVM + Parent Virtual Machine to clone Virtual machines. + Applicable only to Linked Clone and Instant Clone pools. + +.PARAMETER SnapshotVM + Base image VM for Linked Clone pool and current Image for Instant Clone Pool. + +.PARAMETER VmFolder + VM folder to deploy the VMs to. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER HostOrCluster + Host or cluster to deploy the VMs in. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER ResourcePool + Resource pool to deploy the VMs. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER Datastores + Datastore names to store the VM + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER UseVSAN + Whether to use vSphere VSAN. This is applicable for vSphere 5.5 or later. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER StopOnProvisioningError + Set to true to stop provisioning of all VMs on error. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER TransparentPageSharingScope + The transparent page sharing scope. + The default value is 'VM'. + +.PARAMETER NamingMethod + Determines how the VMs in the desktop are named. + Set SPECIFIED to use specific name. + Set PATTERN to use naming pattern. + The default value is PATTERN. For Instant Clone pool the value must be PATTERN. + +.PARAMETER NamingPattern + Virtual machines will be named according to the specified naming pattern. + Value would be considered only when $namingMethod = PATTERN. + The default value is poolName + '{n:fixed=4}'. + +.PARAMETER MinReady + Minimum number of ready (provisioned) machines during View Composer maintenance operations. + The default value is 0. + Applicable to Linked Clone Pools. + +.PARAMETER MaximumCount + Maximum number of machines in the pool. + The default value is 1. + Applicable to Full, Linked, Instant Clone Pools + +.PARAMETER SpareCount + Number of spare powered on machines in the pool. + The default value is 1. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER ProvisioningTime + Determines when machines are provisioned. + Supported values are ON_DEMAND, UP_FRONT. + The default value is UP_FRONT. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER MinimumCount + The minimum number of machines to have provisioned if on demand provisioning is selected. + The default value is 0. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER SpecificNames + Specified names of VMs in the pool. + The default value is -1 + Applicable to Full, Linked and Cloned Pools. + +.PARAMETER StartInMaintenanceMode + Set this to true to allow virtual machines to be customized manually before users can log + in and access them. + the default value is false + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER NumUnassignedMachinesKeptPoweredOn + Number of unassigned machines kept powered on. value should be less than max number of vms in the pool. + The default value is 1. + Applicable to Full, Linked, Instant Clone Pools. + When JSON Spec file is used for pool creation, the value will be read from JSON spec. + +.PARAMETER AdContainer + This is the Active Directory container which the machines will be added to upon creation. + The default value is 'CN=Computers'. + Applicable to Instant Clone Pool. + +.PARAMETER NetBiosName + Domain Net Bios Name. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER DomainAdmin + Domain Administrator user name which will be used to join the domain. + Default value is null. + Applicable to Full, Linked, Instant Clone Pools. + +.PARAMETER CustType + Type of customization to use. + Supported values are 'CLONE_PREP','QUICK_PREP','SYS_PREP','NONE'. + Applicable to Full, Linked Clone Pools. + +.PARAMETER SysPrepName + The customization spec to use. + Applicable to Full, Linked Clone Pools. + +.PARAMETER Source + Source of the Virtual machines for manual pool. + Supported values are 'VIRTUAL_CENTER','UNMANAGED'. + Set VIRTUAL_CENTER for vCenter managed VMs. + Set UNMANAGED for Physical machines or VMs which are not vCenter managed VMs. + Applicable to Manual Pools. + +.PARAMETER VM + List of existing virtual machine names to add into manual pool. + Applicable to Manual Pools. + +.PARAMETER Farm + Farm to create RDS pools + Applicable to RDS Pools. + +.PARAMETER Spec + Path of the JSON specification file. + +.PARAMETER ClonePool + Existing pool info to clone a new pool. + +.PARAMETER HvServer + Reference to Horizon View Server to query the pools from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Create new automated linked clone pool with naming method pattern + New-HVPool -LinkedClone -PoolName 'vmwarepool' -UserAssignment FLOATING -ParentVM 'Agent_vmware' -SnapshotVM 'kb-hotfix' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -Datastores 'datastore1' -NamingMethod PATTERN -PoolDisplayName 'vmware linkedclone pool' -Description 'created linkedclone pool from ps' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "vmware2" -MinReady 1 -MaximumCount 1 -SpareCount 1 -ProvisioningTime UP_FRONT -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root + +.EXAMPLE + Create new automated linked clone pool by using JSON spec file + New-HVPool -Spec C:\VMWare\Specs\LinkedClone.json + +.EXAMPLE + Clone new pool from automated linked (or) full clone pool + Get-HVPool -PoolName 'vmwarepool' | New-HVPool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; + (OR) + $vmwarepool = Get-HVPool -PoolName 'vmwarepool'; New-HVPool -ClonePool $vmwarepool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; + +.EXAMPLE + Create new automated instant clone pool with naming method pattern + New-HVPool -InstantClone -PoolName "InsPoolvmware" -PoolDisplayName "insPool" -Description "create instant pool" -UserAssignment FLOATING -ParentVM 'Agent_vmware' -SnapshotVM 'kb-hotfix' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -NamingMethod PATTERN -Datastores 'datastore1' -NamingPattern "inspool2" -NetBiosName 'adviewdev' -DomainAdmin root + +.EXAMPLE + Create new automated full clone pool with naming method pattern + New-HVPool -FullClone -PoolName "FullClone" -PoolDisplayName "FullClonePra" -Description "create full clone" -UserAssignment DEDICATED -Template 'powerCLI-VM-TEMPLATE' -VmFolder 'vmware' -HostOrCluster 'CS-1' -ResourcePool 'CS-1' -Datastores 'datastore1' -NamingMethod PATTERN -NamingPattern 'FullCln1' -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root + +.EXAMPLE + Create new managed manual pool from virtual center managed VirtualMachines. + New-HVPool -MANUAL -PoolName 'manualVMWare' -PoolDisplayName 'MNLPUL' -Description 'Manual pool creation' -UserAssignment FLOATING -Source VIRTUAL_CENTER -VM 'PowerCLIVM1', 'PowerCLIVM2' + +.EXAMPLE + Create new unmanaged manual pool from unmanaged VirtualMachines. + New-HVPool -MANUAL -PoolName 'unmangedVMWare' -PoolDisplayName 'unMngPl' -Description 'unmanaged Manual Pool creation' -UserAssignment FLOATING -Source UNMANAGED -VM 'myphysicalmachine.vmware.com' + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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 = $true,ParameterSetName = 'INSTANT_CLONE')] + [switch] + $InstantClone, + + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [switch] + $LinkedClone, + + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [switch] + $FullClone, + + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [switch] + $Manual, + + [Parameter(Mandatory = $true,ParameterSetName = 'RDS')] + [switch] + $Rds, + + [Parameter(Mandatory = $true,ParameterSetName = 'JSON_FILE')] + [string] + $Spec, + + [Parameter(Mandatory = $true,ValueFromPipeline = $true,ParameterSetName = 'CLONED_POOL')] + $ClonePool, + + #desktopSpec.desktopBase.name + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'RDS')] + [Parameter(Mandatory = $true,ParameterSetName = 'CLONED_POOL')] + [string] + $PoolName, + + #desktopSpec.desktopBase.displayName + [Parameter(Mandatory = $false)] + [string] + $PoolDisplayName = $poolName, + + #desktopSpec.desktopBase.description + [Parameter(Mandatory = $false)] + [string] + $Description = ' ', + + #desktopSpec.desktopBase.accessGroup + [Parameter(Mandatory = $false)] + [string] + $AccessGroup = 'Root', + + #desktopSpec.globalEntitlement + [Parameter(Mandatory = $false)] + [string] + $GlobalEntitlement, + + #desktopSpec.automatedDesktopSpec.desktopUserAssignment.userAssigment if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.manualDesktopSpec.desktopUserAssignment.userAssigment if MANUAL + + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [ValidateSet('FLOATING','DEDICATED')] + [string] + $UserAssignment, + + #desktopSpec.automatedDesktopSpec.desktopUserAssignment.automaticAssignment + [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [boolean] + $AutomaticAssignment = $true, + + #desktopSpec.desktopSettings.enabled + [Parameter(Mandatory = $false)] + [boolean] + $Enable = $true, + + #desktopSpec.desktopSettings.connectionServerRestrictions + [Parameter(Mandatory = $false)] + [string[]] + $ConnectionServerRestrictions, + + #desktopSpec.automatedDesktopSpec.virtualCenter if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #desktopSpec.manualDesktopSpec.virtualCenter if MANUAL + [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [string] + $Vcenter, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.template if FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string] + $Template, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVM if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [string] + $ParentVM, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshotVM if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [string] + $SnapshotVM, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string] + $VmFolder, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.hostOrCluster if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string] + $HostOrCluster, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.resourcePool if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string] + $ResourcePool, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [string[]] + $Datastores, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.useVSAN if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [string] + $UseVSAN, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [boolean] + $EnableProvisioning = $true, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [boolean] + $StopOnProvisioningError = $true, + + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] + [string] + $TransparentPageSharingScope = 'VM', + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.namingMethod if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] + [ValidateSet('SPECIFIED','PATTERN')] + [string] + $NamingMethod = 'PATTERN', + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.namingPattern if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] + [string] + $NamingPattern = $poolName + '{n:fixed=4}', + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [int] + $MinReady = 0, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.maxNumberOfMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [int] + $MaximumCount = 1, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.numberOfSpareMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [int] + $SpareCount = 1, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.provisioningTime if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [ValidateSet('ON_DEMAND','UP_FRONT')] + [string] + $ProvisioningTime = 'UP_FRONT', + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.patternNamingSettings.minimumNumberOfMachines if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [int] + $MinimumCount = 0, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.namingPattern if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] + [string[]] + $SpecificNames = $poolName + '-1', + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.startMachinesInMaintenanceMode if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [boolean] + $StartInMaintenanceMode = $false, + + #desktopSpec.automatedDesktopSpec.vmNamingSpec.specifiNamingSpec.numUnassignedMachinesKeptPoweredOnif LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = "JSON_FILE")] + [int] + $NumUnassignedMachinesKeptPoweredOn = 1, + + #desktopSpec.automatedDesktopSpec.customizationSettings.cloneprepCustomizationSettings.instantCloneEngineDomainAdministrator if INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + $AdContainer = 'CN=Computers', + + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [string]$NetBiosName, + + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string]$DomainAdmin = $null, + + #desktopSpec.automatedDesktopSpec.customizationSettings.customizationType if LINKED_CLONE, FULL_CLONE + [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = "FULL_CLONE")] + [ValidateSet('CLONE_PREP','QUICK_PREP','SYS_PREP','NONE')] + [string] + $CustType, + + #desktopSpec.automatedDesktopSpec.customizationSettings.sysprepCustomizationSettings.customizationSpec if LINKED_CLONE, FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = "FULL_CLONE")] + [string] + $SysPrepName, + + #manual desktop + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [ValidateSet('VIRTUAL_CENTER','UNMANAGED')] + [string] + $Source, + + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] + [Parameter(Mandatory = $false,ParameterSetName = "JSON_FILE")] + [string[]]$VM, + + #farm + [Parameter(Mandatory = $false,ParameterSetName = 'RDS')] + [string] + $Farm, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + # + # + # + # DesktopSpec/DesktopInfo + # *DesktopBase + # +AccessGroupId + # &DesktopSettings + # DesktopLogoffSettings + # DesktopDisplayProtocolSettings + # DesktopPCoIPDisplaySettings + # DesktopAdobeFlashSettings + # DesktopAdobeFlashSettings + # DesktopMirageConfigurationOverrides + # DesktopAutomatedDesktopSpec/DesktopAutomatedDesktopData + # */+VirtualCenterId + # DesktopUserAssignment + # DesktopVirtualMachineNamingSpec/DesktopVirtualMachineNamingSettings + # DesktopPatternNamingSpec/DesktopPatternNamingSettings + # DesktopSpecificNamingSettings/DesktopSpecificNamingSettings + # DesktopVirtualCenterProvisioningSettings + # DesktopVirtualCenterProvisioningData/virtualCenterProvisioningData + # DesktopVirtualCenterStorageSettings + # DesktopVirtualCenterNetworkingSettings + # DesktopVirtualCenterManagedCommonSettings + # DesktopCustomizationSettings + # ViewComposerDomainAdministratorId + # ADContainerId + # DesktopNoCustomizationSettings + # DesktopSysprepCustomizationSettings + # CustomizationSpecId + # DesktopQuickprepCustomizationSettings + # DesktopQuickprepCustomizationSettings + # DesktopCloneprepCustomizationSettings + # InstantCloneEngineDomainAdministratorId + # DesktopManualDesktopSpec + # DesktopUserAssignment + # MachineId[] + # VirtualCenterId + # DesktopViewStorageAcceleratorSettings + # DesktopBlackoutTime[] + # DesktopVirtualCenterManagedCommonSettings + # DesktopRDSDesktopSpec + # DesktopBlackoutTime[] + # DesktopGlobalEntitlementData + # GlobalEntitlementId + + + # retrieve values from the pipeline ... takes care of "get-hvpool -poolName | New-HVPool -poolName common parameters + # + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + + if ($poolName) { + try { + $sourcePool = Get-HVPool -poolName $poolName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($sourcePool) { + Write-Error "Pool with name: [$poolName] already exists" + break + } + } + + if ($spec) { + try { + $jsonObject = Get_Json_Object -specFile $spec + } catch { + Write-Error "Json file exception, $_" + break + } + if ($jsonObject.type -eq "AUTOMATED") { + $poolType = 'AUTOMATED' + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenter) { + $vCenter = $jsonObject.AutomatedDesktopSpec.VirtualCenter + } + $userAssignment = $jsonObject.AutomatedDesktopSpec.userAssignment.userAssignment + $automaticAssignment = $jsonObject.AutomatedDesktopSpec.userAssignment.AutomaticAssignment + $netBiosName = $jsonObject.NetBiosName + if (!$jsonObject.AutomatedDesktopSpec.CustomizationSettings.AdContainer) { + Write-Host "adContainer was empty using CN=Computers" + } else { + $adContainer = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.AdContainer + } + $custType = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CustomizationType + if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "INSTANT_CLONE_ENGINE") { + $InstantClone = $true + } else { + if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "VIEW_COMPOSER") { + $LinkedClone = $true + } else { + $FullClone = $true + } + $sysPrepName = $jsonObject.SysPrepName + } + $namingMethod = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.NamingMethod + $transparentPageSharingScope = $jsonObject.AutomatedDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope + if ($namingMethod -eq "PATTERN") { + $namingPattern = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.namingPattern + $maximumCount = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.maxNumberOfMachines + $spareCount = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.numberOfSpareMachines + $provisioningTime = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.provisioningTime + } else { + $specificNames = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.specifiedNames + $startInMaintenanceMode = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode + $numUnassignedMachinesKeptPoweredOn = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Template) { + $template = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Template + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm) { + $parentVM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot) { + $snapshotVM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot + } + $vmFolder = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.VmFolder + $hostOrCluster = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.HostOrCluster + $resourcePool = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ResourcePool + $dataStoreList = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores + foreach ($dtStore in $dataStoreList) { + $datastores += $dtStore.Datastore + } + } elseif ($jsonObject.type -eq "MANUAL") { + $MANUAL = $true + $poolType = 'MANUAL' + $userAssignment = $jsonObject.ManualDesktopSpec.userAssignment.userAssignment + $automaticAssignment = $jsonObject.ManualDesktopSpec.userAssignment.AutomaticAssignment + $source = $jsonObject.ManualDesktopSpec.source + $VMs = $jsonObject.ManualDesktopSpec.Machines + foreach ($vmObj in $VMs) { + $VM += $vmObj.Machine + } + + } else { + $RDS = $true + $poolType = 'RDS' + $farm = $jsonObject.RdsDesktopSpec.farm + } + $poolDisplayName = $jsonObject.base.DisplayName + $description = $jsonObject.base.Description + $accessGroup = $jsonObject.base.AccessGroup + $poolName = $jsonObject.base.name + } + + if ($PSCmdlet.MyInvocation.ExpectingInput -or $clonePool) { + + if ($clonePool -and ($clonePool.GetType().name -eq 'DesktopSummaryView')) { + $clonePool = Get-HVPool -poolName $clonePool.desktopsummarydata.name -Full + } else { + Write-Error "In pipeline did not get object of expected type DesktopSummaryView" + return + } + $poolType = $clonePool.type + $desktopBase = $clonePool.base + $desktopSettings = $clonePool.DesktopSettings + $provisioningType = $null + if ($clonePool.AutomatedDesktopData) { + $provisioningType = $clonePool.AutomatedDesktopData.ProvisioningType + $virtualCenterID = $clonePool.AutomatedDesktopData.VirtualCenter + $desktopUserAssignment = $clonePool.AutomatedDesktopData.userAssignment + $desktopVirtualMachineNamingSpec = $clonePool.AutomatedDesktopData.VmNamingSettings + $DesktopVirtualCenterProvisioningSettings = $clonePool.AutomatedDesktopData.VirtualCenterProvisioningSettings + $DesktopVirtualCenterProvisioningData = $DesktopVirtualCenterProvisioningSettings.VirtualCenterProvisioningData + $DesktopVirtualCenterStorageSettings = $DesktopVirtualCenterProvisioningSettings.VirtualCenterStorageSettings + $DesktopVirtualCenterNetworkingSettings = $DesktopVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings + $desktopVirtualCenterManagedCommonSettings = $clonePool.AutomatedDesktopData.virtualCenterManagedCommonSettings + $desktopCustomizationSettings = $clonePool.AutomatedDesktopData.CustomizationSettings + } + if (($null -eq $provisioningType) -or ($provisioningType -eq 'INSTANT_CLONE_ENGINE')) { + Write-Error "Only Automated linked clone or full clone pool support cloning" + break + } + } else { + + if ($InstantClone) { + $poolType = 'AUTOMATED' + $provisioningType = 'INSTANT_CLONE_ENGINE' + } + elseif ($LinkedClone) { + $poolType = 'AUTOMATED' + $provisioningType = 'VIEW_COMPOSER' + } + elseif ($FullClone) { + $poolType = 'AUTOMATED' + $provisioningType = 'VIRTUAL_CENTER' + } + elseif ($Manual) { $poolType = 'MANUAL' } + elseif ($RDS) { $poolType = 'RDS' } + + } + $script:desktopSpecObj = Get_Desktop_Spec -poolType $poolType -provisioningType $provisioningType -namingMethod $namingMethod + + # + # accumulate properties that are shared among various type + # + + if ($poolType -ne 'RDS') { + # + # vCenter: if $vcenterID is defined, then this is a clone + # if the user specificed the name, then find it from the list + # if none specified, then automatically use the vCenter if there is only one + # + # skips Unmanged Manual pool for VC check + if (! (($poolType -eq 'MANUAL') -and ($source -eq 'UNMANAGED'))) { + + if (!$virtualCenterID) { + $virtualCenterID = Get_Vcenter_ID -services $services -vCenter $vCenter + } + if ($null -eq $virtualCenterID) { + $handleException = $true + break + } + } + # + # populate user assignment + # + if (!$desktopUserAssignment) { + if ($desktopSpecObj.AutomatedDesktopSpec) { + $desktopSpecObj.AutomatedDesktopSpec.userAssignment.userAssignment = $userAssignment + $desktopSpecObj.AutomatedDesktopSpec.userAssignment.AutomaticAssignment = $automaticAssignment + $desktopUserAssignment = $desktopSpecObj.AutomatedDesktopSpec.userAssignment + } else { + $desktopSpecObj.ManualDesktopSpec.userAssignment.userAssignment = $userAssignment + $desktopSpecObj.ManualDesktopSpec.userAssignment.AutomaticAssignment = $automaticAssignment + $desktopUserAssignment = $desktopSpecObj.ManualDesktopSpec.userAssignment + } + + } + # + # transparentPageSharingScope + # + if (!$desktopVirtualCenterManagedCommonSettings) { + if ($desktopSpecObj.AutomatedDesktopSpec) { + $desktopSpecObj.AutomatedDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope + $desktopVirtualCenterManagedCommonSettings = $desktopSpecObj.AutomatedDesktopSpec.virtualCenterManagedCommonSettings + } else { + $desktopSpecObj.ManualDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope = $transparentPageSharingScope + $desktopVirtualCenterManagedCommonSettings = $desktopSpecObj.ManualDesktopSpec.virtualCenterManagedCommonSettings + } + } + } + # + # build out the infrastructure based on type of provisioning + # + switch ($poolType) + { + 'RDS' { + <# + Query FarmId from Farm Name + #> + $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals + $QueryFilterEquals.memberName = 'data.name' + $QueryFilterEquals.value = $farm + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'FarmSummaryView' + $defn.Filter = $QueryFilterEquals + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $queryResults = $query_service_helper.QueryService_Query($services,$defn) + if ($queryResults.results.Count -eq 0) { + Write-Error "No farm found with name: [$farm]" + return + } + $farmID = $queryResults.results.id + $desktopSpecObj.RdsDesktopSpec.farm = $farmID + } + 'MANUAL' { + [VMware.Hv.MachineId[]]$machineList = $null + $desktopSpecObj.ManualDesktopSpec.source = $source + if ($source -eq 'VIRTUAL_CENTER') { + # Get vCenter VMs + $vmTable = @{} + $vm | ForEach-Object { $vmTable[$_] = $_ } + $virtual_machine_helper = New-Object VMware.Hv.VirtualMachineService + $machineId = ($virtual_machine_helper.VirtualMachine_List($services,$virtualCenterId) | Where-Object { $vmTable.Contains($_.name) } | Select-Object -Property Id) + $machineList += $machineId.id + $desktopSpecObj.ManualDesktopSpec.VirtualCenter = $virtualCenterID + } else { + # Get Physical Regstered VMs + $machineList = Get-RegisteredPhysicalMachines -services $services -machinesList $VM + } + $desktopSpecObj.ManualDesktopSpec.Machines = $machineList + } + default { + if (!$desktopVirtualMachineNamingSpec) { + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.NamingMethod = $namingMethod + if ($namingMethod -eq 'PATTERN') { + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.namingPattern = $namingPattern + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.maxNumberOfMachines = $maximumCount + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.numberOfSpareMachines = $spareCount + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.provisioningTime = $provisioningTime + + if ($provisioningTime -eq 'ON_DEMAND') { $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.minNumberOfMachines = $minimumCount } + } else { + $desktopSpecifiedName = @() + $specificNames | ForEach-Object { $desktopSpecifiedName += New-Object VMware.Hv.DesktopSpecifiedName -Property @{ 'vmName' = $_; } } + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.specifiedNames = $desktopSpecifiedName + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode = $startInMaintenanceMode + $desktopSpecObj.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn = $numUnassignedMachinesKeptPoweredOn + } + } else { + $vmNamingSpec = New-Object VMware.Hv.DesktopVirtualMachineNamingSpec + if ($desktopVirtualMachineNamingSpec.NamingMethod -eq 'PATTERN') { + $vmNamingSpec.NamingMethod = 'PATTERN' + $vmNamingSpec.patternNamingSettings = $desktopVirtualMachineNamingSpec.patternNamingSettings + $vmNamingSpec.patternNamingSettings.namingPattern = $namingPattern + } else { + $desktopSpecifiedName = @() + $specificNames | ForEach-Object { $desktopSpecifiedName += New-Object VMware.Hv.DesktopSpecifiedName -Property @{ 'vmName' = $_; } } + $vmNamingSpec.NamingMethod = 'SPECIFIED' + $vmNamingSpec.SpecificNamingSpec = New-Object VMware.Hv.DesktopSpecificNamingSpec + $vmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn = $desktopVirtualMachineNamingSpec.specificNamingSettings.numUnassignedMachinesKeptPoweredOn + $vmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode = $desktopVirtualMachineNamingSpec.specificNamingSettings.startMachinesInMaintenanceMode + $vmNamingSpec.SpecificNamingSpec.specifiedNames = $desktopSpecifiedName + } + + } + + # + # build the VM LIST + # + $handleException = $false + try { + $desktopVirtualCenterProvisioningData = Build_VM_List -vc $virtualCenterID -vmObject $desktopVirtualCenterProvisioningData + $hostClusterId = $desktopVirtualCenterProvisioningData.HostOrCluster + $desktopVirtualCenterStorageSettings = Build_Datastore_List -hostclusterID $hostClusterId -storageObject $desktopVirtualCenterStorageSettings + $DesktopVirtualCenterNetworkingSettings = Build_Network_List -networkObject $DesktopVirtualCenterNetworkingSettings + $desktopCustomizationSettings = Build_Customization_Settings -vc $virtualCenterID -customObject $desktopCustomizationSettings + } catch { + $handleException = $true + Write-Error "Failed to create Pool with error: $_" + break + } + + if (!$DesktopVirtualCenterProvisioningSettings) { + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.enableProvisioning = $true + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $true + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = 0 + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings = $desktopCustomizationSettings + $desktopSpecObj.AutomatedDesktopSpec.ProvisioningType = $provisioningType + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenter = $virtualCenterID + } + else { + $DesktopVirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData + $DesktopVirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings + $DesktopVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings + + $DesktopAutomatedDesktopSpec = New-Object VMware.Hv.DesktopAutomatedDesktopSpec + $DesktopAutomatedDesktopSpec.ProvisioningType = $provisioningType + $DesktopAutomatedDesktopSpec.VirtualCenter = $virtualCenterID + $DesktopAutomatedDesktopSpec.userAssignment = $desktopUserAssignment + $DesktopAutomatedDesktopSpec.VmNamingSpec = $vmNamingSpec + $DesktopAutomatedDesktopSpec.VirtualCenterProvisioningSettings = $desktopVirtualCenterProvisioningSettings + $DesktopAutomatedDesktopSpec.virtualCenterManagedCommonSettings = $desktopVirtualCenterManagedCommonSettings + $DesktopAutomatedDesktopSpec.CustomizationSettings = $desktopCustomizationSettings + } + } + } + + if ($handleException) { + break + } + if (!$desktopBase) { + $accessGroup_client = New-Object VMware.Hv.AccessGroupService + $ag = $accessGroup_client.AccessGroup_List($services) | Where-Object { $_.base.name -eq $accessGroup } + $desktopSpecObj.base.AccessGroup = $ag.id + } else { + $desktopSpecObj.base = $desktopBase + } + + $desktopSpecObj.base.name = $poolName + $desktopSpecObj.base.DisplayName = $poolDisplayName + $desktopSpecObj.base.Description = $description + $desktopSpecObj.type = $poolType + + if ($desktopSettings) { $desktopSpecObj.DesktopSettings = $desktopSettings } + + if ($desktopAutomatedDesktopSpec) { + $desktopSpecObj.AutomatedDesktopSpec = $desktopAutomatedDesktopSpec + } + if ($DesktopManualDesktopSpecList) { $desktopSpecObj.ManualDesktopSpec = $DesktopManualDesktopSpecList } + if ($desktopRDSDesktopSpec) { $desktopSpecObj.RdsDesktopSpec = $RDSDesktopSpec } + if ($desktopGlobalEntitlementData) { $desktopSpecObj.GlobalEntitlementData = $desktopGlobalEntitlementData } + + # Please uncomment below code, if you want save desktopSpec object to json file + <# + $myDebug = convertto-json -InputObject $desktopSpecObj -depth 12 + $myDebug | out-file -filepath c:\temp\copieddesktop.json + #> + $desktop_helper = New-Object VMware.Hv.DesktopService + $desktop_helper.Desktop_create($services,$desktopSpecObj) + } + + end { + $desktopSpecObj = $null + [System.gc]::collect() + } + +} + +function Build_VM_List { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopVirtualCenterProvisioningData]$VmObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID + ) + if (!$vmObject) { $vmObject = $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData } + if ($template) { + $vm_template_helper = New-Object VMware.Hv.VmTemplateService + $templateList = $vm_template_helper.VmTemplate_List($services,$vcID) + $templateVM = $templateList | Where-Object { $_.name -eq $template } + if ($null -eq $templateVM) { + throw "No template VM found with Name: [$template]" + } + $vmObject.Template = $templateVM.id + $dataCenterID = $templateVM.datacenter + $vmObject.datacenter = $dataCenterID + } + if ($parentVM) { + $base_imageVm_helper = New-Object VMware.Hv.BaseImageVmService + $parentList = $base_imageVm_helper.BaseImageVm_List($services,$vcID) + $parentVmObj = $parentList | Where-Object { $_.name -eq $parentVM } + if ($null -eq $parentVMObj) { + throw "No parent VM found with Name: [$parentVM]" + } + $vmObject.ParentVm = $parentVmObj.id + $dataCenterID = $parentVmObj.datacenter + $vmObject.datacenter = $dataCenterID + } + if ($snapshotVM) { + $baseImageSnapshot_helper = New-Object VMware.Hv.BaseImageSnapshotService + $snapshotList = $baseImageSnapshot_helper.BaseImageSnapshot_List($services,$parentVmObj.id) + $snapshotVmObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } + if ($null -eq $snapshotVmObj) { + throw "No sanpshot found with Name: [$snapshotVM]" + } + $vmObject.Snapshot = $snapshotVmObj.id + } + if ($vmFolder) { + $vmFolder_helper = New-Object VMware.Hv.VmFolderService + $folders = $vmFolder_helper.VmFolder_GetVmFolderTree($services,$vmObject.datacenter) + $folderList = @() + $folderList += $folders + while ($folderList.Length -gt 0) { + $item = $folderList[0] + if ($item -and !$_.folderdata.incompatiblereasons.inuse -and !$_.folderdata.incompatiblereasons.viewcomposerreplicafolder -and ($item.folderdata.name -eq $vmFolder)) { + $vmObject.VmFolder = $item.id + break + } + foreach ($folderItem in $item.children) { + $folderList += $folderItem + } + $folderList = $folderList[1..$folderList.Length] + } + if ($null -eq $vmObject.VmFolder) { + throw "No vmfolder found with Name: [$vmFolder]" + } + } + if ($hostOrCluster) { + $vmFolder_helper = New-Object VMware.Hv.HostOrClusterService + $hostClusterList = ($vmFolder_helper.HostOrCluster_GetHostOrClusterTree($services,$vmobject.datacenter)).treeContainer.children.info + $hostClusterObj = $hostClusterList | Where-Object { $_.name -eq $hostOrCluster } + if ($null -eq $hostClusterObj) { + throw "No hostOrCluster found with Name: [$hostOrCluster]" + } + $vmObject.HostOrCluster = $hostClusterObj.id + } + if ($resourcePool) { + $resourcePool_helper = New-Object VMware.Hv.ResourcePoolService + $resourcePoolList = $resourcePool_helper.ResourcePool_GetResourcePoolTree($services,$vmobject.HostOrCluster) + $resourcePoolObj = $resourcePoolList | Where-Object { $_.resourcepooldata.name -eq $resourcePool } + if ($null -eq $resourcePoolObj) { + throw "No hostOrCluster found with Name: [$resourcePool]" + } + $vmObject.ResourcePool = $resourcePoolObj.id + } + return $vmObject +} + +function Build_Datastore_List { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopVirtualCenterStorageSettings]$StorageObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.HostOrClusterId]$HostClusterID + ) + if (!$storageObject) { + $storageObject = New-Object VMware.Hv.DesktopVirtualCenterStorageSettings + $storageAcceleratorList = @{ + 'useViewStorageAccelerator' = $false + } + $desktopViewStorageAcceleratorSettings = New-Object VMware.Hv.DesktopViewStorageAcceleratorSettings -Property $storageAcceleratorList + $storageObject.viewStorageAcceleratorSettings = $desktopViewStorageAcceleratorSettings + $desktopSpaceReclamationSettings = New-Object VMware.Hv.DesktopSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $false } + $desktopPersistentDiskSettings = New-Object VMware.Hv.DesktopPersistentDiskSettings -Property @{ 'redirectWindowsProfile' = $false } + $desktopNonPersistentDiskSettings = New-Object VMware.Hv.DesktopNonPersistentDiskSettings -Property @{ 'redirectDisposableFiles' = $false } + + $desktopViewComposerStorageSettingsList = @{ + 'useSeparateDatastoresReplicaAndOSDisks' = $false; + 'useNativeSnapshots' = $false; + 'spaceReclamationSettings' = $desktopSpaceReclamationSettings; + 'persistentDiskSettings' = $desktopPersistentDiskSettings; + 'nonPersistentDiskSettings' = $desktopNonPersistentDiskSettings + } + if (!$FullClone) { + $storageObject.ViewComposerStorageSettings = New-Object VMware.Hv.DesktopViewComposerStorageSettings -Property $desktopViewComposerStorageSettingsList + } + } + if ($datastores) { + $datastore_helper = New-Object VMware.Hv.DatastoreService + $datastoreList = $datastore_helper.Datastore_ListDatastoresByHostOrCluster($services,$hostClusterID) + $datastoresSelected = @() + foreach ($ds in $datastores) { + $datastoresSelected += ($datastoreList | Where-Object { $_.datastoredata.name -eq $ds }).id + } + foreach ($ds in $datastoresSelected) { + $myDatastores = New-Object VMware.Hv.DesktopVirtualCenterDatastoreSettings + $myDatastores.Datastore = $ds + $mydatastores.StorageOvercommit = 'UNBOUNDED' + $storageObject.Datastores += $myDatastores + } + } + if ($storageObject.Datastores.Count -eq 0) { + throw "No datastore found with Name: [$datastores]" + } + if ($useVSAN) { $storageObject.useVSAN = $useVSAN } + return $storageObject +} + +function Build_Network_List { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopVirtualCenterNetworkingSettings]$NetworkObject + ) + if (!$networkObject) { + $networkObject = $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings + } + return $networkObject +} + +function Build_Customization_Settings { + param( + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopCustomizationSettings]$CustomObject, + + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID + ) + if (!$customObject) { + # View Composer and Instant Clone Engine Active Directory container for QuickPrep and ClonePrep. This must be set for Instant Clone Engine or SVI sourced desktops. + if ($InstantClone -or $LinkedClone) { + $ad_domain_helper = New-Object VMware.Hv.ADDomainService + $adDomianId = ($ad_domain_helper.ADDomain_List($services) | Where-Object { $_.NetBiosName -eq $netBiosName } | Select-Object -Property id) + if ($null -eq $adDomianId) { + throw "No Domain found with netBiosName: [$netBiosName]" + } + $ad_container_helper = New-Object VMware.Hv.AdContainerService + $adContainerId = ($ad_container_helper.ADContainer_ListByDomain($services,$adDomianId.id) | Where-Object { $_.Rdn -eq $adContainer } | Select-Object -Property id).id + if ($null -eq $adContainerId) { + throw "No AdContainer found with name: [$adContainer]" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.AdContainer = $adContainerId + } + if ($InstantClone) { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'CLONE_PREP' + $instantCloneEngineDomainAdministrator_helper = New-Object VMware.Hv.InstantCloneEngineDomainAdministratorService + $instantCloneEngineDomainAdministrator = ($instantCloneEngineDomainAdministrator_helper.InstantCloneEngineDomainAdministrator_List($services) | Where-Object { $_.namesData.dnsName -match $netBiosName }) + if (![string]::IsNullOrWhitespace($domainAdmin)) { + $instantCloneEngineDomainAdministrator = ($instantCloneEngineDomainAdministrator | Where-Object { $_.base.userName -eq $domainAdmin }).id + } else { + $instantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator[0].id + } + if ($null -eq $instantCloneEngineDomainAdministrator) { + throw "No Instant Clone Engine Domain Administrator found with netBiosName: [$netBiosName]" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings = Get_CustomizationSettings_Objects + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator + } + else { + if ($LinkedClone) { + $viewComposerDomainAdministrator_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService + $ViewComposerDomainAdministratorID = ($viewComposerDomainAdministrator_helper.ViewComposerDomainAdministrator_List($services,$vcID) | Where-Object { $_.base.domain -match $netBiosName }) + if (![string]::IsNullOrWhitespace($domainAdmin)) { + $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministratorID | Where-Object { $_.base.userName -ieq $domainAdmin }).id + } else { + $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id + } + if ($null -eq $ViewComposerDomainAdministratorID) { + throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" + } + if ($custType -eq 'SYS_PREP') { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings = Get_CustomizationSettings_Objects + + # Get SysPrep CustomizationSpec ID + $customization_spec_helper = New-Object VMware.Hv.CustomizationSpecService + $sysPrepIds = $customization_spec_helper.CustomizationSpec_List($services,$vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id + if ($sysPrepIds.Count -eq 0) { + throw "No Sysprep Customization Spec found with Name: [$sysPrepName]" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id + } elseif ($custType -eq 'QUICK_PREP') { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'QUICK_PREP' + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings = Get_CustomizationSettings_Objects + } else { + throw "The customization type: [$custType] is not supported for LinkedClone Pool" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.DomainAdministrator = $ViewComposerDomainAdministratorID + } elseif ($FullClone) { + if ($custType -eq 'SYS_PREP') { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings = Get_CustomizationSettings_Objects + # Get SysPrep CustomizationSpec ID + $customization_spec_helper = New-Object VMware.Hv.CustomizationSpecService + $sysPrepIds = $customization_spec_helper.CustomizationSpec_List($services,$vcID) | Where-Object { $_.customizationSpecData.name -eq $sysPrepName } | Select-Object -Property id + if ($sysPrepIds.Count -eq 0) { + throw "No Sysprep Customization Spec found with Name: [$sysPrepName]" + } + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id + } elseif ($custType -eq 'NONE') { + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings = Get_CustomizationSettings_Objects + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings.DoNotPowerOnVMsAfterCreation = $false + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = "NONE" + } else { + throw "The customization type: [$custType] is not supported for FullClone Pool." + } + } + } + $customObject = $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings + } + return $customObject +} + +function Get_CustomizationSettings_Objects { + if ($InstantClone) { + return New-Object VMware.Hv.DesktopCloneprepCustomizationSettings + } elseif ($LinkedClone) { + if ($custType -eq 'QUICK_PREP') { + return New-Object VMware.Hv.DesktopQuickPrepCustomizationSettings + } else { + return New-Object VMware.Hv.DesktopSysPrepCustomizationSettings + } + } else { + if ($custType -eq 'SYS_PREP') { + return New-Object VMware.Hv.DesktopSysPrepCustomizationSettings + } else { + return New-Object VMware.Hv.DesktopNoCustomizationSettings + } + } +} + +function Get_Desktop_Spec { + + param( + [Parameter(Mandatory = $true)] + [string]$PoolType, + + [Parameter(Mandatory = $false)] + [string]$ProvisioningType, + + [Parameter(Mandatory = $false)] + [string]$NamingMethod + ) + $desktop_helper = New-Object VMware.Hv.DesktopService + $desktop_spec_helper = $desktop_helper.getDesktopSpecHelper() + $desktop_spec_helper.setType($poolType) + if ($poolType -eq $desktop_spec_helper.TYPE_AUTOMATED) { + if ($namingMethod -eq 'PATTERN') { + $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings = $desktop_helper.getDesktopPatternNamingSettingsHelper().getDataObject() + } else { + $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec = $desktop_helper.getDesktopSpecificNamingSpecHelper().getDataObject() + } + if ($provisioningType -ne 'VIRTUAL_CENTER') { + $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings = $desktop_helper.getDesktopViewComposerStorageSettingsHelper().getDataObject() + } + } elseif ($poolType -eq 'MANUAL') { + $desktop_spec_helper.getDataObject().ManualDesktopSpec.userAssignment = $desktop_helper.getDesktopUserAssignmentHelper().getDataObject() + $desktop_spec_helper.getDataObject().ManualDesktopSpec.viewStorageAcceleratorSettings = $desktop_helper.getDesktopViewStorageAcceleratorSettingsHelper().getDataObject() + $desktop_spec_helper.getDataObject().ManualDesktopSpec.virtualCenterManagedCommonSettings = $desktop_helper.getDesktopVirtualCenterManagedCommonSettingsHelper().getDataObject() + } else { + $desktop_spec_helper.getDataObject().RdsDesktopSpec = $desktop_helper.getDesktopRDSDesktopSpecHelper().getDataObject() + } + return $desktop_spec_helper.getDataObject() + +} + +function Remove-HVFarm { +<# +.SYNOPSIS + Deletes specified farm(s). + +.DESCRIPTION + This function deletes the farm(s) with the specified name/object(s) from the Connection Server. Optionally, user can pipe the farm object(s) as input to this function. + +.PARAMETER FarmName + Name of the farm to be deleted. + +.PARAMETER Farm + Object(s) of the farm to be deleted. Object(s) should be of type FarmSummaryView/FarmInfo. + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Remove-HVFarm -FarmName 'Farm-01' -HvServer $hvServer + +.EXAMPLE + $farm_array | Remove-HVFarm -HvServer $hvServer + +.EXAMPLE + $farm1 = Get-HVFarm -FarmName 'Farm-01' + Remove-HVFarm -Farm $farm1 + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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 = $true,ParameterSetName = 'option')] + [string] + [ValidateNotNullOrEmpty()] $FarmName, + + # Farmobject + [Parameter(ValueFromPipeline = $true,Mandatory = $true,ParameterSetName = 'pipeline')] + [ValidateNotNullOrEmpty()] $Farm, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $farmList = @() + if ($farmName) { + try { + $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($farmSpecObj) { + foreach ($farmObj in $farmSpecObj) { + $farmList += $farmObj.id + } + } else { + Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farmName]" + break + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + foreach ($item in $farm) { + if ($item.GetType().name -eq 'FarmInfo' -or $item.GetType().name -eq 'FarmSummaryView') { + $farmList += $item.id + } + else { + Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" + [System.gc]::collect() + return + } + } + } + $farm_service_helper = New-Object VMware.Hv.FarmService + foreach ($item in $farmList) { + $farm_service_helper.Farm_Delete($services, $item) + } + Write-Host "Farm Deleted" + + } + end { + [System.gc]::collect() + } +} + +function Remove-HVPool { +<# +.SYNOPSIS + Deletes specified pool(s). + +.DESCRIPTION + This function deletes the pool(s) with the specified name/object(s) from Connection Server. This can be used for deleting any pool irrespective of its type. + Optionally, user can pipe the pool object(s) as input to this function. + +.PARAMETER PoolName + Name of the pool to be deleted. + +.PARAMETER Pool + Object(s) of the pool to be deleted. + +.PARAMETER DeleteFromDisk + Switch parameter to delete the virtual machine(s) from the disk. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER TerminateSession + Logs off a session forcibly to virtual machine(s). This operation will also log off a locked session. + +.EXAMPLE + Remove-HVPool -HvServer $hvServer -PoolName 'FullClone' -DeleteFromDisk + +.EXAMPLE + $pool_array | Remove-HVPool -HvServer $hvServer -DeleteFromDisk + +.EXAMPLE + Remove-HVPool -Pool $pool1 + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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,ParameterSetName = 'option')] + [string] $poolName, + + # PoolObject + [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] + $Pool, + + [Parameter(Mandatory = $false)] + [switch] $TerminateSession = $false, + + [Parameter(Mandatory = $false)] + [switch] $DeleteFromDisk, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $poolList = @() + if ($poolName) { + try { + $myPools = get-hvpool -poolName $poolName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($myPools) { + foreach ($poolObj in $myPools) { + $poolList += $poolObj.id + } + } else { + Write-Error "No desktopsummarydata found with pool name: [$pool]" + break + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + foreach ($item in $pool) { + if (($item.GetType().name -eq 'DesktopInfo') -or ($item.GetType().name -eq 'DesktopSummaryView')) { + $poolList += $item.id + } + else { + Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" + [System.gc]::collect() + return + } + } + } + $desktop_service_helper = New-Object VMware.Hv.DesktopService + $deleteSpec = New-Object VMware.Hv.DesktopDeleteSpec + $deleteSpec.DeleteFromDisk = $deleteFromDisk + foreach ($item in $poolList) { + if ($terminateSession) { + #Terminate session + $queryResults = Get-HVQueryResults MachineSummaryView (Get-HVQueryFilter base.desktop -eq $item) + $sessions += $queryResults.base.session + + if ($null -ne $sessions) { + $session_service_helper = New-Object VMware.Hv.SessionService + try { + Write-Host "Terminating Sessions, it may take few seconds..." + $session_service_helper.Session_LogoffSessionsForced($services,$sessions) + } catch { + Write-Host "Warning: Terminate Session failed." + } + } else { + Write-Host "No session found." + } + } + Write-Host "Deleting Pool" + $desktop_service_helper.Desktop_Delete($services,$item,$deleteSpec) + } + } + + end { + [System.gc]::collect() + } +} + +function Set-HVFarm { +<# +.SYNOPSIS + Edit farm configuration by passing key/values as parameters/json. + +.DESCRIPTION + This function allows user to edit farm configuration by passing key/value pairs. Optionally, user can pass a JSON spec file. User can also pipe the farm object(s) as input to this function. + +.PARAMETER FarmName + Name of the farm to edit. + +.PARAMETER Farm + Object(s) of the farm to edit. Object(s) should be of type FarmSummaryView/FarmInfo. + +.PARAMETER Key + Property names path separated by . (dot) from the root of desktop spec. + +.PARAMETER Value + Property value corresponds to above key name. + +.PARAMETER Spec + Path of the JSON specification file containing key/value pair. + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Set-HVFarm -FarmName 'Farm-o1' -Spec 'C:\Edit-HVFarm\ManualEditFarm.json' + +.EXAMPLE + Set-HVFarm -FarmName 'Farm-o1' -Key 'base.description' -Value 'updated description' + +.EXAMPLE + $farm_array | Set-HVFarm -Key 'base.description' -Value 'updated description' + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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,ParameterSetName = 'option')] + [string]$FarmName, + + [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] + $Farm, + + [Parameter(Mandatory = $false)] + [string]$Key, + + [Parameter(Mandatory = $false)] + $Value, + + [Parameter(Mandatory = $false)] + [string]$Spec, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $farmList = @() + if ($farmName) { + try { + $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($farmSpecObj) { + foreach ($farmObj in $farmSpecObj) { + $farmList += $farmObj.id + } + } else { + Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farmName]" + break + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + foreach ($item in $farm) { + if ($item.GetType().name -eq 'FarmInfo' -or $item.GetType().name -eq 'FarmSummaryView') { + $farmList += $item.id + } + else { + Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" + [System.gc]::collect() + return + } + } + } + + $updates = @() + if ($key -and $value) { + $updates += Get_MapEntry -key $key -value $value + } elseif ($key -or $value) { + Write-Error "Both key:[$key] and value:[$value] need to be specified" + } + if ($spec) { + $specObject = Get_Json_Object -specFile $spec + foreach ($member in ($specObject.PSObject.Members | Where-Object { $_.MemberType -eq 'NoteProperty' })) { + $updates += Get_MapEntry -key $member.name -value $member.value + } + } + $farm_service_helper = New-Object VMware.Hv.FarmService + foreach ($item in $farmList) { + $farm_service_helper.Farm_Update($services,$item,$updates) + } + } + + end { + $updates = $null + [System.gc]::collect() + } +} + +function Set-HVPool { +<# +.SYNOPSIS + Sets the existing pool properties. + +.DESCRIPTION + This cmdlet allows user to edit pool configuration by passing key/value pair. Optionally, user can pass a JSON spec file. + +.PARAMETER PoolName + Name of the pool to edit. + +.PARAMETER Pool + Object(s) of the pool to edit. + +.PARAMETER Key + Property names path separated by . (dot) from the root of desktop spec. + +.PARAMETER Value + Property value corresponds to above key name. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.PARAMETER Spec + Path of the JSON specification file containing key/value pair. + +.EXAMPLE + Set-HVPool -PoolName 'ManualPool' -Spec 'C:\Edit-HVPool\EditPool.json' + +.EXAMPLE + Set-HVPool -PoolName 'RDSPool' -Key 'base.description' -Value 'update description' + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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,ParameterSetName = 'option')] + [string]$PoolName, + + #pool object + [Parameter(ValueFromPipeline = $true,ParameterSetName = 'pipeline')] + $Pool, + + [Parameter(Mandatory = $false)] + [string]$Key, + + [Parameter(Mandatory = $false)] + $Value, + + [Parameter(Mandatory = $false)] + [string]$Spec, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $poolList = @() + if ($poolName) { + try { + $desktopPools = Get-HVPool -poolName $poolName -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($desktopPools) { $poolList += $desktopPools.id } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + foreach ($item in $pool) { + if (($item.GetType().name -eq 'DesktopInfo') -or ($item.GetType().name -eq 'DesktopSummaryView')) { + $poolList += $item.id + } + else { + Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" + [System.gc]::collect() + return + } + } + } + $updates = @() + if ($key -and $value) { + $updates += Get_MapEntry -key $key -value $value + } elseif ($key -or $value) { + Write-Error "Both key:[$key] and value:[$value] needs to be specified" + } + if ($spec) { + try { + $specObject = Get_Json_Object -specFile $spec + } catch { + Write-Error "Json file exception, $_" + return + } + foreach ($member in ($specObject.PSObject.Members | Where-Object { $_.MemberType -eq 'NoteProperty' })) { + $updates += Get_MapEntry -key $member.name -value $member.value + } + } + + $desktop_helper = New-Object VMware.Hv.DesktopService + foreach ($item in $poolList) { + $desktop_helper.Desktop_Update($services,$item,$updates) + } + } + + end { + [System.gc]::collect() + } +} + +function Start-HVFarm { +<# +.SYNOPSIS + Perform maintenance tasks on the farm(s). + +.DESCRIPTION + This function is used to perform maintenance tasks like enable/disable, start/stop and recompose the farm. + +.PARAMETER Farm + Name/Object(s) of the farm. Object(s) should be of type FarmSummaryView/FarmInfo. + +.PARAMETER Enable + Switch to enable the farm(s). + +.PARAMETER Disable + Switch to disable the farm(s). + +.PARAMETER Start + Switch to enable provisioning immediately for the farm(s). It's applicable only for 'AUTOMATED' farm type. + +.PARAMETER Stop + Switch to disable provisioning immediately for the farm(s). It's applicable only for 'AUTOMATED' farm type. + +.PARAMETER Recompose + Switch for recompose operation. Requests a recompose of RDS Servers in the specified 'AUTOMATED' farm. This marks the RDS Servers for recompose, which is performed asynchronously. + +.PARAMETER StartTime + Specifies when to start the operation. If unset, the operation will begin immediately. + +.PARAMETER LogoffSetting + Determines when to perform the operation on machines which have an active session. This property will be one of: + "FORCE_LOGOFF" - Users will be forced to log off when the system is ready to operate on their RDS Servers. Before being forcibly logged off, users may have a grace period in which to save their work (Global Settings). + "WAIT_FOR_LOGOFF" - Wait for connected users to disconnect before the task starts. The operation starts immediately on RDS Servers without active sessions. + +.PARAMETER StopOnFirstError + Indicates that the operation should stop on first error. + +.PARAMETER Servers + The RDS Server(s) id to recompose. Provide a comma separated list for multiple RDSServerIds. + +.PARAMETER ParentVM + New base image VM for automated farm's RDS Servers. This must be in the same datacenter as the base image of the RDS Server. + +.PARAMETER SnapshotVM + Base image snapshot for the Automated Farm's RDS Servers. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) of the given farm. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER HvServer + Reference to Horizon View Server to query the data from. If the value is not passed or null then first element from global:DefaultHVServers would be considered inplace of hvServer. + +.EXAMPLE + Start-HVFarm -Recompose -Farm 'Farm-01' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' + +.EXAMPLE + Start-HVFarm -Farm 'Farm-01' -Enable + +.EXAMPLE + Start-HVFarm -Farm 'Farm-01' -Disable + +.EXAMPLE + Start-HVFarm -Farm 'Farm-01' -Start + +.EXAMPLE + Start-HVFarm -Farm 'Farm-01' -Stop + +.EXAMPLE + $myTime = Get-Date '10/03/2016 12:30:00' + Start-HVFarm -Farm 'Farm-01' -Recompose -LogoffSetting 'FORCE_LOGOFF' -ParentVM 'ParentVM' -SnapshotVM 'SnapshotVM' -StartTime $myTime + +.OUTPUTS + None + +.NOTES + Author : Ankit Gupta. + Author email : guptaa@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 = $true,ValueFromPipeline = $true)] + $Farm, + + [Parameter(Mandatory = $false,ParameterSetName = 'ENABLE')] + [switch]$Enable, + + [Parameter(Mandatory = $false,ParameterSetName = 'DISABLE')] + [switch]$Disable, + + [Parameter(Mandatory = $false,ParameterSetName = 'START')] + [switch]$Start, + + [Parameter(Mandatory = $false,ParameterSetName = 'STOP')] + [switch]$Stop, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [switch]$Recompose, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [System.DateTime]$StartTime, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [ValidateSet('FORCE_LOGOFF','WAIT_FOR_LOGOFF')] + [string]$LogoffSetting, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [boolean]$StopOnFirstError = $true, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [string []]$Servers, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [string]$ParentVM, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [string]$SnapshotVM, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [string]$Vcenter, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $farmList = @{} + $farmType = @{} + $farmSource = @{} + $farm_service_helper = New-Object VMware.Hv.FarmService + if ($farm) { + if ($farm.GetType().name -eq 'FarmInfo') { + $id = $farm.id + $name = $farm.data.name + $type = $farm.type + } + elseif ($farm.GetType().name -eq 'FarmSummaryView') { + $id = $farm.id + $name = $farm.data.name + $type = $farm.data.type + } + elseif ($farm.GetType().name -eq 'String') { + try { + $farmSpecObj = Get-HVFarm -farmName $farm -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + break + } + if ($farmSpecObj) { + $id = $farmSpecObj.id + $name = $farmSpecObj.data.name + $type = $farmSpecObj.data.type + } else { + Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farm]" + break + } + } else { + Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" + break + } + if ($type -eq 'AUTOMATED') { + $source = 'VIEW_COMPOSER' + } + $farmList.Add($id,$name) + $farmType.Add($id,$type) + $farmSource.Add($id,$source) + } + } + + + end { + foreach ($item in $farmList.Keys) { + $operation = $PsCmdlet.ParameterSetName + Write-Host "Performing $operation" on $farmList.$item + switch ($operation) { + 'RECOMPOSE' { + if ($farmSource.$item -ne 'VIEW_COMPOSER') { + Write-Error "RECOMPOSE operation is not supported for farm with name [$farmList.$item]" + break + } else { + $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter + if ($null -eq $vcId) { + break + } + $serverList = Get-AllRDSServersInFarm -services $services -farm $item -serverList $servers + if ($null -eq $serverList) { + Write-Error "No servers found for the farm [$item]" + } + $spec = New-Object VMware.Hv.FarmRecomposeSpec + $spec.LogoffSetting = $logoffSetting + $spec.StopOnFirstError = $stopOnFirstError + $spec.RdsServers = $serverList + try { + $spec = Set_Spec_Vms_Farm -vcId $vcId -spec $spec + } catch { + Write-Error "RECOMPOSE task failed with error: $_" + break + } + if ($startTime) { $spec.startTime = $startTime } + # Update Base Image VM and Snapshot in Farm + $updates = @() + $updates += Get_MapEntry -key 'automatedFarmData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVm' -value $spec.ParentVM + $updates += Get_MapEntry -key 'automatedFarmData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshot' -value $spec.Snapshot + $farm_service_helper.Farm_Update($services,$item,$updates) + + $farm_service_helper.Farm_Recompose($services,$item,$spec) + } + } + 'ENABLE' { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'data.enabled' + $map.value = $true + $farm_service_helper.Farm_Update($services,$item,$map) + } + 'DISABLE' { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'data.enabled' + $map.value = $false + $farm_service_helper.Farm_Update($services,$item,$map) + } + 'START' { + if ($farmType.$item -ne 'AUTOMATED') { + Write-Error "Start operation is not supported for farm with name [$farmList.$item]" + break + } else { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'automatedFarmData.virtualCenterProvisioningSettings.enableProvisioning' + $map.value = $true + $farm_service_helper.Farm_Update($services,$item,$map) + } + } + 'STOP' { + if ($farmType.$item -ne 'AUTOMATED') { + Write-Error "STOP operation is not supported for farm with name [$farmList.$item]" + break + } else { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'automatedFarmData.virtualCenterProvisioningSettings.enableProvisioning' + $map.value = $false + $farm_service_helper.Farm_Update($services,$item,$map) + } + } + } + return + } + } + +} + +function Get-AllRDSServersInFarm ($Services,$Farm,$ServerList) { + [VMware.Hv.RDSServerId[]]$servers = @() + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $remainingCount = 1 # run through loop at least once + $query = New-Object VMware.Hv.QueryDefinition + $query.queryEntityType = 'RDSServerSummaryView' + $farmFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'MemberName' = 'base.farm'; 'value' = $farm } + if ($serverList) { + $serverFilters = [VMware.Hv.queryFilter[]]@() + foreach ($name in $serverList) { + $serverFilters += (New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $name }) + } + $serverList = New-Object VMware.Hv.QueryFilterOr -Property @{ 'filters' = $serverFilters } + $treeList = @() + $treeList += $serverList + $treelist += $farmFilter + $query.Filter = New-Object VMware.Hv.QueryFilterAnd -Property @{ 'filters' = $treeList } + } else { + $query.Filter = $farmFilter + } + while ($remainingCount -ge 1) { + $queryResults = $query_service_helper.QueryService_Query($services,$query) + $results = $queryResults.results + $servers += $results.id + $query.StartingOffset = $query.StartingOffset + $queryResults.results.Count + $remainingCount = $queryResults.RemainingCount + } + return $servers +} + +function Set_Spec_Vms_Farm { + param( + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID, + + [Parameter(Mandatory = $true)] + $Spec + ) + if ($parentVM) { + $baseImage_service_helper = New-Object VMware.Hv.BaseImageVmService + $parentList = $baseImage_service_helper.BaseImageVm_List($services, $vcID) + $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } + if ($null -eq $parentVMObj) { + throw "No Parent VM found with name: [$parentVM]" + } + $spec.ParentVm = $parentVMObj.id + } + if ($snapshotVM) { + $parentVM = $spec.ParentVm.id + $baseImageSnapshot_service_helper = New-Object VMware.Hv.BaseImageSnapshotService + $snapshotList = $baseImageSnapshot_service_helper.BaseImageSnapshot_List($services, $spec.ParentVm) + $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } + if ($null -eq $snapshotVMObj) { + throw "No Snapshot found with name: [$snapshotVM] for VM name: [$parentVM] " + } + $spec.Snapshot = $snapshotVMObj.id + } + return $spec +} + +function Start-HVPool { +<# +.SYNOPSIS + Perform maintenance tasks on Pool. + +.DESCRIPTION + This cmdlet is used to perform maintenance tasks like enable/disable the pool, enable/disable the provisioning of a pool, refresh, rebalance, recompose, push image and cancel image. Push image and Cancel image tasks only applies for instant clone pool. + +.PARAMETER Pool + Name/Object(s) of the pool. + +.PARAMETER Enable + Switch parameter to enable the pool. + +.PARAMETER Disable + Switch parameter to disable the pool. + +.PARAMETER Start + Switch parameter to start the pool. + +.PARAMETER Stop + Switch parameter to stop the pool. + +.PARAMETER Refresh + Switch parameter to refresh operation. + +.PARAMETER Recompose + Switch parameter to recompose operation. + +.PARAMETER Rebalance + Switch parameter to rebalance operation. + +.PARAMETER SchedulePushImage + Switch parameter to push image operation. + +.PARAMETER CancelPushImage + Switch parameter to cancel push image operation. + +.PARAMETER StartTime + Specifies when to start the operation. If unset, the operation will begin immediately. + +.PARAMETER LogoffSetting + Determines when to perform the operation on machines which have an active session. This property will be one of: + 'FORCE_LOGOFF' - Users will be forced to log off when the system is ready to operate on their virtual machines. + 'WAIT_FOR_LOGOFF' - Wait for connected users to disconnect before the task starts. The operation starts immediately on machines without active sessions. + +.PARAMETER StopOnFirstError + Indicates that the operation should stop on first error. + +.PARAMETER Machines + The machine names to recompose. These must be associated with the pool. + +.PARAMETER ParentVM + New base image VM for the desktop. This must be in the same datacenter as the base image of the desktop. + +.PARAMETER SnapshotVM + Name of the snapshot used in pool deployment. + +.PARAMETER Vcenter + Virtual Center server-address (IP or FQDN) of the given pool. This should be same as provided to the Connection Server while adding the vCenter server. + +.PARAMETER HvServer + View API service object of Connect-HVServer cmdlet. + +.EXAMPLE + Start-HVPool -Recompose -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' + +.EXAMPLE + Start-HVPool -Refresh -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF + +.EXAMPLE + $myTime = Get-Date '10/03/2016 12:30:00' + Start-HVPool -Eebalance -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -StartTime $myTime + +.EXAMPLE + Start-HVPool -SchedulePushImage -Pool 'InstantPool' -LogoffSetting FORCE_LOGOFF -ParentVM 'InsParentVM' -SnapshotVM 'InsSnapshotVM' + +.EXAMPLE + Start-HVPool -CancelPushImage -Pool 'InstantPool' + +.EXAMPLE + Start-HVPool -Pool 'TestPool' -Enable + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@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( + # handles both objects and string + [Parameter(Mandatory = $true,ValueFromPipeline = $true)] + $Pool, + + [Parameter(Mandatory = $false,ParameterSetName = 'ENABLE')] + [switch]$Enable, + + [Parameter(Mandatory = $false,ParameterSetName = 'DISABLE')] + [switch]$Disable, + + [Parameter(Mandatory = $false,ParameterSetName = 'START')] + [switch]$Start, + + [Parameter(Mandatory = $false,ParameterSetName = 'STOP')] + [switch]$Stop, + + [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] + [switch]$Refresh, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [switch]$Recompose, + + [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] + [switch]$Rebalance, + + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [switch]$SchedulePushImage, + + [Parameter(Mandatory = $false,ParameterSetName = 'CANCEL_PUSH_IMAGE')] + [switch]$CancelPushImage, + + [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [System.DateTime]$StartTime, + + [Parameter(Mandatory = $true,ParameterSetName = 'REBALANCE')] + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $true,ParameterSetName = 'REFRESH')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [ValidateSet('FORCE_LOGOFF','WAIT_FOR_LOGOFF')] + [string]$LogoffSetting, + + [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [boolean]$StopOnFirstError = $true, + + [Parameter(Mandatory = $false,ParameterSetName = 'REBALANCE')] + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'REFRESH')] + [string []]$Machines, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [string]$ParentVM, + + [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [string]$SnapshotVM, + + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'PUSH_IMAGE')] + [string]$Vcenter, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + + begin { + $services = Get_ViewAPI_Service -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + + $poolList = @{} + $poolType = @{} + $poolSource = @{} + if ($pool) { + foreach ($item in $pool) { + if ($item.GetType().name -eq 'DesktopInfo') { + $id = $item.id + $name = $item.base.name + $source = $item.source + $type = $item.type + } elseif ($item.GetType().name -eq 'DesktopSummaryView') { + $id = $item.id + $name = $item.desktopsummarydata.name + $source = $item.desktopsummarydata.source + $type = $item.desktopsummarydata.type + } elseif ($item.GetType().name -eq 'String') { + try { + $poolObj = Get-HVPool -poolName $item -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVPool advanced function is loaded, $_" + break + } + if ($poolObj) { + $id = $poolObj.id + $name = $poolObj.desktopsummarydata.name + $source = $poolObj.desktopsummarydata.source + $type = $poolObj.desktopsummarydata.type + } else { + Write-Error "No desktopsummarydata found with pool name: [$item]" + break + } + } else { + Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" + break + } + $poolList.Add($id,$name) + $poolType.Add($id,$type) + $poolSource.Add($id,$source) + } + } + } + + end { + foreach ($item in $poolList.Keys) { + $operation = $PsCmdlet.ParameterSetName + Write-Host "Performing $operation on" $poolList.$item + $desktop_helper = New-Object VMware.Hv.DesktopService + switch ($operation) { + 'REBALANCE' { + $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRebalanceSpec' -desktopId $item + if ($null -ne $spec) { + # make sure current task on VMs, must be None + $desktop_helper.Desktop_Rebalance($services,$item,$spec) + } + } + 'REFRESH' { + $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRefreshSpec' -desktopId $item + if ($null -ne $spec) { + # make sure current task on VMs, must be None + $desktop_helper.Desktop_Refresh($services,$item,$spec) + } + } + 'RECOMPOSE' { + $spec = Get_TaskSpec -Source $poolSource.$item -poolName $poolList.$item -operation $operation -taskSpecName 'DesktopRecomposeSpec' -desktopId $item + if ($null -ne $spec) { + $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter + $spec = Set_Spec_Vms -vcId $vcId -spec $spec + + # make sure current task on VMs, must be None + $desktop_helper.Desktop_Recompose($services,$item,$spec) + + # Update Base Image VM and Snapshot in Pool + $updates = @() + $updates += Get_MapEntry -key 'automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVm' -value $spec.ParentVM + $updates += Get_MapEntry -key 'automatedDesktopData.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshot' -value $spec.Snapshot + $desktop_helper.Desktop_Update($services,$item,$updates) + + } + } + 'PUSH_IMAGE' { + if ($poolSource.$item -ne 'INSTANT_CLONE_ENGINE') { + Write-Error "$poolList.$item is not a INSTANT CLONE pool" + break + } else { + $spec = New-Object VMware.Hv.DesktopPushImageSpec + $vcId = Get_Vcenter_ID -services $services -vCenter $vCenter + $spec = Set_Spec_Vms -vcId $vcId -spec $spec + $spec.Settings = New-Object VMware.Hv.DesktopPushImageSettings + $spec.Settings.LogoffSetting = $logoffSetting + $spec.Settings.StopOnFirstError = $stopOnFirstError + if ($startTime) { $spec.Settings.startTime = $startTime } + $desktop_helper.Desktop_SchedulePushImage($services,$item,$spec) + } + } + 'CANCEL_PUSH_IMAGE' { + if ($poolSource.$item -ne 'INSTANT_CLONE_ENGINE') { + Write-Error "$poolList.$item is not a INSTANT CLONE pool" + break + } else { + $desktop_helper.Desktop_CancelScheduledPushImage($services,$item) + } + } + 'ENABLE' { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'desktopSettings.enabled' + $map.value = $true + $desktop_helper.Desktop_Update($services,$item,$map) + } + 'DISABLE' { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'desktopSettings.enabled' + $map.value = $false + $desktop_helper.Desktop_Update($services,$item,$map) + } + 'START' { + if ($poolType.$item -ne 'Automated') { + Write-Error "$poolList.$item is not a Automated pool" + break + } else { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'automatedDesktopData.virtualCenterProvisioningSettings.enableProvisioning' + $map.value = $true + $desktop_helper.Desktop_Update($services,$item,$map) + } + } + 'STOP' { + if ($poolType.$item -ne 'Automated') { + Write-Error "$poolList.$item is not a Automated pool" + break + } else { + $map = New-Object VMware.Hv.MapEntry + $map.key = 'automatedDesktopData.virtualCenterProvisioningSettings.enableProvisioning' + $map.value = $false + $desktop_helper.Desktop_Update($services,$item,$map) + } + } + } + } + } +} + +function Get-Machines ($Pool,$MachineList) { + [VMware.Hv.MachineId[]]$machines = @() + $remainingCount = 1 # run through loop at least once + $query = New-Object VMware.Hv.QueryDefinition + $query.queryEntityType = 'MachineSummaryView' + $poolFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'MemberName' = 'base.desktop'; 'value' = $pool } + if ($machineList) { + $machineFilters = [vmware.hv.queryFilter[]]@() + foreach ($name in $machineList) { + $machineFilters += (New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.name'; 'value' = $name }) + } + $machineList = New-Object VMware.Hv.QueryFilterOr -Property @{ 'filters' = $machineFilters } + $treeList = @() + $treeList += $machineList + $treelist += $poolFilter + $query.Filter = New-Object VMware.Hv.QueryFilterAnd -Property @{ 'filters' = $treeList } + } else { + $query.Filter = $poolFilter + } + while ($remainingCount -ge 1) { + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $queryResults = $query_service_helper.QueryService_Query($services, $query) + $results = $queryResults.results + $machines += $results.id + $query.StartingOffset = $query.StartingOffset + $queryResults.results.Count + $remainingCount = $queryResults.RemainingCount + } + return $machines +} + +function Set_Spec_Vms { + param( + [Parameter(Mandatory = $true)] + [VMware.Hv.VirtualCenterId]$VcID, + + [Parameter(Mandatory = $true)] + $Spec + ) + if ($parentVM) { + $baseimage_helper = New-Object VMware.Hv.BaseImageVmService + $parentList = $baseimage_helper.BaseImageVm_List($services,$vcID) + $parentVMObj = $parentList | Where-Object { $_.name -eq $parentVM } + $spec.ParentVm = $parentVMObj.id + } + if ($snapshotVM) { + $baseimage_snapshot_helper = New-Object VMware.Hv.BaseImageSnapshotService + $snapshotList = $baseimage_snapshot_helper.BaseImageSnapshot_List($services,$spec.ParentVm) + $snapshotVMObj = $snapshotList | Where-Object { $_.name -eq $snapshotVM } + $spec.Snapshot = $snapshotVMObj.id + } + return $spec +} + +function Get_TaskSpec { + param( + [Parameter(Mandatory = $true)] + [string]$Source, + + [Parameter(Mandatory = $true)] + [string]$PoolName, + + [Parameter(Mandatory = $true)] + [string]$Operation, + + [Parameter(Mandatory = $true)] + [string]$TaskSpecName, + + [Parameter(Mandatory = $true)] + $DesktopId + + ) + if ($source -ne 'VIEW_COMPOSER') { + Write-Error "$operation task is not supported for pool type: [$source]" + return $null + } + $machineList = Get-Machines $desktopId $machines + if ($machineList.Length -eq 0) { + Write-Error "Failed to get any Virtual Center machines with the given pool name: [$poolName]" + return $null + } + $spec = Get_New_Object -TypeName $taskSpecName + $spec.LogoffSetting = $logoffSetting + $spec.StopOnFirstError = $stopOnFirstError + $spec.Machines = $machineList + if ($startTime) { $spec.startTime = $startTime } + return $spec +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVEvent,Get-HVFarm,Get-HVPool,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool From 7da4ea673baa4127af947ad6baa053970ecc0b2d Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Wed, 23 Nov 2016 09:45:05 -0500 Subject: [PATCH 16/20] Create Update_PowerCLI_Scripts.ps1 Created for use when migrating over to PowerCLI 6.5 Functions which can be used to detect where scripts (.ps1) are referencing either the PowerCLI Initialization script or Add-PSSnapin functions to start working with PowerCLI: Get-PowerCLIInitialization Get-PowerCLISnapinUse Function used to update the path to the Initialization script found by the above function: Update-PowerCLIInitialization Function used to change from adding in the PowerCLI snapins to now importing the PowerCLI modules: Update-PowerCLISnapinUse --- Scripts/Update_PowerCLI_Scripts.ps1 | 228 ++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 Scripts/Update_PowerCLI_Scripts.ps1 diff --git a/Scripts/Update_PowerCLI_Scripts.ps1 b/Scripts/Update_PowerCLI_Scripts.ps1 new file mode 100644 index 0000000..ec5e09a --- /dev/null +++ b/Scripts/Update_PowerCLI_Scripts.ps1 @@ -0,0 +1,228 @@ +function Get-PowerCLIInitialization { +<# +.SYNOPSIS + Gathers information on PowerShell resources which refer to the old PowerCLI Initialization Script +.DESCRIPTION + Will provide an inventory of scripts, modules, etc refering to the old vSphere PowerCLI directory +.NOTES + Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com +.PARAMETER Path + Directory path to be searched +.EXAMPLE + Get-PowerCLIInitialization -Path C:\Temp\Scripts + Gathers information from the 'C:\Temp\Scripts\' directory +#> +[CmdletBinding()] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [string]$Path + ) + + Process { + + #Validate whether a path was passed as a parameter or not + if (!$Path) {$FullName = (Get-Location).ProviderPath} + else { + + #Validate whether the path passed as a parameter was a literal path or not, then establish the FullName of the desired path + if ((Test-Path -Path $Path -ErrorAction SilentlyContinue) -eq $true -and $Path -is [System.IO.DirectoryInfo]) {$FullName = (Get-Item -Path $Path).FullName} + elseif ((Test-Path -Path $Path -ErrorAction SilentlyContinue) -eq $true -and $Path -isnot [System.IO.DirectoryInfo]) {$FullName = (Get-Item -LiteralPath $Path).FullName} + else { + $currdir = (Get-Location).ProviderPath + Write-Warning "No valid path found at - $currdir\$Path" + } + + } + + if ($FullName) { + + #Gather scripts using ps1 extension and have a string matching "\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1" + $scripts = Get-ChildItem -Path $FullName -Recurse -Filter *.ps1 -File -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Select-String -Pattern "\\VMware\\Infrastructure\\vSphere PowerCLI\\Scripts\\Initialize-PowerCLIEnvironment.ps1" + + #Create a report of neccessary output based on the scripts gathered above + $scriptreport = @() + foreach ($script in $scripts) { + + $singleitem = New-Object System.Object + $singleitem | Add-Member -Type NoteProperty -Name Filename -Value $script.Filename + $singleitem | Add-Member -Type NoteProperty -Name LineNumber -Value $script.LineNumber + $singleitem | Add-Member -Type NoteProperty -Name Path -Value $script.Path.TrimEnd($script.Filename) + $singleitem | Add-Member -Type NoteProperty -Name FullPath -Value $script.Path + $scriptreport += $singleitem + + } + return $scriptreport + + } + + } # End of process +} # End of function + +function Get-PowerCLISnapinUse { +<# +.SYNOPSIS + Gathers information on PowerShell resources which refer to the old PowerCLI Snapins +.DESCRIPTION + Will provide an inventory of scripts, modules, etc refering to the old PowerCLI Snapins +.NOTES + Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com +.PARAMETER Path + Directory path to be searched +.EXAMPLE + Get-PowerCLISnapinUse -Path C:\Temp\Scripts + Gathers information from the 'C:\Temp\Scripts\' directory +#> +[CmdletBinding()] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [string]$Path + ) + + Process { + + #Validate whether a path was passed as a parameter or not + if (!$Path) {$FullName = (Get-Location).ProviderPath} + else { + + #Validate whether the path passed as a parameter was a literal path or not, then establish the FullName of the desired path + if ((Test-Path -Path $Path -ErrorAction SilentlyContinue) -eq $true -and $Path -is [System.IO.DirectoryInfo]) {$FullName = (Get-Item -Path $Path).FullName} + elseif ((Test-Path -Path $Path -ErrorAction SilentlyContinue) -eq $true -and $Path -isnot [System.IO.DirectoryInfo]) {$FullName = (Get-Item -LiteralPath $Path).FullName} + else { + $currdir = (Get-Location).ProviderPath + Write-Warning "No valid path found at - $currdir\$Path" + } + + } + + if ($FullName) { + + #Gather scripts using ps1 extension and have a string matching "add-pssnapin" and "VMware." on the same line + $scripts = Get-ChildItem -Path $FullName -Recurse -Filter *.ps1 -File -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Select-String -Pattern "add-pssnapin" | Where-Object {$_ | Select-String -Pattern "VMware."} + + #Create a report of neccessary output based on the scripts gathered above + $scriptreport = @() + foreach ($script in $scripts) { + + $singleitem = New-Object System.Object + $singleitem | Add-Member -Type NoteProperty -Name Filename -Value $script.Filename + $singleitem | Add-Member -Type NoteProperty -Name LineNumber -Value $script.LineNumber + $singleitem | Add-Member -Type NoteProperty -Name Path -Value $script.Path.TrimEnd($script.Filename) + $singleitem | Add-Member -Type NoteProperty -Name FullPath -Value $script.Path + $scriptreport += $singleitem + + } + + return $scriptreport + + } + + } # End of process +} # End of function + +function Update-PowerCLIInitialization { +<# +.SYNOPSIS + Updates the information in PowerShell resources which refer to the old PowerCLI Initialization Script +.DESCRIPTION + Will update scripts, modules, etc refering to the old vSphere PowerCLI directory +.NOTES + Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com +.PARAMETER Path + Directory path to be searched +.EXAMPLE + Update-PowerCLIInitialization -Path C:\Temp\Scripts + Gathers information from the 'C:\Temp\Scripts\' directory +#> +[CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [string]$Path + ) + + Process { + + #Gather scripts using ps1 extension and have a string matching "\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1" + $scripts = Get-PowerCLIInitialization -Path $Path + + #Check to see if any scripts are found + if (!$scripts) {Write-Warning "No PowerShell resources found requiring update within $Path"} + else { + + foreach ($script in $scripts) { + + #Finds and updates the string to the new location of the Initialize-PowerCLIEnvironment.ps1 script + (Get-Content $script.FullPath).Replace("\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1","\VMware\Infrastructure\PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1") | Set-Content $script.FullPath + + } + + } + + + } # End of process +} # End of function + +function Update-PowerCLISnapinUse { +<# +.SYNOPSIS + Updates the information in PowerShell resources which refer to the old PowerCLI Initialization Script +.DESCRIPTION + Will update scripts, modules, etc refering to the old vSphere PowerCLI directory +.NOTES + Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com +.PARAMETER Path + Directory path to be searched +.EXAMPLE + Update-PowerCLISnapinUse -Path C:\Temp\Scripts + Gathers information from the 'C:\Temp\Scripts\' directory +#> +[CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] + [string]$Path + ) + + Process { + + #Gather scripts using ps1 extension and have a string matching "\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1" + $scripts = Get-PowerCLISnapinUse -Path $Path | select -Unique FullPath + + #Check to see if any scripts are found + if (!$scripts) {Write-Warning "No PowerShell resources found requiring update within $Path"} + else { + + foreach ($script in $scripts) { + + #Finds and updates the string to import the PowerCLI modules + $scriptcontent = (Get-Content $script.FullPath) + + $newoutput = @() + [int]$counter = 0 + foreach ($line in $scriptcontent) { + + #Checks to see if the line includes adding in the VMware PSSnapins and, if so, comments it out + #On first discovery, adds the invokation of get-module for the PowerCLI modules + if ($line -like "Add-PSSnapin*VMware*" -and $counter -eq 0) { + + $newoutput += "Get-Module -ListAvailable VMware* | Import-Module" + $newoutput += $line.Insert(0,'#') + $counter = 1 + + } + elseif ($line -like "Add-PSSnapin*VMware*" -and $counter -eq 1) { + + $newoutput += $line.Insert(0,'#') + + } + else {$newoutput += $line} + + } + + #Updates the script + Set-Content -Value $newoutput -Path $script.FullPath + + } + + } + + } # End of process +} # End of function From c2bd42eb6cec37f77031e49b0a69872e3ef79df3 Mon Sep 17 00:00:00 2001 From: mycloudrevolution Date: Fri, 25 Nov 2016 14:58:24 +0100 Subject: [PATCH 17/20] function Recommend-Sizing This Function collects Basic vSphere Informations for a Hardware Sizing Recomamndation. Focus is in Compute Ressources. --- Modules/Recommend-Sizing.psm1 | 199 ++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 Modules/Recommend-Sizing.psm1 diff --git a/Modules/Recommend-Sizing.psm1 b/Modules/Recommend-Sizing.psm1 new file mode 100644 index 0000000..8aea554 --- /dev/null +++ b/Modules/Recommend-Sizing.psm1 @@ -0,0 +1,199 @@ +function Recommend-Sizing { +<# + .NOTES + =========================================================================== + Created by: Markus Kraus + Twitter: @VMarkus_K + Private Blog: mycloudrevolution.com + =========================================================================== + Changelog: + 2016.11 ver 1.0 Base Release + =========================================================================== + External Code Sources: + http://www.lucd.info/2011/04/22/get-the-maximum-iops/ + https://communities.vmware.com/thread/485386 + =========================================================================== + Tested Against Environment: + vSphere Version: 5.5 U2 + PowerCLI Version: PowerCLI 6.3 R1, PowerCLI 6.5 R1 + PowerShell Version: 4.0, 5.0 + OS Version: Windows 8.1, Server 2012 R2 + =========================================================================== + Keywords vSphere, ESXi, VM, Storage, Sizing + =========================================================================== + + .DESCRIPTION + This Function collects Basic vSphere Informations for a Hardware Sizing Recomamndation. Focus is in Compute Ressources. + + .Example + Recommend-Sizing -ClusterNames Cluster01, Cluster02 -StatsRange 480 -Verbose + + .Example + Recommend-Sizing -ClusterNames Cluster01, Cluster02 + + .Example + Recommend-Sizing -ClusterNames Cluster01 + + .PARAMETER ClusterNames + List of your vSphere Cluser Names to process. + + .PARAMETER StatsRange + Time Range in Minutes for the Stats Collection. + Default is 24h. + +#Requires PS -Version 4.0 +#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"} +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=0)] + [Array] $ClusterNames, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=1)] + [int] $StatsRange = 1440 + +) +Begin { + [int]$TimeRange = "-" + $StatsRange + $Validate = $True + #region: Check Clusters + Write-Verbose "$(Get-Date -Format G) Starting Cluster Validation..." + foreach ($ClusterName in $ClusterNames) { + $TestCluster = Get-Cluster -Name $ClusterName -ErrorAction SilentlyContinue -Verbose:$False + if(!($TestCluster)){ + Write-Warning "No Custer found wth Name $ClusterName!" + $Validate = $False + } + elseif ($TestCluster.count -gt 1) { + Write-Warning "Multiple Custers found wth Name $ClusterName!`nUse a List of explicit Cluster Names: Recommend-Sizing -ClusterNames Cluster01, Cluster02 " + $Validate = $False + } + } + Write-Verbose "$(Get-Date -Format G) Cluster Validation completed" + #endregion +} + +Process { + $MyView = @() + if ($Validate -eq $True) { + foreach ($ClusterName in $ClusterNames) { + #region: Get Cluster Objects + Write-Verbose "$(Get-Date -Format G) Collect $ClusterName Cluster Objects..." + $Cluster = Get-Cluster -Name $ClusterName -Verbose:$False + $ClusterVMs = $Cluster | Get-VM -Verbose:$False + $ClusterVMsPoweredOn = $ClusterVMs | where {$_.PowerState -eq "PoweredOn"} + $ClusterDatastores = $Cluster | Get-Datastore -Verbose:$False + $ClusterHosts = $Cluster | Get-VMHost -Verbose:$False + $HostsAverageMemoryUsageGB = [math]::round( ($ClusterHosts | Measure-Object -Average -Property MemoryUsageGB).Average,1 ) + $HostsAverageMemoryUsage = $([math]::round( (($ClusterHosts | Measure-Object -Average -Property MemoryUsageGB).Average / ($ClusterHosts | Measure-Object -Average -Property MemoryTotalGB).Average) * 100,1 )) + $HostsAverageCpuUsageMhz = [math]::round( ($ClusterHosts | Measure-Object -Average -Property CpuUsageMhz).Average,1 ) + $HostsAverageCpuUsage = $([math]::round( (($ClusterHosts | Measure-Object -Average -Property CpuUsageMhz).Average / ($ClusterHosts | Measure-Object -Average -Property CpuTotalMhz).Average) * 100,1 )) + Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) Cluster Objects completed" + #endregion + + #region: CPU Calculation + Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) CPU Details..." + $VMvCPUs = ($ClusterVMs | Measure-Object -Sum -Property NumCpu).sum + $LogicalThreads = $Cluster.ExtensionData.Summary.NumCpuThreads + $CpuCores = $Cluster.ExtensionData.Summary.NumCpuCores + $vCPUpCPUratio = [math]::round( $VMvCPUs / $LogicalThreads,1 ) + Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) CPU Details completed." + #endregion + + #region: Memory Calculation + Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) Memory Details..." + $AllocatedVMMemoryGB = [math]::round( ($ClusterVMs | Measure-Object -Sum -Property MemoryGB).sum ) + $PhysicalMemory = [math]::round( $Cluster.ExtensionData.Summary.TotalMemory / 1073741824,1 ) + $MemoryUsage = [math]::round( ($AllocatedVMMemoryGB / $PhysicalMemory) * 100 ,1 ) + Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) Memory Details completed" + #endregion + + #region: Creating Disk Metrics + Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) IOPS Metrics..." + $DiskMetrics = "virtualDisk.numberReadAveraged.average","virtualDisk.numberWriteAveraged.average" + $start = (Get-Date).AddMinutes($TimeRange) + $DiskStats = Get-Stat -Stat $DiskMetrics -Entity $ClusterVMsPoweredOn -Start $start -Verbose:$False + Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) IOPS Metrics completed" + #endregion + + #region: Creating IOPS Reports + Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) IOPS Report..." + $reportDiskPerf = @() + $reportDiskPerf = $DiskStats | Group-Object -Property {$_.Entity.Name},Instance | %{ + New-Object PSObject -Property @{ + IOPSMax = ($_.Group | ` + Group-Object -Property Timestamp | ` + %{$_.Group[0].Value + $_.Group[1].Value} | ` + Measure-Object -Maximum).Maximum + } + } + Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) IOPS Report completed" + #endregion + + #region: Create VM Disk Space Report + Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) VM Disk Space Report..." + $reportDiskSpace = @() + foreach ($ClusterVM in $ClusterVMs){ + $VMDKs = $ClusterVM | get-HardDisk -Verbose:$False + foreach ($VMDK in $VMDKs) { + if ($VMDK -ne $null){ + [int]$CapacityGB = $VMDK.CapacityKB/1024/1024 + $Report = [PSCustomObject] @{ + CapacityGB = $CapacityGB + } + $reportDiskSpace += $Report + } + } + } + Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) VM Disk Space Report completed" + #endregion + + #region: Create Datastore Space Report + Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) Datastore Space Report..." + $DatastoreReport = @($ClusterDatastores | Select-Object @{N="CapacityGB";E={[math]::Round($_.CapacityGB,2)}}, @{N="FreeSpaceGB";E={[math]::Round($_.FreeSpaceGB,2)}}, @{N="UsedSpaceGB";E={[math]::Round($_.CapacityGB - $_.FreeSpaceGB,2)}}) + Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) Datastore Space Report completed" + #endregion + + #region: Create Global Report + Write-Verbose "$(Get-Date -Format G) Process Global Report..." + $SizingReport = [PSCustomObject] @{ + Cluster = $Cluster.name + HAEnabled = $Cluster.HAEnabled + DrsEnabled = $Cluster.DrsEnabled + Hosts = $Cluster.ExtensionData.Summary.NumHosts + HostsAverageMemoryUsageGB = $HostsAverageMemoryUsageGB + HostsAverageMemoryUsage = "$HostsAverageMemoryUsage %" + HostsAverageCpuUsageMhz = $HostsAverageCpuUsageMhz + HostsAverageCpuUsage = "$HostsAverageCpuUsage %" + PhysicalCPUCores = $CpuCores + LogicalCPUThreads = $LogicalThreads + VMs = $ClusterVMs.count + ActiveVMs = $ClusterVMsPoweredOn.count + VMvCPUs = $VMvCPUs + vCPUpCPUratio = "$vCPUpCPUratio : 1" + PhysicalMemoryGB = $PhysicalMemory + AllocatedVMMemoryGB = $AllocatedVMMemoryGB + ClusterMemoryUsage = "$MemoryUsage %" + SumMaxVMIOPS = [math]::round( ($reportDiskPerf | Measure-Object -Sum -Property IOPSMax).sum, 1 ) + AverageMaxVMIOPs = [math]::round( ($reportDiskPerf | Measure-Object -Average -Property IOPSMax).Average,1 ) + SumVMDiskSpaceGB = [math]::round( ($reportDiskSpace | Measure-Object -Sum -Property CapacityGB).sum, 1 ) + SumDatastoreSpaceGB = [math]::round( ($DatastoreReport | Measure-Object -Sum -Property CapacityGB).sum, 1 ) + SumDatastoreUsedSpaceGB = [math]::round( ($DatastoreReport | Measure-Object -Sum -Property UsedSpaceGB).sum, 1 ) + } + $MyView += $SizingReport + Write-Verbose "$(Get-Date -Format G) Process Global Report completed" + #endregion + } + + } + Else { + Write-Error "Validation Failed! Processing Skipped" + } + + } + + End { + $MyView + } + +} \ No newline at end of file From 5bf60badf13961bac3a6a6b2d3585be7511ffbe2 Mon Sep 17 00:00:00 2001 From: Alan Renouf Date: Sun, 27 Nov 2016 21:57:51 -0800 Subject: [PATCH 18/20] Example Horizon View Desktop function Example Horizon View Desktop function --- .../Horizon View Example Desktop Script.ps1 | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Scripts/Horizon View Example Desktop Script.ps1 diff --git a/Scripts/Horizon View Example Desktop Script.ps1 b/Scripts/Horizon View Example Desktop Script.ps1 new file mode 100644 index 0000000..d0b571c --- /dev/null +++ b/Scripts/Horizon View Example Desktop Script.ps1 @@ -0,0 +1,49 @@ +Function Get-HVDesktop { + <# + .SYNOPSIS + This cmdlet retrieves the virtual desktops on a horizon view Server. + .DESCRIPTION + This cmdlet retrieves the virtual desktops on a horizon view Server. + .NOTES + Author: Alan Renouf, @alanrenouf,virtu-al.net + .PARAMETER State + Hash table containing states to filter on + .EXAMPLE + List All Desktops + Get-HVDesktop + + .EXAMPLE + List All Problem Desktops + Get-HVDesktop -state @('PROVISIONING_ERROR', + 'ERROR', + 'AGENT_UNREACHABLE', + 'AGENT_ERR_STARTUP_IN_PROGRESS', + 'AGENT_ERR_DISABLED', + 'AGENT_ERR_INVALID_IP', + 'AGENT_ERR_NEED_REBOOT', + 'AGENT_ERR_PROTOCOL_FAILURE', + 'AGENT_ERR_DOMAIN_FAILURE', + 'AGENT_CONFIG_ERROR', + 'UNKNOWN') + #> +Param ( + $State + ) + + $ViewAPI = $global:DefaultHVServers[0].ExtensionData + $query_service = New-Object "Vmware.Hv.QueryServiceService" + $query = New-Object "Vmware.Hv.QueryDefinition" + $query.queryEntityType = 'MachineSummaryView' + if ($State) { + [VMware.Hv.QueryFilter []] $filters = @() + foreach ($filterstate in $State) { + $filters += new-object VMware.Hv.QueryFilterEquals -property @{'memberName' = 'base.basicState'; 'value' = $filterstate} + } + $orFilter = new-object VMware.Hv.QueryFilterOr -property @{'filters' = $filters} + $query.Filter = $orFilter + } + $Desktops = $query_service.QueryService_Query($ViewAPI,$query) + $Desktops.Results.Base +} + + From a0d2450ff1b5aba4dbb99186f6a9d6bed425a624 Mon Sep 17 00:00:00 2001 From: mycloudrevolution Date: Mon, 28 Nov 2016 11:19:09 +0100 Subject: [PATCH 19/20] Optional Stats Collection. Temporary workaround for problems with vSphere 6.x --- Modules/Recommend-Sizing.psm1 | 65 ++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/Modules/Recommend-Sizing.psm1 b/Modules/Recommend-Sizing.psm1 index 8aea554..db01181 100644 --- a/Modules/Recommend-Sizing.psm1 +++ b/Modules/Recommend-Sizing.psm1 @@ -8,6 +8,7 @@ function Recommend-Sizing { =========================================================================== Changelog: 2016.11 ver 1.0 Base Release + 2016.11 ver 1.1 Optional Stats Collection. =========================================================================== External Code Sources: http://www.lucd.info/2011/04/22/get-the-maximum-iops/ @@ -26,7 +27,7 @@ function Recommend-Sizing { This Function collects Basic vSphere Informations for a Hardware Sizing Recomamndation. Focus is in Compute Ressources. .Example - Recommend-Sizing -ClusterNames Cluster01, Cluster02 -StatsRange 480 -Verbose + Recommend-Sizing -ClusterNames Cluster01, Cluster02 -Stats -StatsRange 60 -Verbose .Example Recommend-Sizing -ClusterNames Cluster01, Cluster02 @@ -37,6 +38,11 @@ function Recommend-Sizing { .PARAMETER ClusterNames List of your vSphere Cluser Names to process. + .PARAMETER Stats + Enables Stats Collection. + + Warning: At the moment this is only tested and supported with vSphere 5.5! + .PARAMETER StatsRange Time Range in Minutes for the Stats Collection. Default is 24h. @@ -49,12 +55,18 @@ function Recommend-Sizing { param( [Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=0)] [Array] $ClusterNames, - [Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=1)] + [Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=2)] + [switch] $Stats, + [Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=2)] [int] $StatsRange = 1440 ) Begin { - [int]$TimeRange = "-" + $StatsRange + if ($Stats) { + Write-Warning "Stats Collection enabled.`nAt the moment this is only tested and supported with vSphere 5.5" + [int]$TimeRange = "-" + $StatsRange + } + $Validate = $True #region: Check Clusters Write-Verbose "$(Get-Date -Format G) Starting Cluster Validation..." @@ -108,27 +120,32 @@ Process { Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) Memory Details completed" #endregion - #region: Creating Disk Metrics - Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) IOPS Metrics..." - $DiskMetrics = "virtualDisk.numberReadAveraged.average","virtualDisk.numberWriteAveraged.average" - $start = (Get-Date).AddMinutes($TimeRange) - $DiskStats = Get-Stat -Stat $DiskMetrics -Entity $ClusterVMsPoweredOn -Start $start -Verbose:$False - Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) IOPS Metrics completed" - #endregion - - #region: Creating IOPS Reports - Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) IOPS Report..." - $reportDiskPerf = @() - $reportDiskPerf = $DiskStats | Group-Object -Property {$_.Entity.Name},Instance | %{ - New-Object PSObject -Property @{ - IOPSMax = ($_.Group | ` - Group-Object -Property Timestamp | ` - %{$_.Group[0].Value + $_.Group[1].Value} | ` - Measure-Object -Maximum).Maximum + if ($Stats) { + #region: Creating Disk Metrics + Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) IOPS Metrics..." + $DiskMetrics = "virtualDisk.numberReadAveraged.average","virtualDisk.numberWriteAveraged.average" + $start = (Get-Date).AddMinutes($TimeRange) + $DiskStats = Get-Stat -Stat $DiskMetrics -Entity $ClusterVMsPoweredOn -Start $start -Verbose:$False + Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) IOPS Metrics completed" + #endregion + + #region: Creating IOPS Reports + Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) IOPS Report..." + $reportDiskPerf = @() + $reportDiskPerf = $DiskStats | Group-Object -Property {$_.Entity.Name},Instance | %{ + New-Object PSObject -Property @{ + IOPSMax = ($_.Group | ` + Group-Object -Property Timestamp | ` + %{$_.Group[0].Value + $_.Group[1].Value} | ` + Measure-Object -Maximum).Maximum + } } + Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) IOPS Report completed" + #endregion + } + else { + Write-Verbose "$(Get-Date -Format G) Stats Cellocetion skipped..." } - Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) IOPS Report completed" - #endregion #region: Create VM Disk Space Report Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) VM Disk Space Report..." @@ -174,11 +191,11 @@ Process { PhysicalMemoryGB = $PhysicalMemory AllocatedVMMemoryGB = $AllocatedVMMemoryGB ClusterMemoryUsage = "$MemoryUsage %" - SumMaxVMIOPS = [math]::round( ($reportDiskPerf | Measure-Object -Sum -Property IOPSMax).sum, 1 ) - AverageMaxVMIOPs = [math]::round( ($reportDiskPerf | Measure-Object -Average -Property IOPSMax).Average,1 ) SumVMDiskSpaceGB = [math]::round( ($reportDiskSpace | Measure-Object -Sum -Property CapacityGB).sum, 1 ) SumDatastoreSpaceGB = [math]::round( ($DatastoreReport | Measure-Object -Sum -Property CapacityGB).sum, 1 ) SumDatastoreUsedSpaceGB = [math]::round( ($DatastoreReport | Measure-Object -Sum -Property UsedSpaceGB).sum, 1 ) + SumMaxVMIOPS = [math]::round( ($reportDiskPerf | Measure-Object -Sum -Property IOPSMax).sum, 1 ) + AverageMaxVMIOPs = [math]::round( ($reportDiskPerf | Measure-Object -Average -Property IOPSMax).Average,1 ) } $MyView += $SizingReport Write-Verbose "$(Get-Date -Format G) Process Global Report completed" From 530b07d73ee69ca7d192aa30f1a2d17b786b613d Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Wed, 30 Nov 2016 11:46:53 -0500 Subject: [PATCH 20/20] Updating the Approval Process --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae27a3d..7d2825c 100644 --- a/README.md +++ b/README.md @@ -189,4 +189,4 @@ Members: * Rynardt Spies (Community Member) ## Approval of Additions -Items added to the repository, including items from the Board members, require 2 votes from the board members before being added to the repository. The approving members will have ideally downloaded and tested the item. When two “Approved for Merge” comments are added from board members, the pull can then be committed to the repository. +Items added to the repository, including items from the Board members, require a review and approval from at least one board member before being added to the repository. The approving member/s will have verified for a lack of malicious code. Once an “Approved for Merge” comment has been added from a board member, the pull can then be committed to the repository. \ No newline at end of file