diff --git a/Modules/VMware.Hv.Helper/Json/Farm/AutomatedInstantCloneFarm.json b/Modules/VMware.Hv.Helper/Json/Farm/AutomatedInstantCloneFarm.json new file mode 100644 index 0000000..605e6a5 --- /dev/null +++ b/Modules/VMware.Hv.Helper/Json/Farm/AutomatedInstantCloneFarm.json @@ -0,0 +1,98 @@ +{ + "Type": "AUTOMATED", + "Data": { + "Name": "ICFarmJson", + "DisplayName": "FarmJsonTest", + "AccessGroup": "Root", + "Description": "created IC Farm from PS via JSON", + "Enabled": null, + "Deleting": false, + "Settings": { + "DisconnectedSessionTimeoutPolicy" : "NEVER", + "DisconnectedSessionTimeoutMinutes" : 1, + "EmptySessionTimeoutPolicy" : "AFTER", + "EmptySessionTimeoutMinutes" : 1, + "LogoffAfterTimeout" : false + }, + "Desktop": null, + "DisplayProtocolSettings": { + "DefaultDisplayProtocol" : "PCOIP", + "AllowDisplayProtocolOverride" : false, + "EnableHTMLAccess" : false + }, + "ServerErrorThreshold": null, + "MirageConfigurationOverrides": { + "OverrideGlobalSetting" : false, + "Enabled" : false, + "Url" : null + } + }, + "AutomatedFarmSpec": { + "ProvisioningType": "INSTANT_CLONE_ENGINE", + "VirtualCenter": null, + "RdsServerNamingSpec": { + "NamingMethod": "PATTERN", + "PatternNamingSettings": { + "NamingPattern": "ICFarmVMPS", + "MaxNumberOfRDSServers": 1 + } + }, + "VirtualCenterProvisioningSettings": { + "EnableProvisioning": true, + "StopProvisioningOnError": true, + "MinReadyVMsOnVComposerMaintenance": 0, + "VirtualCenterProvisioningData": { + "ParentVm": "vm-rdsh-ic", + "Snapshot": "snap_5", + "Datacenter": null, + "VmFolder": "Instant_Clone_VMs", + "HostOrCluster": "vimal-cluster", + "ResourcePool": "vimal-cluster" + }, + "VirtualCenterStorageSettings": { + "Datastores": [ + { + "Datastore": "Datastore1", + "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": "CLONE_PREP", + "DomainAdministrator": null, + "AdContainer": "CN=Computers", + "ReusePreExistingAccounts": false, + "ClonePrepCustomizationSettings": { + "InstantCloneEngineDomainAdministrator": null, + "PowerOffScriptName": null, + "PowerOffScriptParameters": null, + "PostSynchronizationScriptName": null, + "PostSynchronizationScriptParameters": null + } + }, + "RdsServerMaxSessionsData": { + "MaxSessionsType": "UNLIMITED", + "MaxSessions": null + } + }, + "ManualFarmSpec": null, + "NetBiosName" : "ad-vimalg" +} diff --git a/Modules/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json b/Modules/VMware.Hv.Helper/Json/Farm/AutomatedLinkedCloneFarm.json similarity index 84% rename from Modules/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json rename to Modules/VMware.Hv.Helper/Json/Farm/AutomatedLinkedCloneFarm.json index 3706374..32c3f9a 100644 --- a/Modules/VMware.Hv.Helper/New-HVFarm/AutomatedLinkedCloneFarm.json +++ b/Modules/VMware.Hv.Helper/Json/Farm/AutomatedLinkedCloneFarm.json @@ -1,17 +1,31 @@ { "Type": "AUTOMATED", "Data": { - "Name": "LCFarmTest", - "DisplayName": "Ankit LC Farm Test", + "Name": "LCFarmJson", + "DisplayName": "FarmJsonTest", "AccessGroup": "Root", - "Description": "created LC Farm from PS", + "Description": "created LC Farm from PS via JSON", "Enabled": null, "Deleting": false, - "Settings": null, + "Settings": { + "DisconnectedSessionTimeoutPolicy" : "NEVER", + "DisconnectedSessionTimeoutMinutes" : 1, + "EmptySessionTimeoutPolicy" : "AFTER", + "EmptySessionTimeoutMinutes" : 1, + "LogoffAfterTimeout" : false + }, "Desktop": null, - "DisplayProtocolSettings": null, + "DisplayProtocolSettings": { + "DefaultDisplayProtocol" : "PCOIP", + "AllowDisplayProtocolOverride" : false, + "EnableHTMLAccess" : false + }, "ServerErrorThreshold": null, - "MirageConfigurationOverrides": null + "MirageConfigurationOverrides": { + "OverrideGlobalSetting" : false, + "Enabled" : false, + "Url" : null + } }, "AutomatedFarmSpec": { "ProvisioningType": "VIEW_COMPOSER", @@ -19,7 +33,7 @@ "RdsServerNamingSpec": { "NamingMethod": "PATTERN", "PatternNamingSettings": { - "NamingPattern": "LCFarmVM_PS", + "NamingPattern": "LCFarmVMPS", "MaxNumberOfRDSServers": 1 } }, @@ -28,17 +42,17 @@ "StopProvisioningOnError": true, "MinReadyVMsOnVComposerMaintenance": 0, "VirtualCenterProvisioningData": { - "ParentVm": "Win_Server_2012_R2", - "Snapshot": "Snap_RDS", + "ParentVm": "RDSServer", + "Snapshot": "RDS_SNAP1", "Datacenter": null, - "VmFolder": "AnkitPoolVM", - "HostOrCluster": "cls", - "ResourcePool": "cls" + "VmFolder": "Praveen", + "HostOrCluster": "CS-1", + "ResourcePool": "CS-1" }, "VirtualCenterStorageSettings": { "Datastores": [ { - "Datastore": "datastore1 (5)", + "Datastore": "Datastore1", "StorageOvercommit": "UNBOUNDED" } ], @@ -67,7 +81,7 @@ "AdContainer": "CN=Computers", "ReusePreExistingAccounts": false, "SysprepCustomizationSettings": { - "CustomizationSpec": "RDSH_Cust2" + "CustomizationSpec": "PraveenCust" } }, "RdsServerMaxSessionsData": { @@ -76,5 +90,5 @@ } }, "ManualFarmSpec": null, - "NetBiosName" : "adankit" + "NetBiosName" : "adviewdev" } diff --git a/Modules/VMware.Hv.Helper/New-HVFarm/ManualFarm.json b/Modules/VMware.Hv.Helper/Json/Farm/ManualFarm.json similarity index 51% rename from Modules/VMware.Hv.Helper/New-HVFarm/ManualFarm.json rename to Modules/VMware.Hv.Helper/Json/Farm/ManualFarm.json index cf674c1..3dd1678 100644 --- a/Modules/VMware.Hv.Helper/New-HVFarm/ManualFarm.json +++ b/Modules/VMware.Hv.Helper/Json/Farm/ManualFarm.json @@ -7,17 +7,31 @@ "Description": "Manual PS Test", "Enabled": null, "Deleting": false, - "Settings": null, + "Settings": { + "DisconnectedSessionTimeoutPolicy" : "NEVER", + "DisconnectedSessionTimeoutMinutes" : 1, + "EmptySessionTimeoutPolicy" : "AFTER", + "EmptySessionTimeoutMinutes" : 1, + "LogoffAfterTimeout" : false + }, "Desktop": null, - "DisplayProtocolSettings": null, + "DisplayProtocolSettings": { + "DefaultDisplayProtocol" : "PCOIP", + "AllowDisplayProtocolOverride" : false, + "EnableHTMLAccess" : false + }, "ServerErrorThreshold": null, - "MirageConfigurationOverrides": null + "MirageConfigurationOverrides": { + "OverrideGlobalSetting" : false, + "Enabled" : false, + "Url" : null + } }, "AutomatedFarmSpec": null, "ManualFarmSpec": { "RdsServers": [ { - "rdsServer": "WIN-ORKA1Q8B0P7" + "rdsServer": "RDSServer.adviewdev.eng.vmware.com" } ] } diff --git a/Modules/VMware.Hv.Helper/New-HVPool/FullClone.json b/Modules/VMware.Hv.Helper/Json/Pool/FullClone.json similarity index 82% rename from Modules/VMware.Hv.Helper/New-HVPool/FullClone.json rename to Modules/VMware.Hv.Helper/Json/Pool/FullClone.json index 2ae9539..e6d7fae 100644 --- a/Modules/VMware.Hv.Helper/New-HVPool/FullClone.json +++ b/Modules/VMware.Hv.Helper/Json/Pool/FullClone.json @@ -5,7 +5,44 @@ "AccessGroup": "Root", "Description": "create full clone via JSON" }, - "DesktopSettings": null, + "DesktopSettings": { + "enabled": true, + "deleting": false, + "connectionServerRestrictions": null, + "logoffSettings": { + "powerPolicy": "TAKE_NO_POWER_ACTION", + "automaticLogoffPolicy": "NEVER", + "automaticLogoffMinutes": 120, + "allowUsersToResetMachines": false, + "allowMultipleSessionsPerUser": false, + "deleteOrRefreshMachineAfterLogoff": "NEVER", + "refreshOsDiskAfterLogoff": "NEVER", + "refreshPeriodDaysForReplicaOsDisk": 5, + "refreshThresholdPercentageForReplicaOsDisk": 10 + }, + "displayProtocolSettings": { + "supportedDisplayProtocols": ["PCOIP", "BLAST" ], + "defaultDisplayProtocol": "BLAST", + "allowUsersToChooseProtocol": true, + "pcoipDisplaySettings": { + "renderer3D": "DISABLED", + "enableGRIDvGPUs": false, + "vRamSizeMB": 96, + "maxNumberOfMonitors": 3, + "maxResolutionOfAnyOneMonitor": "WSXGA_PLUS" + }, + "enableHTMLAccess": true + }, + "flashSettings": { + "quality": "NO_CONTROL", + "throttling": "DISABLED" + }, + "mirageConfigurationOverrides": { + "overrideGlobalSetting": false, + "enabled": false, + "url": false + } + }, "Type": "AUTOMATED", "AutomatedDesktopSpec": { "ProvisioningType": "VIRTUAL_CENTER", @@ -69,7 +106,7 @@ "NoCustomizationSettings": { "DoNotPowerOnVMsAfterCreation": false }, - "SysprepCustomizationSettings": null, + "SysprepCustomizationSettings": {"customizationSpec" : "praveencust"}, "QuickprepCustomizationSettings": null, "CloneprepCustomizationSettings": null } @@ -77,6 +114,5 @@ "ManualDesktopSpec": null, "RdsDesktopSpec": null, "GlobalEntitlementData": null, - "NetBiosName" : "adviewdev", - "SysPrepName" : "praveencust" + "NetBiosName" : "adviewdev" } diff --git a/Modules/VMware.Hv.Helper/New-HVPool/InstantClone.json b/Modules/VMware.Hv.Helper/Json/Pool/InstantClone.json similarity index 88% rename from Modules/VMware.Hv.Helper/New-HVPool/InstantClone.json rename to Modules/VMware.Hv.Helper/Json/Pool/InstantClone.json index a8da482..4c3c584 100644 --- a/Modules/VMware.Hv.Helper/New-HVPool/InstantClone.json +++ b/Modules/VMware.Hv.Helper/Json/Pool/InstantClone.json @@ -5,7 +5,44 @@ "AccessGroup": "ROOT", "Description": "create instant pool" }, - "DesktopSettings": null, + "DesktopSettings": { + "enabled": true, + "deleting": false, + "connectionServerRestrictions": null, + "logoffSettings": { + "powerPolicy": "ALWAYS_POWERED_ON", + "automaticLogoffPolicy": "NEVER", + "automaticLogoffMinutes": 120, + "allowUsersToResetMachines": false, + "allowMultipleSessionsPerUser": false, + "deleteOrRefreshMachineAfterLogoff": "DELETE", + "refreshOsDiskAfterLogoff": "NEVER", + "refreshPeriodDaysForReplicaOsDisk": 5, + "refreshThresholdPercentageForReplicaOsDisk": 10 + }, + "displayProtocolSettings": { + "supportedDisplayProtocols": ["PCOIP", "BLAST" ], + "defaultDisplayProtocol": "BLAST", + "allowUsersToChooseProtocol": true, + "pcoipDisplaySettings": { + "renderer3D": "DISABLED", + "enableGRIDvGPUs": false, + "vRamSizeMB": 96, + "maxNumberOfMonitors": 3, + "maxResolutionOfAnyOneMonitor": "WSXGA_PLUS" + }, + "enableHTMLAccess": true + }, + "flashSettings": { + "quality": "NO_CONTROL", + "throttling": "DISABLED" + }, + "mirageConfigurationOverrides": { + "overrideGlobalSetting": false, + "enabled": false, + "url": false + } + }, "Type": "AUTOMATED", "AutomatedDesktopSpec": { "ProvisioningType": "INSTANT_CLONE_ENGINE", diff --git a/Modules/VMware.Hv.Helper/New-HVPool/LinkedClone.json b/Modules/VMware.Hv.Helper/Json/Pool/LinkedClone.json similarity index 80% rename from Modules/VMware.Hv.Helper/New-HVPool/LinkedClone.json rename to Modules/VMware.Hv.Helper/Json/Pool/LinkedClone.json index 53171a6..ee3dfac 100644 --- a/Modules/VMware.Hv.Helper/New-HVPool/LinkedClone.json +++ b/Modules/VMware.Hv.Helper/Json/Pool/LinkedClone.json @@ -5,7 +5,44 @@ "AccessGroup": "Root", "Description": "created linkedclone pool from ps" }, - "DesktopSettings": null, + "DesktopSettings": { + "enabled": true, + "deleting": false, + "connectionServerRestrictions": null, + "logoffSettings": { + "powerPolicy": "TAKE_NO_POWER_ACTION", + "automaticLogoffPolicy": "NEVER", + "automaticLogoffMinutes": 120, + "allowUsersToResetMachines": false, + "allowMultipleSessionsPerUser": false, + "deleteOrRefreshMachineAfterLogoff": "NEVER", + "refreshOsDiskAfterLogoff": "NEVER", + "refreshPeriodDaysForReplicaOsDisk": 5, + "refreshThresholdPercentageForReplicaOsDisk": 10 + }, + "displayProtocolSettings": { + "supportedDisplayProtocols": ["RDP","PCOIP", "BLAST" ], + "defaultDisplayProtocol": "PCOIP", + "allowUsersToChooseProtocol": true, + "pcoipDisplaySettings": { + "renderer3D": "DISABLED", + "enableGRIDvGPUs": false, + "vRamSizeMB": 96, + "maxNumberOfMonitors": 3, + "maxResolutionOfAnyOneMonitor": "WSXGA_PLUS" + }, + "enableHTMLAccess": true + }, + "flashSettings": { + "quality": "NO_CONTROL", + "throttling": "DISABLED" + }, + "mirageConfigurationOverrides": { + "overrideGlobalSetting": false, + "enabled": false, + "url": null + } + }, "Type": "AUTOMATED", "AutomatedDesktopSpec": { "ProvisioningType": "VIEW_COMPOSER", @@ -33,7 +70,7 @@ "Template": null, "ParentVm": "Agent_pra", "Snapshot": "kb-hotfix", - "Datacenter": null, + "Datacenter": "Dev-Dc", "VmFolder": "Praveen", "HostOrCluster": "CS-1", "ResourcePool": "CS-1" @@ -52,7 +89,8 @@ "UseNativeSnapshots": false, "SpaceReclamationSettings": { "ReclaimVmDiskSpace": false, - "ReclamationThresholdGB": null + "ReclamationThresholdGB": null, + "BlackoutTimes" : null }, "PersistentDiskSettings": { "RedirectWindowsProfile": false, @@ -75,19 +113,31 @@ } }, "VirtualCenterNetworkingSettings": { - "Nics": null + "Nics": [ + { + "Nic": "nicName", + "NetworkLabelAssignmentSpecs": [ + { + "Enabled" : false, + "networkLabel" : null, + "maxLabelType" : null, + "maxLabel" : null + } + ] + } + ] } }, "VirtualCenterManagedCommonSettings": { "TransparentPageSharingScope": "VM" }, "CustomizationSettings": { - "CustomizationType": "QUICK_PREP", - "DomainAdministrator": null, + "CustomizationType": "SYS_PREP", + "DomainAdministrator": "administrator", "AdContainer": "CN=Computers", "ReusePreExistingAccounts": false, "NoCustomizationSettings": null, - "SysprepCustomizationSettings": null, + "SysprepCustomizationSettings": {"customizationSpec" : "praveencust"}, "QuickprepCustomizationSettings": { "PowerOffScriptName": null, "PowerOffScriptParameters": null, @@ -99,7 +149,6 @@ }, "ManualDesktopSpec": null, "RdsDesktopSpec": null, - "GlobalEntitlementData": null, - "NetBiosName" : "adviewdev", - "SysPrepName" : "praveencust" + "GlobalEntitlementData": null, + "NetBiosName" : "adviewdev" } diff --git a/Modules/VMware.Hv.Helper/New-HVPool/ManualSpec.json b/Modules/VMware.Hv.Helper/Json/Pool/ManualSpec.json similarity index 54% rename from Modules/VMware.Hv.Helper/New-HVPool/ManualSpec.json rename to Modules/VMware.Hv.Helper/Json/Pool/ManualSpec.json index b302bba..8b95389 100644 --- a/Modules/VMware.Hv.Helper/New-HVPool/ManualSpec.json +++ b/Modules/VMware.Hv.Helper/Json/Pool/ManualSpec.json @@ -5,7 +5,44 @@ "AccessGroup": "ROOT", "Description": "Manual pool creation" }, - "DesktopSettings": null, + "DesktopSettings": { + "enabled": true, + "deleting": false, + "connectionServerRestrictions": null, + "logoffSettings": { + "powerPolicy": "TAKE_NO_POWER_ACTION", + "automaticLogoffPolicy": "NEVER", + "automaticLogoffMinutes": 120, + "allowUsersToResetMachines": false, + "allowMultipleSessionsPerUser": false, + "deleteOrRefreshMachineAfterLogoff": "NEVER", + "refreshOsDiskAfterLogoff": "NEVER", + "refreshPeriodDaysForReplicaOsDisk": 5, + "refreshThresholdPercentageForReplicaOsDisk": 10 + }, + "displayProtocolSettings": { + "supportedDisplayProtocols": ["PCOIP", "BLAST" ], + "defaultDisplayProtocol": "BLAST", + "allowUsersToChooseProtocol": true, + "pcoipDisplaySettings": { + "renderer3D": "DISABLED", + "enableGRIDvGPUs": false, + "vRamSizeMB": 96, + "maxNumberOfMonitors": 3, + "maxResolutionOfAnyOneMonitor": "WSXGA_PLUS" + }, + "enableHTMLAccess": true + }, + "flashSettings": { + "quality": "NO_CONTROL", + "throttling": "DISABLED" + }, + "mirageConfigurationOverrides": { + "overrideGlobalSetting": false, + "enabled": false, + "url": false + } + }, "Type": "MANUAL", "AutomatedDesktopSpec": null, "ManualDesktopSpec": { @@ -16,7 +53,7 @@ "Source": "VIRTUAL_CENTER", "Machines": [ { - "Machine" : "PowerCLI-VM" + "Machine" : "Praveen_Agent" } ], "VirtualCenter": null, @@ -32,4 +69,5 @@ }, "RdsDesktopSpec": null, "GlobalEntitlementData": null + } diff --git a/Modules/VMware.Hv.Helper/Json/Pool/RdsSpec.json b/Modules/VMware.Hv.Helper/Json/Pool/RdsSpec.json new file mode 100644 index 0000000..bab0c67 --- /dev/null +++ b/Modules/VMware.Hv.Helper/Json/Pool/RdsSpec.json @@ -0,0 +1,27 @@ +{ + "Base": { + "Name" : "RdsJson", + "DisplayName": "TestRDSPS", + "AccessGroup": "Root", + "Description": "Testing PS" + }, + "DesktopSettings": { + "enabled": true, + "deleting": false, + "connectionServerRestrictions": null, + "logoffSettings": null, + "displayProtocolSettings": null, + "flashSettings": { + "quality": "NO_CONTROL", + "throttling": "DISABLED" + }, + "mirageConfigurationOverrides": null + }, + "Type": "RDS", + "AutomatedDesktopSpec": null, + "ManualDesktopSpec": null, + "RdsDesktopSpec": { + "Farm": "test1" + }, + "GlobalEntitlementData": null +} diff --git a/Modules/VMware.Hv.Helper/New-HVPool/RdsSpec.json b/Modules/VMware.Hv.Helper/New-HVPool/RdsSpec.json deleted file mode 100644 index 86b3571..0000000 --- a/Modules/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/README.md b/Modules/VMware.Hv.Helper/README.md new file mode 100644 index 0000000..fe87153 --- /dev/null +++ b/Modules/VMware.Hv.Helper/README.md @@ -0,0 +1,20 @@ +Prerequisites/Steps to use this module: + +1. This module only works for Horizon product E.g. Horizon 7.0.2 and later. +2. Install the latest version of Powershell, PowerCLI(6.5) or (later version via psgallery). +3. Import HorizonView module by running: Import-Module VMware.VimAutomation.HorizonView. +4. Import "VMware.Hv.Helper" module by running: Import-Module -Name "location of this module" or Get-Module -ListAvailable 'VMware.Hv.Helper' | Import-Module. +5. Get-Command -Module "This module Name" to list all available functions or Get-Command -Module 'VMware.Hv.Helper'. + +# Example script to connect view API service of Connection Server: + +Import-Module VMware.VimAutomation.HorizonView +# Connection to view API service +$hvServer = Connect-HVServer -server +$hvServices = $hvserver.ExtensionData +$csList = $hvServices.ConnectionServer.ConnectionServer_List() +# Load this module +Get-Module -ListAvailable 'VMware.Hv.Helper' | Import-Module +Get-Command -Module 'VMware.Hv.Helper' +# Use advanced functions of this module +New-HVPool -spec 'path to InstantClone.json file' diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.format.ps1xml b/Modules/VMware.Hv.Helper/VMware.HV.Helper.format.ps1xml index 62ce001..7f8a6aa 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.format.ps1xml +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.format.ps1xml @@ -27,6 +27,10 @@ 16 + + + 8 + 7 @@ -56,10 +60,23 @@ $_.desktopSummaryData.userAssignment - + + + $filterContains = Get-HVQueryFilter localData.desktops -contains ([VMware.Hv.DesktopId[]]$_.id) + $GlobalfilterContains = Get-HVQueryFilter localData.desktops -contains ([VMware.Hv.DesktopId[]]$_.id) + Try { + $results += Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $filterContains + $results += Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $GlobalfilterContains + } Catch { + #Do nothing + } + $results.length + + + $_.desktopSummaryData.enabled - + $_.desktopSummaryData.numSessions @@ -97,6 +114,20 @@ $_.desktopSummaryData.userAssignment + + + $filterContains = Get-HVQueryFilter localData.desktops -contains ([VMware.Hv.DesktopId[]]$_.id) + $GlobalfilterContains = Get-HVQueryFilter localData.desktops -contains ([VMware.Hv.DesktopId[]]$_.id) + Try { + $results += Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $filterContains + $results += Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $GlobalfilterContains + } Catch { + #Do nothing + } + $results.length + + + $_.desktopSummaryData.enabled diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psd1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psd1 index 705cc80..42dc6aa 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psd1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psd1 @@ -12,7 +12,7 @@ # RootModule = '' # Version number of this module. -ModuleVersion = '1.0' +ModuleVersion = '1.1' # ID used to uniquely identify this module GUID = '6d3f7fb5-4e52-43d8-91e1-f65f72532a1d' diff --git a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 index 7c06a99..56ad921 100644 --- a/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 +++ b/Modules/VMware.Hv.Helper/VMware.HV.Helper.psm1 @@ -1,5 +1,5 @@ #Script Module : VMware.Hv.Helper -#Version : 1.0 +#Version : 1.1 #Copyright © 2016 VMware, Inc. All Rights Reserved. @@ -48,14 +48,23 @@ function Get-ViewAPIService { 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 - } + $hvServer = $global:DefaultHVServers[0] + return $hvServer.ExtensionData } return $null } +function Get-HVConfirmFlag { + Param( + [Parameter(Mandatory = $true)] + $keys + ) + if (($keys -contains 'Confirm') -or ($keys -contains 'WhatIf')) { + return $true + } + return $false +} + function Get-VcenterID { param( [Parameter(Mandatory = $true)] @@ -177,30 +186,30 @@ The Add-HVDesktop adds virtual machines to already exiting pools by using view A View API service object of Connect-HVServer cmdlet. .EXAMPLE + Add-HVDesktop -PoolName 'ManualPool' -Machines 'manualPool1', 'manualPool2' -Confirm:$false 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' + Add virtual machines to automated specific named dedicated pool .EXAMPLE - Add machines to automated specific named Floating pool Add-HVDesktop -PoolName 'SpecificNamed' -Machines 'vm-03', 'vm-04' + Add machines to automated specific named Floating pool .EXAMPLE - Add machines to unmanged manual pool Add-HVDesktop -PoolName 'Unmanaged' -Machines 'desktop-1.eng.vmware.com' + Add machines to unmanged manual pool .NOTES Author : Praveen Mathamsetty. Author email : pmathamsetty@vmware.com - Version : 1.0 + Version : 1.1 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 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -239,6 +248,7 @@ The Add-HVDesktop adds virtual machines to already exiting pools by using view A } process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys try { $desktopPool = Get-HVPoolSummary -poolName $poolName -hvServer $hvServer } catch { @@ -296,7 +306,10 @@ The Add-HVDesktop adds virtual machines to already exiting pools by using view A return } } - $desktop_service_helper.Desktop_AddMachinesToManualDesktop($services,$id,$machineList) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($machines)) { + $desktop_service_helper.Desktop_AddMachinesToManualDesktop($services,$id,$machineList) + } + return $machineList } default { Write-Error "Only Automated/Manual pool types support this add operation" @@ -347,6 +360,7 @@ function Get-MachinesByVCenter ($MachineList,$VcId) { } return $machines } + function Add-HVRDSServer { <# .SYNOPSIS @@ -365,21 +379,21 @@ function Add-HVRDSServer { View API service object of Connect-HVServer cmdlet. .EXAMPLE + Add-HVRDSServer -Farm "manualFarmTest" -RdsServers "vm-for-rds","vm-for-rds-2" -Confirm:$false 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 + Author : praveen mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 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 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> [CmdletBinding( @@ -407,10 +421,11 @@ function Add-HVRDSServer { } process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys try { - $farmSpecObj = Get-HVFarmSummary -farmName $farmName -hvServer $hvServer + $farmSpecObj = Get-HVFarmSummary -farmName $farmName -hvServer $hvServer -suppressInfo $true } catch { - Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + Write-Error "Make sure Get-HVFarmSummary advanced function is loaded, $_" break } if ($farmSpecObj) { @@ -430,7 +445,10 @@ function Add-HVRDSServer { 'MANUAL' { try { $serverList = Get-RegisteredRDSServer -services $services -serverList $rdsServers - $farm_service_helper.Farm_AddRDSServers($services, $id, $serverList) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($rdsServers)) { + $farm_service_helper.Farm_AddRDSServers($services, $id, $serverList) + } + return $serverList } catch { Write-Error "Failed to Add RDS Server to Farm with error: $_" break @@ -443,7 +461,8 @@ function Add-HVRDSServer { [System.gc]::collect() } } -[System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient") | Out-Null + + function Connect-HVEvent { <# @@ -464,21 +483,21 @@ function Connect-HVEvent { Password corresponds to 'dbUserName' user. .EXAMPLE - Connecting to the database with default username configured on Connection Server $hvServer. Connect-HVEvent -HvServer $hvServer + Connecting to the database with default username configured on Connection Server $hvServer. .EXAMPLE - Connecting to the database configured on Connection Server $hvServer with customised user name 'system'. $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' + Connecting to the database configured on Connection Server $hvServer with customised user name 'system'. .EXAMPLE - Connecting to the database with customised user name and password. $hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' -DbPassword 'censored' + Connecting to the database with customised user name and password. .EXAMPLE + C:\PS>$password = Read-Host 'Database Password' -AsSecureString + C:\PS>$hvDbServer = Connect-HVEvent -HvServer $hvServer -DbUserName 'system' -DbPassword $password 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. @@ -486,11 +505,11 @@ function Connect-HVEvent { .NOTES Author : Paramesh Oddepally. Author email : poddepally@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> [CmdletBinding()] @@ -506,6 +525,7 @@ function Connect-HVEvent { ) begin { + [System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient") | Out-Null # Connect to Connection Server and call the View API service $services = Get-ViewAPIService -hvServer $hvServer if ($null -eq $services) { @@ -594,8 +614,8 @@ function Disconnect-HVEvent { Connection object returned by Connect-HVEvent advanced function. This is a mandatory input. .EXAMPLE - Disconnecting the database connection on $hvDbServer. Disconnect-HVEvent -HvDbServer $hvDbServer + Disconnecting the database connection on $hvDbServer. .OUTPUTS None @@ -603,11 +623,11 @@ function Disconnect-HVEvent { .NOTES Author : Paramesh Oddepally. Author email : poddepally@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -684,15 +704,15 @@ function Get-HVEvent { String that can applied in filtering on 'Message' column. .EXAMPLE + C:\PS>$e = Get-HVEvent -hvDbServer $hvDbServer + C:\PS>$e.Events Querying all the database events on database $hvDbServer. - $e = Get-HVEvent -hvDbServer $hvDbServer - $e.Events .EXAMPLE + C:\PS>$e = Get-HVEvent -HvDbServer $hvDbServer -TimePeriod 'all' -FilterType 'startsWith' -UserFilter 'aduser' -SeverityFilter 'err' -TimeFilter 'HH:MM:SS.fff' -ModuleFilter 'broker' -MessageFilter 'aduser' + C:\PS>$e.Events | Export-Csv -Path 'myEvents.csv' -NoTypeInformation 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. @@ -700,11 +720,11 @@ function Get-HVEvent { .NOTES Author : Paramesh Oddepally. Author email : poddepally@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -904,38 +924,43 @@ function Get-HVFarm { .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 SuppressInfo + Suppress text info, when no farm found with given search parameters .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. + 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 in-place of hvServer. .EXAMPLE Get-HVFarm -FarmName 'Farm-01' + Queries and returns farmInfo based on given parameter farmName .EXAMPLE Get-HVFarm -FarmName 'Farm-01' -FarmDisplayName 'Sales RDS Farm' + Queries and returns farmInfo based on given parameters farmName, farmDisplayName .EXAMPLE Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' + Queries and returns farmInfo based on given parameters farmName, farmType .EXAMPLE Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' -Enabled $true + Queries and returns farmInfo based on given parameters farmName, FarmType etc .EXAMPLE - Get-HVFarm -FarmName 'Farm-01' + Get-HVFarm -FarmName 'Farm-0*' + Queries and returns farmInfo based on parameter farmName with wild character * .OUTPUTs - Returns the list of FarmSummaryView or FarmInfo object matching the query criteria. + Returns the list of FarmInfo object matching the query criteria. .NOTES - Author : Ankit Gupta. - Author email : guptaa@vmware.com - Version : 1.0 + Author : praveen mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -962,6 +987,10 @@ function Get-HVFarm { [boolean] $Enabled, + [Parameter(Mandatory = $false)] + [boolean] + $SuppressInfo = $false, + [Parameter(Mandatory = $false)] $HvServer = $null ) @@ -972,6 +1001,12 @@ function Get-HVFarm { break } $farmList = Find-HVFarm -Param $PSBoundParameters + if (! $farmList) { + if (! $SuppressInfo) { + Write-Host "Get-HVFarm: No Farm Found with given search parameters" + } + return $farmList + } $farm_service_helper = New-Object VMware.Hv.FarmService $queryResults = @() foreach ($id in $farmList.id) { @@ -991,48 +1026,56 @@ function Get-HVFarmSummary { 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 + FarmName to be searched .PARAMETER FarmDisplayName - farmDisplayName to be searched + FarmDisplayName to be searched .PARAMETER FarmType - farmType to be searched. It can take following values: + 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 + Search for farms which are enabled + +.PARAMETER SuppressInfo + Suppress text info, when no farm found with given search parameters .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. + 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 in-place of hvServer. .EXAMPLE - Get-HVFarm -FarmName 'Farm-01' + Get-HVFarmSummary -FarmName 'Farm-01' + Queries and returns farmSummary objects based on given parameter farmName .EXAMPLE - Get-HVFarm -FarmName 'Farm-01' -FarmDisplayName 'Sales RDS Farm' + Get-HVFarmSummary -FarmName 'Farm-01' -FarmDisplayName 'Sales RDS Farm' + Queries and returns farmSummary objects based on given parameters farmName, farmDisplayName .EXAMPLE - Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' + Get-HVFarmSummary -FarmName 'Farm-01' -FarmType 'MANUAL' + Queries and returns farmSummary objects based on given parameters farmName, farmType .EXAMPLE - Get-HVFarm -FarmName 'Farm-01' -FarmType 'MANUAL' -Enabled $true + Get-HVFarmSummary -FarmName 'Farm-01' -FarmType 'MANUAL' -Enabled $true + Queries and returns farmSummary objects based on given parameters farmName, FarmType etc .EXAMPLE - Get-HVFarm -FarmName 'Farm-01' + Get-HVFarmSummary -FarmName 'Farm-0*' + Queries and returns farmSummary objects based on given parameter farmName with wild character * .OUTPUTs - Returns the list of FarmSummaryView or FarmInfo object matching the query criteria. + Returns the list of FarmSummary object matching the query criteria. .NOTES Author : Praveen Mathamsetty. Author email : pmathamsetty@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -1059,6 +1102,10 @@ function Get-HVFarmSummary { [boolean] $Enabled, + [Parameter(Mandatory = $false)] + [boolean] + $SuppressInfo = $false, + [Parameter(Mandatory = $false)] $HvServer = $null ) @@ -1069,7 +1116,10 @@ function Get-HVFarmSummary { break } $farmList = Find-HVFarm -Param $PSBoundParameters - return $farmList + if (!$farmList -and !$SuppressInfo) { + Write-Host "Get-HVFarmSummary: No Farm Found with given search parameters" + } + Return $farmList } function Find-HVFarm { @@ -1092,27 +1142,51 @@ function Find-HVFarm { $query_service_helper = New-Object VMware.Hv.QueryServiceService $query = New-Object VMware.Hv.QueryDefinition + $wildcard = $false # build the query values + if ($params['FarmName'] -and $params['FarmName'].contains('*')) { + $wildcard = $true + } + if ($params['FarmDisplayName'] -and $params['FarmDisplayName'].contains('*')) { + $wildcard = $true + } $query.queryEntityType = 'FarmSummaryView' - [VMware.Hv.queryfilter[]]$filterSet = @() - foreach ($setting in $farmSelectors.Keys) { - if ($null -ne $params[$setting]) { - $equalsFilter = New-Object VMware.Hv.QueryFilterEquals - $equalsFilter.memberName = $farmSelectors[$setting] - $equalsFilter.value = $params[$setting] - $filterSet += $equalsFilter + if (! $wildcard) { + [VMware.Hv.queryfilter[]]$filterSet = @() + foreach ($setting in $farmSelectors.Keys) { + if ($null -ne $params[$setting]) { + $equalsFilter = New-Object VMware.Hv.QueryFilterEquals + $equalsFilter.memberName = $farmSelectors[$setting] + $equalsFilter.value = $params[$setting] + $filterSet += $equalsFilter + } + } + if ($filterSet.Count -gt 0) { + $queryList = New-Object VMware.Hv.QueryFilterAnd + $queryList.Filters = $filterset + $query.Filter = $queryList } - } - 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 - + $queryResults = $query_service_helper.QueryService_Query($services, $query) + $farmList = $queryResults.results + } elseif ($wildcard -or [string]::IsNullOrEmpty($farmList)){ + $query.Filter = $null + $queryResults = $query_service_helper.QueryService_Query($services,$query) + $strFilterSet = @() + foreach ($setting in $farmSelectors.Keys) { + if ($null -ne $params[$setting]) { + if ($wildcard -and (($setting -eq 'FarmName') -or ($setting -eq 'FarmDisplayName')) ) { + $strFilterSet += '($_.' + $farmSelectors[$setting] + ' -like "' + $params[$setting] + '")' + } else { + $strFilterSet += '($_.' + $farmSelectors[$setting] + ' -eq "' + $params[$setting] + '")' + } + } + } + $whereClause = [string]::Join(' -and ', $strFilterSet) + $scriptBlock = [Scriptblock]::Create($whereClause) + $farmList = $queryResults.results | where $scriptBlock + } Return $farmList } @@ -1156,33 +1230,40 @@ function Get-HVPool { 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 SuppressInfo + Suppress text info, when no pool found with given search parameters + .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 + first element from global:DefaultHVServers would be considered in-place of hvServer .EXAMPLE Get-HVPool -PoolName 'mypool' -PoolType MANUAL -UserAssignment FLOATING -Enabled $true -ProvisioningEnabled $true + Queries and returns pool object(s) based on given parameters poolName, poolType etc. .EXAMPLE Get-HVPool -PoolType AUTOMATED -UserAssignment FLOATING + Queries and returns pool object(s) based on given parameters poolType and userAssignment .EXAMPLE Get-HVPool -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false + Queries and returns pool object(s) based on given parameters poolName, PoolType etc. .EXAMPLE Get-HVPool -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false -HvServer $mycs + Queries and returns pool object(s) based on given parameters poolName and HvServer etc. .OUTPUTS - Returns list of objects of type Desktop + Returns list of objects of type DesktopInfo .NOTES Author : Praveen Mathamsetty. Author email : pmathamsetty@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -1218,6 +1299,10 @@ function Get-HVPool { [boolean] $ProvisioningEnabled, + [Parameter(Mandatory = $false)] + [boolean] + $SuppressInfo = $false, + [Parameter(Mandatory = $false)] $HvServer = $null ) @@ -1228,6 +1313,12 @@ function Get-HVPool { break } $poolList = Find-HVPool -Param $PSBoundParameters + if (! $poolList) { + if (! $SuppressInfo) { + Write-Host "Get-HVPool: No Pool Found with given search parameters" + } + return $poolList + } $queryResults = @() $desktop_helper = New-Object VMware.Hv.DesktopService foreach ($id in $poolList.id) { @@ -1278,21 +1369,28 @@ function Get-HVPoolSummary { 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 SuppressInfo + Suppress text info, when no pool found with given search parameters + .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 + first element from global:DefaultHVServers would be considered in-place of hvServer .EXAMPLE Get-HVPoolSummary -PoolName 'mypool' -PoolType MANUAL -UserAssignment FLOATING -Enabled $true -ProvisioningEnabled $true + Queries and returns desktopSummaryView based on given parameters poolName, poolType etc. .EXAMPLE Get-HVPoolSummary -PoolType AUTOMATED -UserAssignment FLOATING + Queries and returns desktopSummaryView based on given parameters poolType, userAssignment. .EXAMPLE Get-HVPoolSummary -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false + Queries and returns desktopSummaryView based on given parameters poolName, poolType, userAssignment etc. .EXAMPLE Get-HVPoolSummary -PoolName 'myrds' -PoolType RDS -UserAssignment DEDICATED -Enabled $false -HvServer $mycs + Queries and returns desktopSummaryView based on given parameters poolName, HvServer etc. .OUTPUTS Returns list of DesktopSummaryView @@ -1300,11 +1398,11 @@ function Get-HVPoolSummary { .NOTES Author : Praveen Mathamsetty. Author email : pmathamsetty@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -1340,6 +1438,10 @@ function Get-HVPoolSummary { [boolean] $ProvisioningEnabled, + [Parameter(Mandatory = $false)] + [boolean] + $SuppressInfo = $false, + [Parameter(Mandatory = $false)] $HvServer = $null ) @@ -1349,8 +1451,11 @@ function Get-HVPoolSummary { Write-Error "Could not retrieve ViewApi services from connection object" break } - $poolList = Find-HVPool -Param $psboundparameters - Return $poolList + $pool_list = Find-HVPool -Param $psboundparameters + if (!$pool_list -and !$suppressInfo) { + Write-Host "Get-HVPoolSummary: No Pool Found with given search parameters" + } + Return $pool_list } function Find-HVPool { @@ -1468,32 +1573,40 @@ function Get-HVQueryFilter { .EXAMPLE Get-HVQueryFilter data.name -Eq vmware + Creates queryFilterEquals with given parameters memberName(position 0) and memberValue(position 2) .EXAMPLE Get-HVQueryFilter -MemberName data.name -Eq -MemberValue vmware + Creates queryFilterEquals with given parameters memberName and memberValue .EXAMPLE Get-HVQueryFilter data.name -Ne vmware + Creates queryFilterNotEquals filter with given parameters memberName and memberValue .EXAMPLE Get-HVQueryFilter data.name -Contains vmware + Creates queryFilterContains with given parameters memberName and memberValue .EXAMPLE Get-HVQueryFilter data.name -Startswith vmware + Creates queryFilterStartsWith with given parameters memberName and memberValue .EXAMPLE - $filter = Get-HVQueryFilter data.name -Startswith vmware - Get-HVQueryFilter -Not $filter + C:\PS>$filter = Get-HVQueryFilter data.name -Startswith vmware + C:\PS>Get-HVQueryFilter -Not $filter + Creates queryFilterNot with given parameter filter .EXAMPLE - $filter1 = Get-HVQueryFilter data.name -Startswith vmware - $filter2 = Get-HVQueryFilter data.name -Contains pool - Get-HVQueryFilter -And @($filter1, $filter2) + C:\PS>$filter1 = Get-HVQueryFilter data.name -Startswith vmware + C:\PS>$filter2 = Get-HVQueryFilter data.name -Contains pool + C:\PS>Get-HVQueryFilter -And @($filter1, $filter2) + Creates queryFilterAnd with given parameter filters array .EXAMPLE - $filter1 = Get-HVQueryFilter data.name -Startswith vmware - $filter2 = Get-HVQueryFilter data.name -Contains pool - Get-HVQueryFilter -Or @($filter1, $filter2) + C:\PS>$filter1 = Get-HVQueryFilter data.name -Startswith vmware + C:\PS>$filter2 = Get-HVQueryFilter data.name -Contains pool + C:\PS>Get-HVQueryFilter -Or @($filter1, $filter2) + Creates queryFilterOr with given parameter filters array .OUTPUTS Returns the QueryFilter object @@ -1501,11 +1614,11 @@ function Get-HVQueryFilter { .NOTES Author : Kummara Ramamohan. Author email : kramamohan@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> [CmdletBinding()] @@ -1616,26 +1729,28 @@ function Get-HVQueryResult { .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 + first element from global:DefaultHVServers would be considered in-place of hvServer .EXAMPLE Get-HVQueryResult DesktopSummaryView + Returns query results of entityType DesktopSummaryView(position 0) .EXAMPLE Get-HVQueryResult DesktopSummaryView (Get-HVQueryFilter data.name -Eq vmware) + Returns query results of entityType DesktopSummaryView(position 0) with given filter(position 1) .EXAMPLE Get-HVQueryResult -EntityType DesktopSummaryView -Filter (Get-HVQueryFilter desktopSummaryData.name -Eq vmware) + Returns query results of entityType DesktopSummaryView with given filter .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 + C:\PS>$myFilter = Get-HVQueryFilter data.name -Contains vmware + C:\PS>Get-HVQueryResult -EntityType DesktopSummaryView -Filter $myFilter -SortBy desktopSummaryData.displayName -SortDescending $false + Returns query results of entityType DesktopSummaryView with given filter and also sorted based on dispalyName .EXAMPLE Get-HVQueryResult DesktopSummaryView -Limit 10 + Returns query results of entityType DesktopSummaryView, maximum count equal to limit .OUTPUTS Returns the list of objects of entityType @@ -1643,11 +1758,11 @@ function Get-HVQueryResult { .NOTES Author : Kummara Ramamohan. Author email : kramamohan@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -1723,6 +1838,7 @@ function Get-HVQueryResult { } } + function New-HVFarm { <# .Synopsis @@ -1734,6 +1850,9 @@ function New-HVFarm { .PARAMETER LinkedClone Switch to Create Automated Linked Clone farm. +.PARAMETER InstantClone + Switch to Create Automated Instant Clone farm. + .PARAMETER Manual Switch to Create Manual farm. @@ -1758,38 +1877,38 @@ function New-HVFarm { .PARAMETER ParentVM Base image VM for RDS Servers. - Applicable only to Linked Clone farms. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER SnapshotVM Base image snapshot for RDS Servers. .PARAMETER VmFolder VM folder to deploy the RDSServers to. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER HostOrCluster Host or cluster to deploy the RDSServers in. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER ResourcePool Resource pool to deploy the RDSServers. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER Datastores Datastore names to store the RDSServer. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER UseVSAN Whether to use vSphere VSAN. This is applicable for vSphere 5.5 or later. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER EnableProvisioning Set to true to enable provision of RDSServers immediately in farm. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER StopOnProvisioningError Set to true to stop provisioning of all RDSServers on error. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER TransparentPageSharingScope The transparent page sharing scope. @@ -1798,7 +1917,7 @@ function New-HVFarm { .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. + The default value is PATTERN. Currently only PATTERN is allowed. .PARAMETER NamingPattern RDS Servers will be named according to the specified naming pattern. @@ -1813,26 +1932,42 @@ function New-HVFarm { .PARAMETER MaximumCount Maximum number of Servers in the farm. The default value is 1. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant 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. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER NetBiosName Domain Net Bios Name. - Applicable to Linked Clone farms. + Applicable to Linked Clone and Instant 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. + Applicable to Linked Clone and Instant Clone farms. .PARAMETER SysPrepName The customization spec to use. Applicable to Linked Clone farms. +.PARAMETER PowerOffScriptName + Power off script. ClonePrep can run a customization script on instant-clone machines before they are powered off. Provide the path to the script on the parent virtual machine. + Applicable to Instant Clone farms. + +.PARAMETER PowerOffScriptParameters + Power off script parameters. Example: p1 p2 p3 + Applicable to Instant Clone farms. + +.PARAMETER PostSynchronizationScriptName + Post synchronization script. ClonePrep can run a customization script on instant-clone machines after they are created or recovered or a new image is pushed. Provide the path to the script on the parent virtual machine. + Applicable to Instant Clone farms. + +.PARAMETER PostSynchronizationScriptParameters + Post synchronization script parameters. Example: p1 p2 p3 + Applicable to Instant Clone farms. + .PARAMETER RdsServers List of existing registered RDS server names to add into manual farm. Applicable to Manual farms. @@ -1841,28 +1976,43 @@ function New-HVFarm { 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. + 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 in-place 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" + 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" + Creates new linkedClone farm by using naming pattern .EXAMPLE - New-HVFarm -Spec C:\VMWare\Specs\LinkedClone.json + New-HVFarm -InstantClone -FarmName 'ICFarmCL' -ParentVM 'vm-rdsh-ic' -SnapshotVM 'Snap_5' -VmFolder 'Instant_Clone_VMs' -HostOrCluster 'vimal-cluster' -ResourcePool 'vimal-cluster' -Datastores 'datastore1' -FarmDisplayName 'IC Farm using CL' -Description 'created IC Farm from PS command-line' -EnableProvisioning $true -StopOnProvisioningError $false -NamingPattern "ICFarmCL-" -NetBiosName "ad-vimalg" + Creates new linkedClone farm by using naming pattern .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" + New-HVFarm -Spec C:\VMWare\Specs\LinkedClone.json -Confirm:$false + Creates new linkedClone farm by using json file + +.EXAMPLE + New-HVFarm -Spec C:\VMWare\Specs\InstantCloneFarm.json -Confirm:$false + Creates new instantClone farm by using json file + +.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" -Confirm:$false + Creates new manual farm by using rdsServers names + +.EXAMPLE + New-HVFarm -Spec C:\VMWare\Specs\AutomatedInstantCloneFarm.json -FarmName 'InsPool' -NamingPattern 'InsFarm-' + Creates new instant clone farm by reading few parameters from json and few parameters from command line. .OUTPUTS None .NOTES - Author : Ankit Gupta. - Author email : guptaa@vmware.com - Version : 1.0 + Author : praveen mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -1876,6 +2026,10 @@ function New-HVFarm { [switch] $LinkedClone, + [Parameter(Mandatory = $true,ParameterSetName = "INSTANT_CLONE")] + [switch] + $InstantClone, + [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] [switch] $Manual, @@ -1883,6 +2037,8 @@ function New-HVFarm { #farmSpec.farmData.name [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = "INSTANT_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'JSON_FILE')] [string] $FarmName, @@ -1906,102 +2062,274 @@ function New-HVFarm { [boolean] $Enable = $true, - #farmSpec.automatedfarmSpec.virtualCenter if LINKED_CLONE + #farmSpec.data.settings.disconnectedSessionTimeoutPolicy + [Parameter(Mandatory = $false)] + [ValidateSet("IMMEDIATE","NEVER","AFTER")] + [string] + $DisconnectedSessionTimeoutPolicy = "NEVER", + + #farmSpec.data.settings.disconnectedSessionTimeoutMinutes + [Parameter(Mandatory = $false)] + [ValidateRange(1,[Int]::MaxValue)] + [int] + $DisconnectedSessionTimeoutMinutes, + + #farmSpec.data.settings.emptySessionTimeoutPolicy + [Parameter(Mandatory = $false)] + [ValidateSet("NEVER","AFTER")] + [string] + $EmptySessionTimeoutPolicy = "AFTER", + + #farmSpec.data.settings.emptySessionTimeoutMinutes + [Parameter(Mandatory = $false)] + [ValidateSet(1,[Int]::MaxValue)] + [int] + $EmptySessionTimeoutMinutes = 1, + + #farmSpec.data.settings.logoffAfterTimeout + [Parameter(Mandatory = $false)] + [boolean] + $LogoffAfterTimeout = $false, + + #farmSpec.data.displayProtocolSettings.defaultDisplayProtocol + [Parameter(Mandatory = $false)] + [ValidateSet("RDP","PCOIP","BLAST")] + [string] + $DefaultDisplayProtocol = "PCOIP", + + #farmSpec.data.displayProtocolSettings.allowDisplayProtocolOverride + [Parameter(Mandatory = $false)] + [boolean] + $AllowDisplayProtocolOverride = $true, + + #farmSpec.data.displayProtocolSettings.enableHTMLAccess + [Parameter(Mandatory = $false)] + [boolean] + $EnableHTMLAccess = $false, + + #farmSpec.data.serverErrorThreshold + [Parameter(Mandatory = $false)] + [ValidateRange(0,[Int]::MaxValue)] + $ServerErrorThreshold = 0, + + #farmSpec.data.mirageConfigurationOverrides.overrideGlobalSetting + [Parameter(Mandatory = $false)] + [boolean] + $OverrideGlobalSetting = $false, + + #farmSpec.data.mirageConfigurationOverrides.enabled + [Parameter(Mandatory = $false)] + [boolean] + $MirageServerEnabled, + + #farmSpec.data.mirageConfigurationOverrides.url + [Parameter(Mandatory = $false)] + [string] + $Url, + + #farmSpec.automatedfarmSpec.virtualCenter if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [string] $Vcenter, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVM if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.parentVM if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] [string] $ParentVM, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshotVM if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.snapshotVM if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] [string] $SnapshotVM, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.vmFolder if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] [string] $VmFolder, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.hostOrCluster if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.hostOrCluster if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] [string] $HostOrCluster, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.resourcePool if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.resourcePool if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] [string] $ResourcePool, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.dataCenter if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [string] + $dataCenter, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] [string[]] $Datastores, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.useVSAN if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastores.storageOvercommit if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] - [string] - $UseVSAN, + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [string[]] + $StorageOvercommit = $null, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.useVSAN if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [boolean] + $UseVSAN = $false, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [boolean] $EnableProvisioning = $true, - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.stopOnProvisioningError if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [boolean] $StopOnProvisioningError = $true, [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [string] $TransparentPageSharingScope = 'VM', - #farmSpec.automatedfarmSpec.rdsServerNamingSpec.namingMethod if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.namingMethod if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [ValidateSet('PATTERN')] [string] $NamingMethod = 'PATTERN', - #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.namingPattern if LINKED_CLONE + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.namingPattern if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'JSON_FILE')] [string] $NamingPattern = $farmName + '{n:fixed=4}', - #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [int] $MinReady = 0, - #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers if LINKED_CLONE + #farmSpec.automatedfarmSpec.rdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [int] $MaximumCount = 1, - #farmSpec.automatedfarmSpec.customizationSettings.adContainer if LINKED_CLONE + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.useSeparateDatastoresReplicaAndOSDisks if INSTANT_CLONE, LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [boolean] + $UseSeparateDatastoresReplicaAndOSDisks = $false, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.replicaDiskDatastore, if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [string] + $ReplicaDiskDatastore, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.useNativeSnapshots, if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [boolean] + $UseNativeSnapshots = $false, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.spaceReclamationSettings.reclaimVmDiskSpace, if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [boolean] + $ReclaimVmDiskSpace = $false, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.spaceReclamationSettings.reclamationThresholdGB + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(0,[Int]::MaxValue)] + [int] + $ReclamationThresholdGB = 1, + + #farmSpec.automatedfarmSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.spaceReclamationSettings.blackoutTimes + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [VMware.Hv.FarmBlackoutTime[]] + $BlackoutTimes, + + #farmSpec.automatedfarmSpec.customizationSettings.adContainer if LINKED_CLONE, INSTANT_CLONE [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = "INSTANT_CLONE")] [string] $AdContainer = 'CN=Computers', #farmSpec.automatedfarmSpec.customizationSettings.domainAdministrator + #farmSpec.automatedfarmSpec.customizationSettings.cloneprepCustomizationSettings.instantCloneEngineDomainAdministrator [Parameter(Mandatory = $true,ParameterSetName = 'LINKED_CLONE')] + [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] [string] $NetBiosName, #farmSpec.automatedfarmSpec.customizationSettings.domainAdministrator + #farmSpec.automatedfarmSpec.customizationSettings.cloneprepCustomizationSettings.instantCloneEngineDomainAdministrator [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = "INSTANT_CLONE")] [string] $DomainAdmin = $null, + #farmSpec.automatedfarmSpec.customizationSettings.reusePreExistingAccounts + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [Boolean] + $ReusePreExistingAccounts = $false, + #farmSpec.automatedfarmSpec.customizationSettings.sysprepCustomizationSettings.customizationSpec if LINKED_CLONE [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] [string] $SysPrepName, - ##farmSpec.manualfarmSpec.rdsServers + #desktopSpec.automatedfarmSpec.customizationSettings.cloneprepCustomizationSettings.powerOffScriptName if INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [string] + $PowerOffScriptName, + + #farmSpec.automatedfarmSpec.customizationSettings.cloneprepCustomizationSettings.powerOffScriptParameters if INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [string] + $PowerOffScriptParameters, + + #farmSpec.automatedfarmSpec.customizationSettings.cloneprepCustomizationSettings.postSynchronizationScriptName if INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [string] + $PostSynchronizationScriptName, + + #farmSpec.automatedfarmSpec.customizationSettings.cloneprepCustomizationSettings.postSynchronizationScriptParameters if INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [string] + $PostSynchronizationScriptParameters, + + #farmSpec.automatedfarmSpec.rdsServerMaxSessionsData.maxSessionsType if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = "INSTANT_CLONE")] + [ValidateSet("UNLIMITED", "LIMITED")] + [string] + $MaxSessionsType = "UNLIMITED", + + #farmSpec.automatedfarmSpec.rdsServerMaxSessionsData.maxSessionsType if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = "INSTANT_CLONE")] + [ValidateRange(1, [int]::MaxValue)] + [int] + $MaxSessions, + + #farmSpec.manualfarmSpec.rdsServers [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] [string[]] $RdsServers, @@ -2033,6 +2361,9 @@ function New-HVFarm { # ADContainerId # FarmSysprepCustomizationSettings # CustomizationSpecId + # FarmCloneprepCustomizationSettings + # InstantCloneEngineDomainAdministratorId + # # FarmManualfarmSpec # RDSServerId[] # @@ -2046,12 +2377,12 @@ function New-HVFarm { } process { - + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys if ($farmName) { try { - $sourceFarm = Get-HVFarm -farmName $farmName -hvServer $hvServer + $sourceFarm = Get-HVFarmSummary -farmName $farmName -hvServer $hvServer -suppressInfo $true } catch { - Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + Write-Error "Make sure Get-HVFarmSummary advanced function is loaded, $_" break } if ($sourceFarm) { @@ -2067,18 +2398,51 @@ function New-HVFarm { Write-Error "Json file exception, $_" break } + try { + Test-HVFarmSpec -PoolObject $jsonObject + } catch { + Write-Error "Json object validation failed, $_" + break + } if ($jsonObject.type -eq 'AUTOMATED') { $farmType = 'AUTOMATED' + $provisioningType = $jsonObject.ProvisioningType if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenter) { $vCenter = $jsonObject.AutomatedFarmSpec.VirtualCenter } - $linkedClone = $true + $netBiosName = $jsonObject.NetBiosName - $adContainer = $jsonObject.AutomatedFarmSpec.CustomizationSettings.AdContainer + if (!$jsonObject.AutomatedFarmSpec.CustomizationSettings.AdContainer) { + Write-Host "adContainer was empty using CN=Computers" + } else { + $AdContainer = $jsonObject.AutomatedFarmSpec.CustomizationSettings.AdContainer + } + + #populate customization settings attributes based on the cutomizationType + if ($jsonObject.AutomatedFarmSpec.ProvisioningType -eq "INSTANT_CLONE_ENGINE") { + $InstantClone = $true + if ($null -ne $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings) { + $DomainAdmin = $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator + $powerOffScriptName = $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.PowerOffScriptName + $powerOffScriptParameters = $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.PowerOffScriptParameters + $postSynchronizationScriptName = $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.PostSynchronizationScriptName + $postSynchronizationScriptParameters = $jsonObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.PostSynchronizationScriptParameters + } + } elseif ($jsonObject.AutomatedFarmSpec.ProvisioningType -eq "VIEW_COMPOSER") { + $LinkedClone = $true + $DomainAdmin = $jsonObject.AutomatedFarmSpec.CustomizationSettings.domainAdministrator + $reusePreExistingAccounts = $jsonObject.AutomatedFarmSpec.CustomizationSettings.ReusePreExistingAccounts + $sysPrepName = $jsonObject.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec + } $namingMethod = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.NamingMethod - $namingPattern = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern + if ($NamingPattern -eq '{n:fixed=4}') { + $namingPattern = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern + } $maximumCount = $jsonObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.maxNumberOfRDSServers + $enableProvisioning = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.EnableProvisioning + $stopProvisioningOnError = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.StopProvisioningOnError + $minReady = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.MinReadyVMsOnVComposerMaintenance $transparentPageSharingScope = $jsonObject.AutomatedFarmSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope @@ -2092,10 +2456,44 @@ function New-HVFarm { $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 + $storageOvercommit += $dtStore.StorageOvercommit } - $sysPrepName = $jsonObject.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec + $useVSan = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.UseVSan + + ## ViewComposerStorageSettings for Linked-Clone farms + if ($LinkedClone -or $InstantClone) { + $useSeparateDatastoresReplicaAndOSDisks = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.ViewComposerStorageSettings.UseSeparateDatastoresReplicaAndOSDisks + if ($useSeparateDatastoresReplicaAndOSDisks) { + $replicaDiskDatastore = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.ViewComposerStorageSettings.ReplicaDiskDatastore + } + if ($LinkedClone) { + #For Instant clone desktops, this setting can only be set to false + $useNativeSnapshots = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.ViewComposerStorageSettings.UseNativeSnapshots + $reclaimVmDiskSpace = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.ViewComposerStorageSettings.SpaceReclamationSettings.ReclaimVmDiskSpace + if ($reclaimVmDiskSpace) { + $ReclamationThresholdGB = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.ViewComposerStorageSettings.SpaceReclamationSettings.ReclamationThresholdGB + if ($null -ne $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.ViewComposerStorageSettings.SpaceReclamationSettings.blackoutTimes) { + $blackoutTimesList = $jsonObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.ViewComposerStorageSettings.SpaceReclamationSettings.blackoutTimes + foreach ($blackout in $blackoutTimesList) { + $blackoutObj = New-Object VMware.Hv.DesktopBlackoutTime + $blackoutObj.Days = $blackout.Days + $blackoutObj.StartTime = $blackout.StartTime + $blackoutObj.EndTime = $blackoutObj.EndTime + $blackoutTimes += $blackoutObj + } + } + } + } + } + + $maxSessionsType = $jsonObject.AutomatedFarmSpec.RdsServerMaxSessionsData.MaxSessionsType + if ($maxSessionsType -eq "LIMITED") { + $maxSessions = $jsonObject.AutomatedFarmSpec.RdsServerMaxSessionsData.MaxSessions + } + } elseif ($jsonObject.type -eq 'MANUAL') { $manual = $true $farmType = 'MANUAL' @@ -2105,16 +2503,44 @@ function New-HVFarm { $rdsServers += $RdsServerObj.rdsServer } } - $farmDisplayName = $jsonObject.data.DisplayName - $description = $jsonObject.data.Description - $accessGroup = $jsonObject.data.AccessGroup - $farmName = $jsonObject.data.name + $farmDisplayName = $jsonObject.Data.DisplayName + $description = $jsonObject.Data.Description + $accessGroup = $jsonObject.Data.AccessGroup + if (! $FarmName) { + $farmName = $jsonObject.Data.name + } + if ($null -ne $jsonObject.Data.Enabled) { + $enable = $jsonObject.Data.Enabled + } + if ($null -ne $jsonObject.Data.Settings) { + $disconnectedSessionTimeoutPolicy = $jsonObject.Data.Settings.DisconnectedSessionTimeoutPolicy + $disconnectedSessionTimeoutMinutes = $jsonObject.Data.Settings.DisconnectedSessionTimeoutMinutes + $emptySessionTimeoutPolicy = $jsonObject.Data.Settings.EmptySessionTimeoutPolicy + $emptySessionTimeoutMinutes = $jsonObject.Data.Settings.EmptySessionTimeoutMinutes + $logoffAfterTimeout = $jsonObject.Data.Settings.LogoffAfterTimeout + } + if ($null -ne $jsonObject.Data.DisplayProtocolSettings) { + $defaultDisplayProtocol = $jsonObject.Data.DisplayProtocolSettings.DefaultDisplayProtocol + $allowDisplayProtocolOverride = $jsonObject.Data.DisplayProtocolSettings.AllowDisplayProtocolOverride + $enableHTMLAccess = $jsonObject.Data.DisplayProtocolSettings.EnableHTMLAccess + } + if ($null -ne $jsonObject.Data.serverErrorThreshold) { + $serverErrorThreshold = $jsonObject.Data.serverErrorThreshold + } + if ($null -ne $jsonObject.Data.MirageConfigurationOverrides) { + $overrideGlobalSetting = $jsonObject.Data.MirageConfigurationOverrides.OverrideGlobalSetting + $mirageserverEnabled = $jsonObject.Data.MirageConfigurationOverrides.Enabled + $url = $jsonObject.Data.MirageConfigurationOverrides.url + } } if ($linkedClone) { $farmType = 'AUTOMATED' $provisioningType = 'VIEW_COMPOSER' - } elseif ($manual) { + } elseif ($InstantClone) { + $farmType = 'AUTOMATED' + $provisioningType = 'INSTANT_CLONE_ENGINE' + }elseif ($manual) { $farmType = 'MANUAL' } @@ -2167,17 +2593,17 @@ function New-HVFarm { $farmVirtualCenterManagedCommonSettings = $farmSpecObj.AutomatedFarmSpec.virtualCenterManagedCommonSettings } - if (!$farmVirtualMachineNamingSpec) { + if ($farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec) { $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.NamingMethod = $namingMethod $vmNamingSpec.patternNamingSettings = New-Object VMware.Hv.FarmPatternNamingSettings $vmNamingSpec.patternNamingSettings.namingPattern = $namingPattern $vmNamingSpec.patternNamingSettings.maxNumberOfRDSServers = $maximumCount + $farmSpecObj.AutomatedFarmSpec.RdsServerNamingSpec = $vmNamingSpec } # @@ -2185,8 +2611,10 @@ function New-HVFarm { # try { $farmVirtualCenterProvisioningData = Get-HVFarmProvisioningData -vc $virtualCenterID -vmObject $farmVirtualCenterProvisioningData - $hostClusterId = $farmVirtualCenterProvisioningData.HostOrCluster - $farmVirtualCenterStorageSettings = Get-HVFarmStorageObject -hostclusterID $hostClusterId -storageObject $farmVirtualCenterStorageSettings + + $HostOrCluster_helper = New-Object VMware.Hv.HostOrClusterService + $hostClusterIds = (($HostOrCluster_helper.HostOrCluster_GetHostOrClusterTree($services, $farmVirtualCenterProvisioningData.datacenter)).treeContainer.children.info).Id + $farmVirtualCenterStorageSettings = Get-HVFarmStorageObject -hostclusterIDs $hostClusterIds -storageObject $farmVirtualCenterStorageSettings $farmVirtualCenterNetworkingSettings = Get-HVFarmNetworkSetting -networkObject $farmVirtualCenterNetworkingSettings $farmCustomizationSettings = Get-HVFarmCustomizationSetting -vc $virtualCenterID -customObject $farmCustomizationSettings } catch { @@ -2195,31 +2623,20 @@ function New-HVFarm { 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 + $farmSpecObj.AutomatedFarmSpec.RdsServerMaxSessionsData.MaxSessionsType = $maxSessionsType + if ($maxSessionsType -eq "LIMITED") { + $farmSpecObj.AutomatedFarmSpec.RdsServerMaxSessionsData.MaxSessionsType = $maxSessions } + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.enableProvisioning = $enableProvisioning + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $stopProvisioningOnError + $farmSpecObj.AutomatedFarmSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = $minReady + $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 } } @@ -2235,6 +2652,29 @@ function New-HVFarm { $farmData.name = $farmName $farmData.DisplayName = $farmDisplayName $farmData.Description = $description + if ($farmData.Settings) { + $farmData.Settings.DisconnectedSessionTimeoutPolicy = $disconnectedSessionTimeoutPolicy + if ($disconnectedSessionTimeoutPolicy -eq "AFTER") { + $farmData.Settings.DisconnectedSessionTimeoutMinutes = $disconnectedSessionTimeoutMinutes + } + $farmData.Settings.EmptySessionTimeoutPolicy = $emptySessionTimeoutPolicy + if ($emptySessionTimeoutPolicy -eq "AFTER") { + $farmData.Settings.EmptySessionTimeoutMinutes = $emptySessionTimeoutMinutes + } + $logoffAfterTimeout = $farmData.Settings.logoffAfterTimeout + } + if ($farmData.DisplayProtocolSettings) { + $farmData.DisplayProtocolSettings.DefaultDisplayProtocol = $defaultDisplayProtocol + $farmData.DisplayProtocolSettings.AllowDisplayProtocolOverride = $AllowDisplayProtocolOverride + $farmData.DisplayProtocolSettings.EnableHTMLAccess = $enableHTMLAccess + } + if ($farmData.MirageConfigurationOverrides){ + $farmData.MirageConfigurationOverrides.OverrideGlobalSetting = $overrideGlobalSetting + $farmData.MirageConfigurationOverrides.Enabled = $mirageServerEnabled + if ($url) { + $farmData.MirageConfigurationOverrides.Url = $url + } + } $farmSpecObj.type = $farmType if ($FarmAutomatedFarmSpec) { @@ -2246,10 +2686,21 @@ function New-HVFarm { # 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) + $myDebug = convertto-json -InputObject $farmSpecObj -depth 12 + $myDebug | out-file -filepath c:\temp\copiedfarm.json + #> + + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($farmSpecObj.data.name)) { + $Id = $farm_service_helper.Farm_Create($services, $farmSpecObj) + } else { + try { + Test-HVFarmSpec -PoolObject $farmSpecObj + } catch { + Write-Error "FarmSpec object validation failed, $_" + break + } + } + return $farmSpecObj } end { @@ -2258,6 +2709,89 @@ $myDebug | out-file -filepath c:\temp\copiedfarm.json } +function Test-HVFarmSpec { + param( + [Parameter(Mandatory = $true)] + $PoolObject + ) + if ($null -eq $PoolObject.Type) { + Throw "Specify type of farm" + } + $jsonFarmTypeArray = @('AUTOMATED','MANUAL') + if (! ($jsonFarmTypeArray -contains $PoolObject.Type)) { + Throw "Farm type must be AUTOMATED or MANUAL" + } + if ($null -eq $PoolObject.Data.Name) { + Throw "Specify farm name" + } + if ($null -eq $PoolObject.Data.AccessGroup) { + Throw "Specify horizon access group" + } + if ($PoolObject.Type -eq "AUTOMATED"){ + $jsonProvisioningType = $PoolObject.AutomatedFarmSpec.ProvisioningType + if ($null -eq $jsonProvisioningType) { + Throw "Must specify provisioningType" + } + if ($null -eq $PoolObject.AutomatedFarmSpec.RdsServerNamingSpec.namingMethod) { + Throw "Must specify naming method to PATTERN" + } + if ($null -eq $PoolObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings) { + Throw "Specify Naming pattern settings" + } + if ($null -eq $PoolObject.AutomatedFarmSpec.RdsServerNamingSpec.patternNamingSettings.namingPattern) { + Throw "Specify specified naming pattern" + } + if ($null -eq $PoolObject.AutomatedFarmSpec.virtualCenterProvisioningSettings.enableProvisioning) { + Throw "Specify Whether to enable provisioning or not" + } + if ($null -eq $PoolObject.AutomatedFarmSpec.virtualCenterProvisioningSettings.stopProvisioningOnError) { + Throw "Specify Whether provisioning on all VMs stops on error" + } + $jsonTemplate = $PoolObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.Template + $jsonParentVm = $PoolObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.ParentVm + $jsonSnapshot = $PoolObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.Snapshot + $jsonVmFolder = $PoolObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.VmFolder + $jsonHostOrCluster = $PoolObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.HostOrCluster + $ResourcePool = $PoolObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.ResourcePool + if (!( ($null -ne $jsonTemplate) -or (($null -ne $jsonParentVm) -and ($null -ne $jsonSnapshot) )) ) { + Throw "Must specify Template or (ParentVm and Snapshot) names" + } + if ($null -eq $jsonVmFolder) { + Throw "Must specify VM folder to deploy the VMs" + } + if ($null -eq $jsonHostOrCluster) { + Throw "Must specify Host or cluster to deploy the VMs" + } + if ($null -eq $resourcePool) { + Throw "Must specify Resource pool to deploy the VMs" + } + if ($null -eq $PoolObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores) { + Throw "Must specify datastores names" + } + if ($null -eq $PoolObject.AutomatedFarmSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.useVSan) { + Throw "Must specify whether to use virtual SAN or not" + } + $customizationType = $PoolObject.AutomatedFarmSpec.CustomizationSettings.customizationType + if ($null -eq $customizationType) { + Throw "Specify customization type" + } + if ($customizationType -eq 'SYS_PREP' -and $null -eq $PoolObject.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings) { + Throw "Specify sysPrep customization settings" + } + if ($customizationType -eq 'CLONE_PREP' -and $null -eq $PoolObject.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings) { + Throw "Specify clone customization settings" + } + if ($null -eq $PoolObject.AutomatedFarmSpec.RdsServerMaxSessionsData.MaxSessionsType) { + Throw "Specify MaxSessionsType" + } + } elseif ($PoolObject.Type -eq "MANUAL") { + if ($null -eq $PoolObject.manualFarmSpec.rdsServers) { + Throw "Specify rdsServers name" + } + } +} + + function Get-HVFarmProvisioningData { param( [Parameter(Mandatory = $false)] @@ -2278,6 +2812,12 @@ function Get-HVFarmProvisioningData { } $vmObject.ParentVm = $parentVMObj.id $dataCenterID = $parentVMObj.datacenter + if ($dataCenter -and $dataCenterID) { + $baseImageVmInfo = $base_imageVm_helper.BaseImageVm_ListByDatacenter($dataCenterID) + if (! ($baseImageVmInfo.Path -like "/$dataCenter/*")) { + throw "$parentVM not exists in datacenter: [$dataCenter]" + } + } $vmObject.datacenter = $dataCenterID } if ($snapshotVM) { @@ -2330,23 +2870,30 @@ function Get-HVFarmProvisioningData { return $vmObject } + function Get-HVFarmStorageObject { param( - [Parameter(Mandatory = $false)] - [VMware.Hv.FarmVirtualCenterStorageSettings]$StorageObject, [Parameter(Mandatory = $true)] - [VMware.Hv.HostOrClusterId]$HostClusterID + [VMware.Hv.HostOrClusterId[]]$HostClusterIDs, + + [Parameter(Mandatory = $false)] + [VMware.Hv.FarmVirtualCenterStorageSettings]$StorageObject ) if (!$storageObject) { $storageObject = New-Object VMware.Hv.FarmVirtualCenterStorageSettings $FarmSpaceReclamationSettings = New-Object VMware.Hv.FarmSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $false } + if ($reclaimVmDiskSpace) { + $FarmSpaceReclamationSettings.ReclamationThresholdGB = $reclamationThresholdGB + if ($blackoutTimes) { + $FarmSpaceReclamationSettings.BlackoutTimes = $blackoutTimes + } + } $FarmViewComposerStorageSettingsList = @{ - 'useSeparateDatastoresReplicaAndOSDisks' = $false; - 'replicaDiskDatastore' = $FarmReplicaDiskDatastore - 'useNativeSnapshots' = $false; + 'useSeparateDatastoresReplicaAndOSDisks' = $UseSeparateDatastoresReplicaAndOSDisks; + 'useNativeSnapshots' = $useNativeSnapshots; 'spaceReclamationSettings' = $FarmSpaceReclamationSettings; } @@ -2354,18 +2901,35 @@ function Get-HVFarmStorageObject { } if ($datastores) { + if ($StorageOvercommit -and ($datastores.Length -ne $StorageOvercommit.Length) ) { + throw "Parameters datastores length: [$datastores.Length] and StorageOvercommit length: [$StorageOvercommit.Length] should be of same size" + } $Datastore_service_helper = New-Object VMware.Hv.DatastoreService - $datastoreList = $Datastore_service_helper.Datastore_ListDatastoresByHostOrCluster($services, $hostClusterID) + foreach ($hostClusterID in $hostClusterIDs) { + $datastoreList += $Datastore_service_helper.Datastore_ListDatastoresByHostOrCluster($services, $hostClusterID) + } $datastoresSelected = @() foreach ($ds in $datastores) { $datastoresSelected += ($datastoreList | Where-Object { $_.datastoredata.name -eq $ds }).id } + if (! $storageOvercommit) { + foreach ($ds in $datastoresSelected) { + $storageOvercommit += ,'UNBOUNDED' + } + } + $StorageOvercommitCnt = 0 foreach ($ds in $datastoresSelected) { $datastoresObj = New-Object VMware.Hv.FarmVirtualCenterDatastoreSettings $datastoresObj.Datastore = $ds - $datastoresObj.StorageOvercommit = 'UNBOUNDED' + $datastoresObj.StorageOvercommit = $storageOvercommit[$StorageOvercommitCnt] $StorageObject.Datastores += $datastoresObj } + if ($useSeparateDatastoresReplicaAndOSDisks) { + $StorageObject.ViewComposerStorageSettings.UseSeparateDatastoresReplicaAndOSDisks = $UseSeparateDatastoresReplicaAndOSDisks + $FarmReplicaDiskDatastore = ($datastoreList | Where-Object { $_.datastoredata.name -eq $replicaDiskDatastore }).id + $StorageObject.ViewComposerStorageSettings.ReplicaDiskDatastore = $FarmReplicaDiskDatastore + } + } if ($storageObject.Datastores.Count -eq 0) { throw "No datastores found with name: [$datastores]" @@ -2374,6 +2938,7 @@ function Get-HVFarmStorageObject { return $storageObject } + function Get-HVFarmNetworkSetting { param( [Parameter(Mandatory = $false)] @@ -2385,6 +2950,7 @@ function Get-HVFarmNetworkSetting { return $networkObject } + function Get-HVFarmCustomizationSetting { param( [Parameter(Mandatory = $false)] @@ -2394,44 +2960,98 @@ function Get-HVFarmCustomizationSetting { [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 -match $netBiosName }) - if (! [string]::IsNullOrWhitespace($domainAdmin)) { - $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministratorID | Where-Object { $_.base.userName -ieq $domainAdmin }).id - } else { - $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id + # 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 + $ADDomains = $ad_domain_helper.ADDomain_List($services) + if ($netBiosName) { + $adDomianId = ($ADDomains | Where-Object { $_.NetBiosName -eq $netBiosName } | Select-Object -Property id) + if ($null -eq $adDomianId) { + throw "No Domain found with netBiosName: [$netBiosName]" + } + } else { + $adDomianId = ($ADDomains[0] | Select-Object -Property id) + if ($null -eq $adDomianId) { + throw "No Domain configured in view administrator UI" + } + } + $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]" + } + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.AdContainer = $adContainerId } - 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]" + if ($InstantClone) { + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CustomizationType = 'CLONE_PREP' + $instantCloneEngineDomainAdministrator_helper = New-Object VMware.Hv.InstantCloneEngineDomainAdministratorService + $insDomainAdministrators = $instantCloneEngineDomainAdministrator_helper.InstantCloneEngineDomainAdministrator_List($services) + $strFilterSet = @() + if (![string]::IsNullOrWhitespace($netBiosName)) { + $strFilterSet += '$_.namesData.dnsName -match $netBiosName' + } + if (![string]::IsNullOrWhitespace($domainAdmin)) { + $strFilterSet += '$_.base.userName -eq $domainAdmin' + } + $whereClause = [string]::Join(' -and ', $strFilterSet) + $scriptBlock = [Scriptblock]::Create($whereClause) + $instantCloneEngineDomainAdministrator = $insDomainAdministrators | Where $scriptBlock + If ($null -ne $instantCloneEngineDomainAdministrator) { + $instantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator[0].id + } elseif ($null -ne $insDomainAdministrators) { + $instantCloneEngineDomainAdministrator = $insDomainAdministrators[0].id + } + if ($null -eq $instantCloneEngineDomainAdministrator) { + throw "No Instant Clone Engine Domain Administrator found with netBiosName: [$netBiosName]" + } + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings = New-Object VMware.Hv.FarmClonePrepCustomizationSettings + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptName = $powerOffScriptName + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptParameters = $powerOffScriptParameters + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.postSynchronizationScriptName = $postSynchronizationScriptName + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.CloneprepCustomizationSettings.postSynchronizationScriptParameters = $postSynchronizationScriptParameters + $customObject = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings + } elseif ($LinkedClone) { + $ViewComposerDomainAdministrator_service_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService + $lcDomainAdministrators = $ViewComposerDomainAdministrator_service_helper.ViewComposerDomainAdministrator_List($services, $vcID) + $strFilterSet = @() + if (![string]::IsNullOrWhitespace($netBiosName)) { + $strFilterSet += '$_.base.domain -match $netBiosName' + } + if (![string]::IsNullOrWhitespace($domainAdmin)) { + $strFilterSet += '$_.base.userName -ieq $domainAdmin' + } + $whereClause = [string]::Join(' -and ', $strFilterSet) + $scriptBlock = [Scriptblock]::Create($whereClause) + $ViewComposerDomainAdministratorID = $lcDomainAdministrators | Where $scriptBlock + if ($null -ne $ViewComposerDomainAdministratorID) { + $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id + } elseif ($null -ne $lcDomainAdministrators) { + $ViewComposerDomainAdministratorID = $lcDomainAdministrators[0].id + } + if ($null -eq $ViewComposerDomainAdministratorID) { + throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" + } + + #Support only Sysprep Customization + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings = New-Object VMware.Hv.FarmSysprepCustomizationSettings + $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.ReusePreExistingAccounts = $reusePreExistingAccounts + $farmSpecObj.AutomatedFarmSpec.CustomizationSettings.SysprepCustomizationSettings = $sysprepCustomizationSettings + $customObject = $farmSpecObj.AutomatedFarmSpec.CustomizationSettings } - $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 } @@ -2454,12 +3074,16 @@ function Get-FarmSpec { 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 + + } + $farm_spec_helper.getDataObject().Data.Settings = $farm_helper.getFarmSessionSettingsHelper().getDataObject() + $farm_spec_helper.getDataObject().Data.DisplayProtocolSettings = $farm_helper.getFarmDisplayProtocolSettingsHelper().getDataObject() + $farm_spec_helper.getDataObject().Data.MirageConfigurationOverrides = $farm_helper.getFarmMirageConfigurationOverridesHelper( ).getDataObject() return $farm_spec_helper.getDataObject() } + function New-HVPool { <# .Synopsis @@ -2518,6 +3142,78 @@ function New-HVPool { 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 PowerPolicy + Power policy for the machines in the desktop after logoff. + This setting is only relevant for managed machines + +.PARAMETER AutomaticLogoffPolicy + Automatically log-off policy after disconnect. + This property has a default value of "NEVER". + +.PARAMETER AutomaticLogoffMinutes + The timeout in minutes for automatic log-off after disconnect. + This property is required if automaticLogoffPolicy is set to "AFTER". + +.PARAMETER AllowUsersToResetMachines + Whether users are allowed to reset/restart their machines. + +.PARAMETER AllowMultipleSessionsPerUser + Whether multiple sessions are allowed per user in case of Floating User Assignment. + +.PARAMETER DeleteOrRefreshMachineAfterLogoff + Whether machines are to be deleted or refreshed after logoff in case of Floating User Assignment. + +.PARAMETER RefreshOsDiskAfterLogoff + Whether and when to refresh the OS disks for dedicated-assignment, linked-clone machines. + +.PARAMETER RefreshPeriodDaysForReplicaOsDisk + Regular interval at which to refresh the OS disk. + +.PARAMETER RefreshThresholdPercentageForReplicaOsDisk + With the 'AT_SIZE' option for refreshOsDiskAfterLogoff, the size of the linked clone's OS disk in the datastore is compared to its maximum allowable size. + +.PARAMETER SupportedDisplayProtocols + The list of supported display protocols for the desktop. + +.PARAMETER DefaultDisplayProtocol + The default display protocol for the desktop. For a managed desktop, this will default to "PCOIP". For an unmanaged desktop, this will default to "RDP". + +.PARAMETER AllowUsersToChooseProtocol + Whether the users can choose the protocol. + +.PARAMETER Renderer3D + Specify 3D rendering dependent types hardware, software, vsphere client etc. + +.PARAMETER EnableGRIDvGPUs + Whether GRIDvGPUs enabled or not + +.PARAMETER VRamSizeMB + VRAM size for View managed 3D rendering. More VRAM can improve 3D performance. + +.PARAMETER MaxNumberOfMonitors + The greater these values are, the more memory will be consumed on the associated ESX hosts + +.PARAMETER MaxResolutionOfAnyOneMonitor + The greater these values are, the more memory will be consumed on the associated ESX hosts. + +.PARAMETER EnableHTMLAccess + HTML Access, enabled by VMware Blast technology, allows users to connect to View machines from Web browsers. + +.PARAMETER Quality + This setting determines the image quality that the flash movie will render. Lower quality results in less bandwidth usage. + +.PARAMETER Throttling + This setting affects the frame rate of the flash movie. If enabled, the frames per second will be reduced based on the aggressiveness level. + +.PARAMETER OverrideGlobalSetting + Mirage configuration specified here will be used for this Desktop + +.PARAMETER Enabled + Whether a Mirage server is enabled. + +.PARAMETER Url + The URL of the Mirage server. This should be in the form "<(DNS name)|(IPv4)|(IPv6)><:(port)>". IPv6 addresses must be enclosed in square brackets. + .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. @@ -2552,6 +3248,60 @@ function New-HVPool { Whether to use vSphere VSAN. This is applicable for vSphere 5.5 or later. Applicable to Full, Linked, Instant Clone Pools. +.PARAMETER UseSeparateDatastoresReplicaAndOSDisks + Whether to use separate datastores for replica and OS disks. + +.PARAMETER ReplicaDiskDatastore + Datastore to store replica disks for View Composer and Instant clone engine sourced machines. + +.PARAMETER UseNativeSnapshots + Native NFS Snapshots is a hardware feature, specify whether to use or not + +.PARAMETER ReclaimVmDiskSpace + virtual machines can be configured to use a space efficient disk format that supports reclamation of unused disk space. + +.PARAMETER ReclamationThresholdGB + Initiate reclamation when unused space on VM exceeds the threshold. + +.PARAMETER RedirectWindowsProfile + Windows profiles will be redirected to persistent disks, which are not affected by View Composer operations such as refresh, recompose and rebalance. + +.PARAMETER UseSeparateDatastoresPersistentAndOSDisks + Whether to use separate datastores for persistent and OS disks. This must be false if redirectWindowsProfile is false. + +.PARAMETER PersistentDiskDatastores + Name of the Persistent disk datastore + +.PARAMETER PersistentDiskStorageOvercommit + Storage overcommit determines how view places new VMs on the selected datastores. + +.PARAMETER DiskSizeMB + Size of the persistent disk in MB. + +.PARAMETER DiskDriveLetter + Persistent disk drive letter. + +.PARAMETER RedirectDisposableFiles + Redirect disposable files to a non-persistent disk that will be deleted automatically when a user's session ends. + +.PARAMETER NonPersistentDiskSizeMB + Size of the non persistent disk in MB. + +.PARAMETER NonPersistentDiskDriveLetter + Non persistent disk drive letter. + +.PARAMETER UseViewStorageAccelerator + Whether to use View Storage Accelerator. + +.PARAMETER ViewComposerDiskTypes + Disk types to enable for the View Storage Accelerator feature. + +.PARAMETER RegenerateViewStorageAcceleratorDays + How often to regenerate the View Storage Accelerator cache. + +.PARAMETER BlackoutTimes + A list of blackout times. + .PARAMETER StopOnProvisioningError Set to true to stop provisioning of all VMs on error. Applicable to Full, Linked, Instant Clone Pools. @@ -2637,6 +3387,22 @@ function New-HVPool { The customization spec to use. Applicable to Full, Linked Clone Pools. +.PARAMETER PowerOffScriptName + Power off script. ClonePrep/QuickPrep can run a customization script on instant/linked clone machines before they are powered off. Provide the path to the script on the parent virtual machine. + Applicable to Linked, Instant Clone pools. + +.PARAMETER PowerOffScriptParameters + Power off script parameters. Example: p1 p2 p3 + Applicable to Linked, Instant Clone pools. + +.PARAMETER PostSynchronizationScriptName + Post synchronization script. ClonePrep/QuickPrep can run a customization script on instant/linked clone machines after they are created or recovered or a new image is pushed. Provide the path to the script on the parent virtual machine. + Applicable to Linked, Instant Clone pools. + +.PARAMETER PostSynchronizationScriptParameters + Post synchronization script parameters. Example: p1 p2 p3 + Applicable to Linked, Instant Clone pools. + .PARAMETER Source Source of the Virtual machines for manual pool. Supported values are 'VIRTUAL_CENTER','UNMANAGED'. @@ -2660,37 +3426,41 @@ function New-HVPool { .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. + first element from global:DefaultHVServers would be considered in-place of hvServer. .EXAMPLE + C:\PS>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 0 -MaximumCount 1 -SpareCount 1 -ProvisioningTime UP_FRONT -SysPrepName vmwarecust -CustType SYS_PREP -NetBiosName adviewdev -DomainAdmin root 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 + New-HVPool -Spec C:\VMWare\Specs\LinkedClone.json -Confirm:$false 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'; + C:\PS>Get-HVPool -PoolName 'vmwarepool' | New-HVPool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; (OR) - $vmwarepool = Get-HVPool -PoolName 'vmwarepool'; New-HVPool -ClonePool $vmwarepool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; + C:\PS>$vmwarepool = Get-HVPool -PoolName 'vmwarepool'; New-HVPool -ClonePool $vmwarepool -PoolName 'clonedPool' -NamingPattern 'clonelnk1'; + Clones new pool by using existing pool configuration .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 + Create new automated instant clone pool with naming method pattern .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 + Create new automated full clone pool with naming method pattern .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' + Create new managed manual pool from virtual center managed VirtualMachines. .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' + Create new unmanaged manual pool from unmanaged VirtualMachines. + +.EXAMPLE + New-HVPool -spec 'C:\Json\InstantClone.json' -PoolName 'InsPool1'-NamingPattern 'INSPool-' + Creates new instant clone pool by reading few parameters from json and few parameters from command line. .OUTPUTS None @@ -2698,11 +3468,11 @@ function New-HVPool { .NOTES Author : Praveen Mathamsetty. Author email : pmathamsetty@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -2746,6 +3516,7 @@ function New-HVPool { [Parameter(Mandatory = $true,ParameterSetName = 'FULL_CLONE')] [Parameter(Mandatory = $true,ParameterSetName = 'RDS')] [Parameter(Mandatory = $true,ParameterSetName = 'CLONED_POOL')] + [Parameter(Mandatory = $false,ParameterSetName = 'JSON_FILE')] [string] $PoolName, @@ -2771,7 +3542,6 @@ function New-HVPool { #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')] @@ -2798,6 +3568,120 @@ function New-HVPool { [string[]] $ConnectionServerRestrictions, + #desktopSpec.desktopSettings.deleting + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean]$Deleting = $false, + + #desktopSpec.desktopSettings.logoffSettings.powerPloicy + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('TAKE_NO_POWER_ACTION', 'ALWAYS_POWERED_ON', 'SUSPEND', 'POWER_OFF')] + [string]$PowerPolicy = 'TAKE_NO_POWER_ACTION', + + #desktopSpec.desktopSettings.logoffSettings.powerPloicy + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('IMMEDIATELY', 'NEVER', 'AFTER')] + [string]$AutomaticLogoffPolicy = 'NEVER', + + #desktopSpec.desktopSettings.logoffSettings.automaticLogoffMinutes + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(1,120)] + [int]$AutomaticLogoffMinutes = 120, + + #desktopSpec.desktopSettings.logoffSettings.allowUsersToResetMachines + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean]$allowUsersToResetMachines = $false, + + #desktopSpec.desktopSettings.logoffSettings.allowMultipleSessionsPerUser + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean]$allowMultipleSessionsPerUser = $false, + + #desktopSpec.desktopSettings.logoffSettings.deleteOrRefreshMachineAfterLogoff + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('NEVER', 'DELETE', 'AFTER')] + [string]$deleteOrRefreshMachineAfterLogoff = 'NEVER', + + #desktopSpec.desktopSettings.logoffSettings.refreshOsDiskAfterLogoff + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('NEVER', 'ALWAYS', 'EVERY', 'AT_SIZE')] + [string]$refreshOsDiskAfterLogoff = 'NEVER', + + #desktopSpec.desktopSettings.logoffSettings.refreshPeriodDaysForReplicaOsDisk + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [int]$refreshPeriodDaysForReplicaOsDisk = 120, + + #desktopSpec.desktopSettings.logoffSettings.refreshThresholdPercentageForReplicaOsDisk + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(1,100)] + [int]$refreshThresholdPercentageForReplicaOsDisk, + + #DesktopDisplayProtocolSettings + #desktopSpec.desktopSettings.logoffSettings.supportedDisplayProtocols + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('RDP', 'PCOIP', 'BLAST')] + [string[]]$supportedDisplayProtocols = @('RDP', 'PCOIP', 'BLAST'), + + #desktopSpec.desktopSettings.logoffSettings.defaultDisplayProtocol + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('RDP', 'PCOIP', 'BLAST')] + [string]$defaultDisplayProtocol = 'PCOIP', + + #desktopSpec.desktopSettings.logoffSettings.allowUsersToChooseProtocol + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [int]$allowUsersToChooseProtocol = $true, + + #desktopSpec.desktopSettings.logoffSettings.enableHTMLAccess + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean]$enableHTMLAccess = $false, + + # DesktopPCoIPDisplaySettings + #desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.renderer3D + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('MANAGE_BY_VSPHERE_CLIENT', 'AUTOMATIC', 'SOFTWARE', 'HARDWARE', 'DISABLED')] + [string]$renderer3D = 'DISABLED', + + #desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.enableGRIDvGPUs + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean]$enableGRIDvGPUs = $false, + + #desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.vRamSizeMB + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(64,512)] + [int]$vRamSizeMB = 96, + + #desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.maxNumberOfMonitors + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(1,4)] + [int]$maxNumberOfMonitors = 2, + + #desktopSpec.desktopSettings.logoffSettings.pcoipDisplaySettings.maxResolutionOfAnyOneMonitor + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('WUXGA', 'WSXGA_PLUS', 'WQXGA', 'UHD')] + [string]$maxResolutionOfAnyOneMonitor = 'WUXGA', + + # flashSettings + #desktopSpec.desktopSettings.flashSettings.quality + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('NO_CONTROL', 'LOW', 'MEDIUM', 'HIGH')] + [string]$quality = 'NO_CONTROL', + + #desktopSpec.desktopSettings.flashSettings.throttling + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateSet('DISABLED', 'CONSERVATIVE', 'MODERATE', 'AGGRESSIVE')] + [string]$throttling = 'DISABLED', + + #mirageConfigurationOverrides + #desktopSpec.desktopSettings.mirageConfigurationOverrides.overrideGlobalSetting + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean]$overrideGlobalSetting = $false, + + #desktopSpec.desktopSettings.mirageConfigurationOverrides.enabled + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean]$enabled = $true, + + #desktopSpec.desktopSettings.mirageConfigurationOverrides.url + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string]$url = $true, + #desktopSpec.automatedDesktopSpec.virtualCenter if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE #desktopSpec.manualDesktopSpec.virtualCenter if MANUAL [Parameter(Mandatory = $false,ParameterSetName = 'MANUAL')] @@ -2845,6 +3729,13 @@ function New-HVPool { [string] $ResourcePool, + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterProvisioningData.datacenter 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] + $datacenter, + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastore if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE [Parameter(Mandatory = $true,ParameterSetName = "LINKED_CLONE")] [Parameter(Mandatory = $true,ParameterSetName = 'INSTANT_CLONE')] @@ -2852,12 +3743,127 @@ function New-HVPool { [string[]] $Datastores, + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.datastores.storageOvercommit 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[]] + $StorageOvercommit = $null, + #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')] + [boolean] + $UseVSAN = $false, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.useSeparateDatastoresReplicaAndOSDisks if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [boolean] + $UseSeparateDatastoresReplicaAndOSDisks = $false, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.replicaDiskDatastore if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [string] - $UseVSAN, + $ReplicaDiskDatastore, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.UseNativeSnapshots if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [boolean] + $UseNativeSnapshots = $false, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.spaceReclamationSettings.reclaimVmDiskSpace if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [boolean] + $ReclaimVmDiskSpace = $false, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.spaceReclamationSettings.reclamationThresholdGB if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(0,[Int]::MaxValue)] + [int] + $ReclamationThresholdGB = 1, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.persistentDiskSettings.redirectWindowsProfile if LINKED_CLONE, INSTANT_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [boolean] + $RedirectWindowsProfile = $true, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.persistentDiskSettings.useSeparateDatastoresPersistentAndOSDisks if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean] + $UseSeparateDatastoresPersistentAndOSDisks = $false, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.persistentDiskSettings.PersistentDiskDatastores if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string[]] + $PersistentDiskDatastores, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.persistentDiskSettings.PersistentDiskDatastores if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string[]] + $PersistentDiskStorageOvercommit = $null, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.persistentDiskSettings.diskSizeMB if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(128,[Int]::MaxValue)] + [int] + $DiskSizeMB = 2048, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.persistentDiskSettings.diskDriveLetter if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidatePattern("^[D-Z]$")] + [string] + $DiskDriveLetter = "D", + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.nonPersistentDiskSettings.redirectDisposableFiles if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean] + $redirectDisposableFiles, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.nonPersistentDiskSettings.diskSizeMB if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(512,[Int]::MaxValue)] + [int] + $NonPersistentDiskSizeMB = 4096, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewComposerStorageSettings.nonPersistentDiskSettings.diskDriveLetter if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidatePattern("^[D-Z]|Auto$")] + [string] + $NonPersistentDiskDriveLetter = "Auto", + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.useViewStorageAccelerator if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [boolean] + $UseViewStorageAccelerator = $false, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.useViewStorageAccelerator if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [string] + $ViewComposerDiskTypes = "OS_DISKS", + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.regenerateViewStorageAcceleratorDays if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [ValidateRange(1,999)] + [int] + $RegenerateViewStorageAcceleratorDays = 7, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterStorageSettings.viewStorageAcceleratorSettings.blackoutTimes if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [VMware.Hv.DesktopBlackoutTime[]] + $BlackoutTimes, + + #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.virtualCenterNetworkingSettings.nics + [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] + [VMware.Hv.DesktopNetworkInterfaceCardSettings[]] + $Nics, #desktopSpec.automatedDesktopSpec.virtualCenterProvisioningSettings.enableProvsioning if LINKED_CLONE, INSTANT_CLONE, FULL_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] @@ -2894,6 +3900,7 @@ function New-HVPool { [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] + [Parameter(Mandatory = $false,ParameterSetName = 'JSON_FILE')] [string] $NamingPattern = $poolName + '{n:fixed=4}', @@ -2963,6 +3970,8 @@ function New-HVPool { [Parameter(Mandatory = $false,ParameterSetName = 'FULL_CLONE')] [string]$NetBiosName, + #desktopSpec.automatedDesktopSpec.customizationSettings.domainAdministrator + #desktopSpec.automatedDesktopSpec.customizationSettings.cloneprepCustomizationSettings.instantCloneEngineDomainAdministrator [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] [string]$DomainAdmin = $null, @@ -2974,12 +3983,50 @@ function New-HVPool { [string] $CustType, + #desktopSpec.automatedDesktopSpec.customizationSettings.reusePreExistingAccounts if LINKED_CLONE + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [Boolean] + $ReusePreExistingAccounts = $false, + #desktopSpec.automatedDesktopSpec.customizationSettings.sysprepCustomizationSettings.customizationSpec if LINKED_CLONE, FULL_CLONE [Parameter(Mandatory = $false,ParameterSetName = "LINKED_CLONE")] [Parameter(Mandatory = $false,ParameterSetName = "FULL_CLONE")] [string] $SysPrepName, + #desktopSpec.automatedDesktopSpec.customizationSettings.noCustomizationSettings.doNotPowerOnVMsAfterCreation if FULL_CLONE + [Parameter(Mandatory = $false,ParameterSetName = "FULL_CLONE")] + [boolean] + $DoNotPowerOnVMsAfterCreation = $false, + + #desktopSpec.automatedDesktopSpec.customizationSettings.quickprepCustomizationSettings.powerOffScriptName if LINKED_CLONE, INSTANT_CLONE + #desktopSpec.automatedDesktopSpec.customizationSettings.cloneprepCustomizationSettings.powerOffScriptName + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string] + $PowerOffScriptName, + + #desktopSpec.automatedDesktopSpec.customizationSettings.quickprepCustomizationSettings.powerOffScriptParameters + #desktopSpec.automatedDesktopSpec.customizationSettings.cloneprepCustomizationSettings.powerOffScriptParameters + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string] + $PowerOffScriptParameters, + + #desktopSpec.automatedDesktopSpec.customizationSettings.quickprepCustomizationSettings.postSynchronizationScriptName + #desktopSpec.automatedDesktopSpec.customizationSettings.cloneprepCustomizationSettings.postSynchronizationScriptName + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string] + $PostSynchronizationScriptName, + + #desktopSpec.automatedDesktopSpec.customizationSettings.quickprepCustomizationSettings.postSynchronizationScriptParameters + #desktopSpec.automatedDesktopSpec.customizationSettings.cloneprepCustomizationSettings.postSynchronizationScriptParameters + [Parameter(Mandatory = $false,ParameterSetName = 'INSTANT_CLONE')] + [Parameter(Mandatory = $false,ParameterSetName = 'LINKED_CLONE')] + [string] + $PostSynchronizationScriptParameters, + #manual desktop [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] [ValidateSet('VIRTUAL_CENTER','UNMANAGED')] @@ -2988,10 +4035,13 @@ function New-HVPool { [Parameter(Mandatory = $true,ParameterSetName = 'MANUAL')] [Parameter(Mandatory = $false,ParameterSetName = "JSON_FILE")] + [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] [string[]]$VM, #farm [Parameter(Mandatory = $false,ParameterSetName = 'RDS')] + [Parameter(Mandatory = $false,ParameterSetName = 'CLONED_POOL')] + [string] $Farm, @@ -3057,10 +4107,10 @@ function New-HVPool { } process { - + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys if ($poolName) { try { - $sourcePool = Get-HVPoolSummary -poolName $poolName -hvServer $hvServer + $sourcePool = Get-HVPoolSummary -poolName $poolName -suppressInfo $true -hvServer $hvServer } catch { Write-Error "Make sure Get-HVPoolSummary advanced function is loaded, $_" break @@ -3078,6 +4128,14 @@ function New-HVPool { Write-Error "Json file exception, $_" break } + + try { + #Json object validation + Test-HVPoolSpec -PoolObject $jsonObject + } catch { + Write-Error "Json object validation failed, $_" + break + } if ($jsonObject.type -eq "AUTOMATED") { $poolType = 'AUTOMATED' if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenter) { @@ -3094,18 +4152,43 @@ function New-HVPool { $custType = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CustomizationType if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "INSTANT_CLONE_ENGINE") { $InstantClone = $true + if ($null -ne $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings) { + $domainAdmin = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator + $powerOffScriptName = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.PowerOffScriptName + $powerOffScriptParameters = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.PowerOffScriptParameters + $postSynchronizationScriptName = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.PostSynchronizationScriptName + $postSynchronizationScriptParameters = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.PostSynchronizationScriptParameters + } } else { if ($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "VIEW_COMPOSER") { $LinkedClone = $true - } else { + $domainAdmin = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.domainAdministrator + } elseIf($jsonObject.AutomatedDesktopSpec.ProvisioningType -eq "VIRTUAL_CENTER") { $FullClone = $true } - $sysPrepName = $jsonObject.SysPrepName + switch ($custType) { + 'SYS_PREP' { + $sysprepCustomizationSettings = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings + $sysPrepName = $sysprepCustomizationSettings.customizationSpec + $reusePreExistingAccounts = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.reusePreExistingAccounts + } + 'QUICK_PREP' { + $powerOffScriptName = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.PowerOffScriptName + $powerOffScriptParameters = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.PowerOffScriptParameters + $postSynchronizationScriptName = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.PostSynchronizationScriptName + $postSynchronizationScriptParameters = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.PostSynchronizationScriptParameters + } + 'NONE' { + $doNotPowerOnVMsAfterCreation = $jsonObject.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings.DoNotPowerOnVMsAfterCreation + } + } } $namingMethod = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.NamingMethod $transparentPageSharingScope = $jsonObject.AutomatedDesktopSpec.virtualCenterManagedCommonSettings.TransparentPageSharingScope if ($namingMethod -eq "PATTERN") { - $namingPattern = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.namingPattern + if ($NamingPattern -eq '{n:fixed=4}') { + $namingPattern = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.namingPattern + } $maximumCount = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.maxNumberOfMachines $spareCount = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.numberOfSpareMachines $provisioningTime = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings.provisioningTime @@ -3114,6 +4197,9 @@ function New-HVPool { $startInMaintenanceMode = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.startMachinesInMaintenanceMode $numUnassignedMachinesKeptPoweredOn = $jsonObject.AutomatedDesktopSpec.VmNamingSpec.SpecificNamingSpec.numUnassignedMachinesKeptPoweredOn } + $enableProvisioning = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.EnableProvisioning + $stopProvisioningOnError = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError + $minReady = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Template) { $template = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Template } @@ -3123,14 +4209,87 @@ function New-HVPool { if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot) { $snapshotVM = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.Snapshot } + $dataCenter = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.dataCenter $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 + $storageOvercommit += $dtStore.StorageOvercommit } - } elseif ($jsonObject.type -eq "MANUAL") { + $useVSan = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.UseVSan + if ($LinkedClone -or $InstantClone) { + $useSeparateDatastoresReplicaAndOSDisks = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.UseSeparateDatastoresReplicaAndOSDisks + if ($useSeparateDatastoresReplicaAndOSDisks) { + $replicaDiskDatastore = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.replicaDiskDatastore + } + if ($LinkedClone) { + #For Instant clone desktops, this setting can only be set to false + $useNativeSnapshots = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.useNativeSnapshots + $reclaimVmDiskSpace = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.spaceReclamationSettings.reclaimVmDiskSpace + if ($reclaimVmDiskSpace) { + $reclamationThresholdGB = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.spaceReclamationSettings.reclamationThresholdGB + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.PersistentDiskSettings) { + $redirectWindowsProfile = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.PersistentDiskSettings.RedirectWindowsProfile + if ($redirectWindowsProfile) { + $useSeparateDatastoresPersistentAndOSDisks = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.PersistentDiskSettings.UseSeparateDatastoresPersistentAndOSDisks + } + $dataStoreList = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.PersistentDiskSettings.persistentDiskDatastores + foreach ($dtStore in $dataStoreList) { + $persistentDiskDatastores += $dtStore.Datastore + $PersistentDiskStorageOvercommit += $dtStore.StorageOvercommit + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.PersistentDiskSettings.DiskSizeMB) { + $diskSizeMB = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.PersistentDiskSettings.DiskSizeMB + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.PersistentDiskSettings.DiskDriveLetter) { + $diskDriveLetter = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.PersistentDiskSettings.DiskDriveLetter + } + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.nonPersistentDiskSettings) { + $redirectDisposableFiles = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.NonPersistentDiskSettings.RedirectDisposableFiles + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.NonPersistentDiskSettings.DiskSizeMB) { + $nonPersistentDiskSizeMB = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.NonPersistentDiskSettings.DiskSizeMB + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.NonPersistentDiskSettings.DiskDriveLetter) { + $nonPersistentDiskDriveLetter = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings.NonPersistentDiskSettings.DiskDriveLetter + } + } + } else { + $useNativeSnapshots = $false + $redirectWindowsProfile = $false + } + } + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings) { + $useViewStorageAccelerator = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.UseViewStorageAccelerator + if ($useViewStorageAccelerator -and $LinkedClone) { + $viewComposerDiskTypes = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.ViewComposerDiskTypes + } + if (! $InstantClone -and $useViewStorageAccelerator) { + $regenerateViewStorageAcceleratorDays = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.RegenerateViewStorageAcceleratorDays + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.blackoutTimes) { + $blackoutTimesList =$jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.viewStorageAcceleratorSettings.blackoutTimes + foreach ($blackout in $blackoutTimesList) { + $blackoutObj = New-Object VMware.Hv.DesktopBlackoutTime + $blackoutObj.Days = $blackout.Days + $blackoutObj.StartTime = $blackout.StartTime + $blackoutObj.EndTime = $blackoutObj.EndTime + $blackoutTimes += $blackoutObj + } + } + } + } + <# ToDo Nic + if ($null -ne $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.nics) { + $nicList = $jsonObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.nics + foreach($nicObj in $nicList) { + $nic = New-Object VMware.Hv.DesktopNetworkInterfaceCardSettings + } + } + #> + } elseIf ($jsonObject.type -eq "MANUAL") { $MANUAL = $true $poolType = 'MANUAL' $userAssignment = $jsonObject.ManualDesktopSpec.userAssignment.userAssignment @@ -3149,21 +4308,87 @@ function New-HVPool { $poolDisplayName = $jsonObject.base.DisplayName $description = $jsonObject.base.Description $accessGroup = $jsonObject.base.AccessGroup - $poolName = $jsonObject.base.name + if (!$poolName) { + $poolName = $jsonObject.base.name + } + + <# + # Populate desktop settings + #> + if ($null -ne $jsonObject.DesktopSettings) { + $Enable = $jsonObject.DesktopSettings.enabled + $deleting = $jsonObject.DesktopSettings.deleting + if ($null -ne $jsonObject.DesktopSettings.connectionServerRestrictions) { + $ConnectionServerRestrictions = $jsonObject.DesktopSettings.connectionServerRestrictions + } + if ($poolType -ne 'RDS') { + if ($null -ne $jsonObject.DesktopSettings.logoffSettings) { + $powerPolicy = $jsonObject.DesktopSettings.logoffSettings.powerPolicy + $automaticLogoffPolicy = $jsonObject.DesktopSettings.logoffSettings.automaticLogoffPolicy + if ($null -ne $jsonObject.DesktopSettings.logoffSettings.automaticLogoffMinutes) { + $automaticLogoffMinutes = $jsonObject.DesktopSettings.logoffSettings.automaticLogoffMinutes + } + $allowUsersToResetMachines = $jsonObject.DesktopSettings.logoffSettings.allowUsersToResetMachines + $allowMultipleSessionsPerUser = $jsonObject.DesktopSettings.logoffSettings.allowMultipleSessionsPerUser + $deleteOrRefreshMachineAfterLogoff = $jsonObject.DesktopSettings.logoffSettings.deleteOrRefreshMachineAfterLogoff + $refreshOsDiskAfterLogoff = $jsonObject.DesktopSettings.logoffSettings.refreshOsDiskAfterLogoff + if ($jsonObject.DesktopSettings.logoffSettings.refreshPeriodDaysForReplicaOsDisk) { + $refreshPeriodDaysForReplicaOsDisk = $jsonObject.DesktopSettings.logoffSettings.refreshPeriodDaysForReplicaOsDisk + } + if ($jsonObject.DesktopSettings.logoffSettings.refreshThresholdPercentageForReplicaOsDisk) { + $refreshThresholdPercentageForReplicaOsDisk = $jsonObject.DesktopSettings.logoffSettings.refreshThresholdPercentageForReplicaOsDisk + } + } + + if ($null -ne $jsonObject.DesktopSettings.displayProtocolSettings) { + $supportedDisplayProtocols = $jsonObject.DesktopSettings.displayProtocolSettings.supportedDisplayProtocols + $defaultDisplayProtocol = $jsonObject.DesktopSettings.displayProtocolSettings.defaultDisplayProtocol + $allowUsersToChooseProtocol = $jsonObject.DesktopSettings.displayProtocolSettings.allowUsersToChooseProtocol + if ($null -ne $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings) { + $renderer3D = $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.renderer3D + $enableGRIDvGPUs = $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.enableGRIDvGPUs + if ($jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.vRamSizeMB) { + $vRamSizeMB = $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.vRamSizeMB + } + $maxNumberOfMonitors = $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.maxNumberOfMonitors + $maxResolutionOfAnyOneMonitor = $jsonObject.DesktopSettings.displayProtocolSettings.pcoipDisplaySettings.maxResolutionOfAnyOneMonitor + } + $enableHTMLAccess = $jsonObject.DesktopSettings.displayProtocolSettings.enableHTMLAccess + } + + if ($null -ne $jsonObject.DesktopSettings.mirageConfigurationOverrides) { + $overrideGlobalSetting = $jsonObject.DesktopSettings.mirageConfigurationOverrides.overrideGlobalSetting + if ($jsonObject.DesktopSettings.mirageConfigurationOverrides.enabled) { + $enabled = $jsonObject.DesktopSettings.mirageConfigurationOverrides.enabled + } + if ($jsonObject.DesktopSettings.mirageConfigurationOverrides.url) { + $url = $jsonObject.DesktopSettings.mirageConfigurationOverrides.url + } + } + } + if ($null -ne $jsonObject.DesktopSettings.flashSettings) { + $quality = $jsonObject.DesktopSettings.flashSettings.quality + $throttling = $jsonObject.DesktopSettings.flashSettings.throttling + } + #desktopsettings ends + } + if ($null -ne $jsonObject.GlobalEntitlementData) { + $globalEntitlement = $jsonObject.GlobalEntitlementData.globalEntitlement + } } if ($PSCmdlet.MyInvocation.ExpectingInput -or $clonePool) { if ($clonePool -and ($clonePool.GetType().name -eq 'DesktopSummaryView')) { $clonePool = Get-HVPool -poolName $clonePool.desktopsummarydata.name - } elseif (!($clonePool -and ($clonePool.GetType().name -eq 'DesktopInfo'))) { + } elseIf (!($clonePool -and ($clonePool.GetType().name -eq 'DesktopInfo'))) { Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" return } $poolType = $clonePool.type $desktopBase = $clonePool.base $desktopSettings = $clonePool.DesktopSettings - $provisioningType = $null + $provisioningType = $clonePool.source if ($clonePool.AutomatedDesktopData) { $provisioningType = $clonePool.AutomatedDesktopData.ProvisioningType $virtualCenterID = $clonePool.AutomatedDesktopData.VirtualCenter @@ -3173,11 +4398,30 @@ function New-HVPool { $DesktopVirtualCenterProvisioningData = $DesktopVirtualCenterProvisioningSettings.VirtualCenterProvisioningData $DesktopVirtualCenterStorageSettings = $DesktopVirtualCenterProvisioningSettings.VirtualCenterStorageSettings $DesktopVirtualCenterNetworkingSettings = $DesktopVirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings - $desktopVirtualCenterManagedCommonSettings = $clonePool.AutomatedDesktopData.virtualCenterManagedCommonSettings - $desktopCustomizationSettings = $clonePool.AutomatedDesktopData.CustomizationSettings + $DesktopVirtualCenterManagedCommonSettings = $clonePool.AutomatedDesktopData.virtualCenterManagedCommonSettings + $DesktopCustomizationSettings = $clonePool.AutomatedDesktopData.CustomizationSettings + $CurrentImageState =` + $clonePool.AutomatedDesktopData.provisioningStatusData.instantCloneProvisioningStatusData.instantCloneCurrentImageState } - if (($null -eq $provisioningType) -or ($provisioningType -eq 'INSTANT_CLONE_ENGINE')) { - Write-Error "Only Automated linked clone or full clone pool support cloning" + elseIf ($clonePool.ManualDesktopData) { + if (! $VM) { + Write-Error "ManualDesktop pool cloning requires list of machines, parameter VM is empty" + break + } + $source = $clonePool.source + $virtualCenterID = $clonePool.ManualDesktopData.VirtualCenter + $desktopUserAssignment = $clonePool.ManualDesktopData.userAssignment + $desktopVirtualCenterStorageSettings = $clonePool.ManualDesktopData.viewStorageAcceleratorSettings + $desktopVirtualCenterManagedCommonSettings = $clonePool.ManualDesktopData.virtualCenterManagedCommonSettings + } + elseIf($clonePool.RdsDesktopData) { + if (! $Farm) { + Write-Error "RdsDesktop pool cloning requires farm, parameter Farm is not set" + break + } + } + if ($provisioningType -eq 'INSTANT_CLONE_ENGINE' -and $poolType -eq 'AUTOMATED' -and $CurrentImageState -ne 'READY') { + Write-Error "Instant clone pool's Current Image State should be in 'READY' state, otherwise cloning is not supported" break } } else { @@ -3186,19 +4430,19 @@ function New-HVPool { $poolType = 'AUTOMATED' $provisioningType = 'INSTANT_CLONE_ENGINE' } - elseif ($LinkedClone) { + elseIf ($LinkedClone) { $poolType = 'AUTOMATED' $provisioningType = 'VIEW_COMPOSER' } - elseif ($FullClone) { + elseIf ($FullClone) { $poolType = 'AUTOMATED' $provisioningType = 'VIRTUAL_CENTER' } - elseif ($Manual) { $poolType = 'MANUAL' } - elseif ($RDS) { $poolType = 'RDS' } + elseIf ($Manual) { $poolType = 'MANUAL' } + elseIf ($RDS) { $poolType = 'RDS' } } - $script:desktopSpecObj = Get-HVDesktopSpec -poolType $poolType -provisioningType $provisioningType -namingMethod $namingMethod + $script:desktopSpecObj = Get-DesktopSpec -poolType $poolType -provisioningType $provisioningType -namingMethod $namingMethod # # accumulate properties that are shared among various type @@ -3256,8 +4500,8 @@ function New-HVPool { { 'RDS' { <# - Query FarmId from Farm Name - #> + Query FarmId from Farm Name + #> $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals $QueryFilterEquals.memberName = 'data.name' $QueryFilterEquals.value = $farm @@ -3289,6 +4533,9 @@ function New-HVPool { $machineList = Get-RegisteredPhysicalMachine -services $services -machinesList $VM } $desktopSpecObj.ManualDesktopSpec.Machines = $machineList + if ($desktopUserAssignment) { + $desktopSpecObj.ManualDesktopSpec.userAssignment = $desktopUserAssignment + } } default { if (!$desktopVirtualMachineNamingSpec) { @@ -3332,7 +4579,9 @@ function New-HVPool { try { $desktopVirtualCenterProvisioningData = Get-HVPoolProvisioningData -vc $virtualCenterID -vmObject $desktopVirtualCenterProvisioningData $hostClusterId = $desktopVirtualCenterProvisioningData.HostOrCluster - $desktopVirtualCenterStorageSettings = Get-HVPoolStorageObject -hostclusterID $hostClusterId -storageObject $desktopVirtualCenterStorageSettings + $hostOrCluster_helper = New-Object VMware.Hv.HostOrClusterService + $hostClusterIds = (($hostOrCluster_helper.HostOrCluster_GetHostOrClusterTree($services, $desktopVirtualCenterProvisioningData.datacenter)).treeContainer.children.info).Id + $desktopVirtualCenterStorageSettings = Get-HVPoolStorageObject -hostClusterIds $hostClusterId -storageObject $desktopVirtualCenterStorageSettings $DesktopVirtualCenterNetworkingSettings = Get-HVPoolNetworkSetting -networkObject $DesktopVirtualCenterNetworkingSettings $desktopCustomizationSettings = Get-HVPoolCustomizationSetting -vc $virtualCenterID -customObject $desktopCustomizationSettings } catch { @@ -3341,10 +4590,10 @@ function New-HVPool { break } - if (!$DesktopVirtualCenterProvisioningSettings) { - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.enableProvisioning = $true - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $true - $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = 0 + if (! $DesktopVirtualCenterProvisioningSettings) { + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.enableProvisioning = $enableProvisioning + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.stopProvisioningOnError = $stopProvisioningOnError + $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.minReadyVMsOnVComposerMaintenance = $minReady $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = $desktopVirtualCenterProvisioningData $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings = $desktopVirtualCenterStorageSettings $desktopSpecObj.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterNetworkingSettings = $DesktopVirtualCenterNetworkingSettings @@ -3385,8 +4634,83 @@ function New-HVPool { $desktopSpecObj.base.Description = $description $desktopSpecObj.type = $poolType - if ($desktopSettings) { $desktopSpecObj.DesktopSettings = $desktopSettings } + if (! $desktopSettings) { + $desktopSettingsService = New-Object VMware.Hv.DesktopService + $desktopSettingsHelper = $desktopSettingsService.getDesktopSettingsHelper() + $desktopSettingsHelper.setEnabled($Enable) + $desktopSettingsHelper.setConnectionServerRestrictions($ConnectionServerRestrictions) + #$desktopLogoffSettings = New-Object VMware.Hv.DesktopLogoffSettings + $desktopLogoffSettings = $desktopSettingsService.getDesktopLogoffSettingsHelper() + if ($InstantClone) { + $deleteOrRefreshMachineAfterLogoff = "DELETE" + $powerPolicy = "ALWAYS_POWERED_ON" + } + $desktopLogoffSettings.setPowerPolicy($powerPolicy) + $desktopLogoffSettings.setAutomaticLogoffPolicy($automaticLogoffPolicy) + $desktopLogoffSettings.setAutomaticLogoffMinutes($automaticLogoffMinutes) + $desktopLogoffSettings.setAllowUsersToResetMachines($allowUsersToResetMachines) + $desktopLogoffSettings.setAllowMultipleSessionsPerUser($allowMultipleSessionsPerUser) + $desktopLogoffSettings.setDeleteOrRefreshMachineAfterLogoff($deleteOrRefreshMachineAfterLogoff) + $desktopLogoffSettings.setRefreshOsDiskAfterLogoff($refreshOsDiskAfterLogoff) + $desktopLogoffSettings.setRefreshPeriodDaysForReplicaOsDisk($refreshPeriodDaysForReplicaOsDisk) + if ($refreshThresholdPercentageForReplicaOsDisk -and $refreshOsDiskAfterLogoff -eq "AT_SIZE") { + $desktopLogoffSettings.setRefreshThresholdPercentageForReplicaOsDisk($refreshThresholdPercentageForReplicaOsDisk) + } + if ($poolType -ne 'RDS') { + $desktopSettingsHelper.setLogoffSettings($desktopLogoffSettings.getDataObject()) + + $desktopDisplayProtocolSettings = $desktopSettingsService.getDesktopDisplayProtocolSettingsHelper() + #setSupportedDisplayProtocols is not exists, because this property cannot be updated. + $desktopDisplayProtocolSettings.getDataObject().SupportedDisplayProtocols = $supportedDisplayProtocols + $desktopDisplayProtocolSettings.setDefaultDisplayProtocol($defaultDisplayProtocol) + $desktopDisplayProtocolSettings.setEnableHTMLAccess($enableHTMLAccess) + $desktopDisplayProtocolSettings.setAllowUsersToChooseProtocol($allowUsersToChooseProtocol) + + $desktopPCoIPDisplaySettings = $desktopSettingsService.getDesktopPCoIPDisplaySettingsHelper() + $desktopPCoIPDisplaySettings.setRenderer3D($renderer3D) + #setEnableGRIDvGPUs is not exists, because this property cannot be updated. + $desktopPCoIPDisplaySettings.getDataObject().EnableGRIDvGPUs = $enableGRIDvGPUs + $desktopPCoIPDisplaySettings.setVRamSizeMB($vRamSizeMB) + $desktopPCoIPDisplaySettings.setMaxNumberOfMonitors($maxNumberOfMonitors) + $desktopPCoIPDisplaySettings.setMaxResolutionOfAnyOneMonitor($maxResolutionOfAnyOneMonitor) + $desktopDisplayProtocolSettings.setPcoipDisplaySettings($desktopPCoIPDisplaySettings.getDataObject()) + $desktopSettingsHelper.setDisplayProtocolSettings($desktopDisplayProtocolSettings.getDataObject()) + + $desktopMirageConfigOverrides = $desktopSettingsService.getDesktopMirageConfigurationOverridesHelper() + $desktopMirageConfigOverrides.setEnabled($enabled) + $desktopMirageConfigOverrides.setOverrideGlobalSetting($overrideGlobalSetting) + $desktopMirageConfigOverrides.setUrl($url) + $desktopSettingsHelper.setMirageConfigurationOverrides($desktopMirageConfigOverrides.getDataObject()) + $desktopSettings = $desktopSettingsHelper.getDataObject() + } + $desktopFlashSettings = $desktopSettingsService.getDesktopAdobeFlashSettingsHelper() + $desktopFlashSettings.setQuality($quality) + $desktopFlashSettings.setThrottling($throttling) + $desktopSettingsHelper.setFlashSettings($desktopFlashSettings.getDataObject()) + } + + $desktopSpecObj.DesktopSettings = $desktopSettings + $info = $services.PodFederation.PodFederation_get() + if ($globalEntitlement -and ("ENABLED" -eq $info.localPodStatus.status)) { + $QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals + $QueryFilterEquals.memberName = 'base.displayName' + $QueryFilterEquals.value = $globalEntitlement + $defn = New-Object VMware.Hv.QueryDefinition + $defn.queryEntityType = 'GlobalEntitlementSummaryView' + $defn.Filter = $QueryFilterEquals + $query_service_helper = New-Object VMware.Hv.QueryServiceService + try { + $queryResults = $query_service_helper.QueryService_Query($services,$defn) + $globalEntitlementid = $queryResults.Results.id + if ($globalEntitlementid.length -eq 1) { + $desktopGlobalEntitlementData = New-Object VMware.Hv.DesktopGlobalEntitlementData -Property @{'globalEntitlement'= $globalEntitlementid;} + } + } + catch { + Write-Host "GlobalEntitlement " $_ + } + } if ($desktopAutomatedDesktopSpec) { $desktopSpecObj.AutomatedDesktopSpec = $desktopAutomatedDesktopSpec } @@ -3396,18 +4720,28 @@ function New-HVPool { # 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 - #> + $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) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($desktopSpecObj.base.name)) { + $id = $desktop_helper.Desktop_create($services,$desktopSpecObj) + } else { + try { + #DesktopSpec validation + Test-HVPoolSpec -PoolObject $desktopSpecObj + } catch { + Write-Error "DesktopSpec object validation failed, $_" + break + } + } + return $desktopSpecObj } end { $desktopSpecObj = $null [System.gc]::collect() } - } function Get-HVPoolProvisioningData { @@ -3428,6 +4762,12 @@ function Get-HVPoolProvisioningData { } $vmObject.Template = $templateVM.id $dataCenterID = $templateVM.datacenter + if ($dataCenter -and $dataCenterID) { + $VmTemplateInfo = $vm_template_helper.VmTemplate_ListByDatacenter($dataCenterID) + if (! ($VmTemplateInfo.Path -like "/$dataCenter/*")) { + throw "$template not exists in datacenter: [$dataCenter]" + } + } $vmObject.datacenter = $dataCenterID } if ($parentVM) { @@ -3457,7 +4797,9 @@ function Get-HVPoolProvisioningData { $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)) { + if ($item -and !$_.folderdata.incompatiblereasons.inuse -and ` + !$_.folderdata.incompatiblereasons.viewcomposerreplicafolder -and ` + (($item.folderdata.path -eq $vmFolder) -or ($item.folderdata.name -eq $vmFolder))) { $vmObject.VmFolder = $item.id break } @@ -3473,7 +4815,7 @@ function Get-HVPoolProvisioningData { 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 } + $hostClusterObj = $hostClusterList | Where-Object { ($_.path -eq $hostOrCluster) -or ($_.name -eq $hostOrCluster) } if ($null -eq $hostClusterObj) { throw "No hostOrCluster found with Name: [$hostOrCluster]" } @@ -3482,7 +4824,7 @@ function Get-HVPoolProvisioningData { 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 } + $resourcePoolObj = $resourcePoolList | Where-Object { ($_.resourcepooldata.path -eq $resourcePool) -or ($_.resourcepooldata.name -eq $resourcePool) } if ($null -eq $resourcePoolObj) { throw "No hostOrCluster found with Name: [$resourcePool]" } @@ -3493,26 +4835,54 @@ function Get-HVPoolProvisioningData { function Get-HVPoolStorageObject { param( - [Parameter(Mandatory = $false)] - [VMware.Hv.DesktopVirtualCenterStorageSettings]$StorageObject, - [Parameter(Mandatory = $true)] - [VMware.Hv.HostOrClusterId]$HostClusterID + [VMware.Hv.HostOrClusterId[]]$HostClusterIDs, + + [Parameter(Mandatory = $false)] + [VMware.Hv.DesktopVirtualCenterStorageSettings]$StorageObject ) + $datastoreList = $null if (!$storageObject) { + $datastore_helper = New-Object VMware.Hv.DatastoreService + foreach ($hostClusterID in $hostClusterIDs){ + $datastoreList += $datastore_helper.Datastore_ListDatastoresByHostOrCluster($services,$hostClusterID) + } $storageObject = New-Object VMware.Hv.DesktopVirtualCenterStorageSettings $storageAcceleratorList = @{ - 'useViewStorageAccelerator' = $false + 'useViewStorageAccelerator' = $useViewStorageAccelerator } $desktopViewStorageAcceleratorSettings = New-Object VMware.Hv.DesktopViewStorageAcceleratorSettings -Property $storageAcceleratorList $storageObject.viewStorageAcceleratorSettings = $desktopViewStorageAcceleratorSettings - $desktopSpaceReclamationSettings = New-Object VMware.Hv.DesktopSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $false } + $desktopSpaceReclamationSettings = New-Object VMware.Hv.DesktopSpaceReclamationSettings -Property @{ 'reclaimVmDiskSpace' = $reclaimVmDiskSpace; 'reclamationThresholdGB' = $reclamationThresholdGB} $desktopPersistentDiskSettings = New-Object VMware.Hv.DesktopPersistentDiskSettings -Property @{ 'redirectWindowsProfile' = $false } $desktopNonPersistentDiskSettings = New-Object VMware.Hv.DesktopNonPersistentDiskSettings -Property @{ 'redirectDisposableFiles' = $false } + if ($LinkedClone) { + if ($blackoutTimes) { + $storageObject.viewStorageAcceleratorSettings.BlackoutTimes = $blackoutTimes + } + if ($useViewStorageAccelerator) { + $storageObject.viewStorageAcceleratorSettings.ViewComposerDiskTypes = $viewComposerDiskTypes + $storageObject.viewStorageAcceleratorSettings.RegenerateViewStorageAcceleratorDays = $regenerateViewStorageAcceleratorDays + } + $desktopPersistentDiskSettings.RedirectWindowsProfile = $redirectWindowsProfile + if ($redirectWindowsProfile) { + $desktopPersistentDiskSettings.UseSeparateDatastoresPersistentAndOSDisks = $useSeparateDatastoresPersistentAndOSDisks + $desktopPersistentDiskSettings.DiskSizeMB = $diskSizeMB + $desktopPersistentDiskSettings.DiskDriveLetter = $diskDriveLetter + } + if ($useSeparateDatastoresPersistentAndOSDisks) { + if ($persistentDiskStorageOvercommit -and ($persistentDiskDatastores.Length -ne $persistentDiskStorageOvercommit.Length) ) { + throw "Parameters persistentDiskDatastores length: [$persistentDiskDatastores.Length] and persistentDiskStorageOvercommit length: [$persistentDiskStorageOvercommit.Length] should be of same size" + } + $desktopPersistentDiskSettings.PersistentDiskDatastores = Get_Datastore -DatastoreInfoList $datastoreList -DatastoreNames $PersistentDiskDatastores -DsStorageOvercommit $persistentDiskStorageOvercommit + } + $desktopNonPersistentDiskSettings.RedirectDisposableFiles = $redirectDisposableFiles + $desktopNonPersistentDiskSettings.DiskSizeMB = $nonPersistentDiskSizeMB + $desktopNonPersistentDiskSettings.DiskDriveLetter = $nonPersistentDiskDriveLetter + } $desktopViewComposerStorageSettingsList = @{ - 'useSeparateDatastoresReplicaAndOSDisks' = $false; - 'useNativeSnapshots' = $false; + 'useNativeSnapshots' = $useNativeSnapshots; 'spaceReclamationSettings' = $desktopSpaceReclamationSettings; 'persistentDiskSettings' = $desktopPersistentDiskSettings; 'nonPersistentDiskSettings' = $desktopNonPersistentDiskSettings @@ -3522,17 +4892,13 @@ function Get-HVPoolStorageObject { } } 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 + if ($StorageOvercommit -and ($datastores.Length -ne $StorageOvercommit.Length) ) { + throw "Parameters datastores length: [$datastores.Length] and StorageOvercommit length: [$StorageOvercommit.Length] should be of same size" } - foreach ($ds in $datastoresSelected) { - $myDatastores = New-Object VMware.Hv.DesktopVirtualCenterDatastoreSettings - $myDatastores.Datastore = $ds - $mydatastores.StorageOvercommit = 'UNBOUNDED' - $storageObject.Datastores += $myDatastores + $storageObject.Datastores = Get-HVDatastore -DatastoreInfoList $datastoreList -DatastoreNames $datastores -DsStorageOvercommit $StorageOvercommit + if ($useSeparateDatastoresReplicaAndOSDisks) { + $storageObject.ViewComposerStorageSettings.UseSeparateDatastoresReplicaAndOSDisks = $UseSeparateDatastoresReplicaAndOSDisks + $storageObject.ViewComposerStorageSettings.ReplicaDiskDatastore = ($datastoreInfoList | Where-Object { ($_.datastoredata.name -eq $replicaDiskDatastore) -or ($_.datastoredata.path -eq $replicaDiskDatastore)}).id } } if ($storageObject.Datastores.Count -eq 0) { @@ -3542,6 +4908,40 @@ function Get-HVPoolStorageObject { return $storageObject } +function Get-HVDatastore { + param( + [Parameter(Mandatory = $true)] + [VMware.Hv.DatastoreInfo[]] + $DatastoreInfoList, + + [Parameter(Mandatory = $true)] + [string[]] + $DatastoreNames, + + [Parameter(Mandatory = $false)] + [string[]] + $DsStorageOvercommit + + ) + $datastoresSelected = @() + foreach ($ds in $datastoreNames) { + $datastoresSelected += ($datastoreInfoList | Where-Object { ($_.DatastoreData.Path -eq $ds) -or ($_.datastoredata.name -eq $ds) }).id + } + $Datastores = $null + if (! $DsStorageOvercommit) { + $DsStorageOvercommit += 'UNBOUNDED' + } + $StorageOvercommitCnt = 0 + foreach ($ds in $datastoresSelected) { + $myDatastores = New-Object VMware.Hv.DesktopVirtualCenterDatastoreSettings + $myDatastores.Datastore = $ds + $mydatastores.StorageOvercommit = $DsStorageOvercommit[$StorageOvercommitCnt] + $Datastores += $myDatastores + $StorageOvercommitCnt++ + } + return $Datastores +} + function Get-HVPoolNetworkSetting { param( [Parameter(Mandatory = $false)] @@ -3565,9 +4965,17 @@ function Get-HVPoolCustomizationSetting { # 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]" + $ADDomains = $ad_domain_helper.ADDomain_List($services) + if ($netBiosName) { + $adDomianId = ($ADDomains | Where-Object { $_.NetBiosName -eq $netBiosName } | Select-Object -Property id) + if ($null -eq $adDomianId) { + throw "No Domain found with netBiosName: [$netBiosName]" + } + } else { + $adDomianId = ($ADDomains[0] | Select-Object -Property id) + if ($null -eq $adDomianId) { + throw "No Domain configured in view administrator UI" + } } $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 @@ -3579,29 +4987,53 @@ function Get-HVPoolCustomizationSetting { 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 }) + $insDomainAdministrators = $instantCloneEngineDomainAdministrator_helper.InstantCloneEngineDomainAdministrator_List($services) + $strFilterSet = @() + if (![string]::IsNullOrWhitespace($netBiosName)) { + $strFilterSet += '$_.namesData.dnsName -match $netBiosName' + } if (![string]::IsNullOrWhitespace($domainAdmin)) { - $instantCloneEngineDomainAdministrator = ($instantCloneEngineDomainAdministrator | Where-Object { $_.base.userName -eq $domainAdmin }).id - } else { + $strFilterSet += '$_.base.userName -eq $domainAdmin' + } + $whereClause = [string]::Join(' -and ', $strFilterSet) + $scriptBlock = [Scriptblock]::Create($whereClause) + $instantCloneEngineDomainAdministrator = $insDomainAdministrators | Where $scriptBlock + If ($null -ne $instantCloneEngineDomainAdministrator) { $instantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator[0].id + } elseif ($null -ne $insDomainAdministrators) { + $instantCloneEngineDomainAdministrator = $insDomainAdministrators[0].id } if ($null -eq $instantCloneEngineDomainAdministrator) { throw "No Instant Clone Engine Domain Administrator found with netBiosName: [$netBiosName]" } $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings = Get-CustomizationObject $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.InstantCloneEngineDomainAdministrator = $instantCloneEngineDomainAdministrator + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptName = $powerOffScriptName + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.powerOffScriptParameters = $powerOffScriptParameters + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.postSynchronizationScriptName = $postSynchronizationScriptName + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CloneprepCustomizationSettings.postSynchronizationScriptParameters = $postSynchronizationScriptParameters } else { if ($LinkedClone) { $viewComposerDomainAdministrator_helper = New-Object VMware.Hv.ViewComposerDomainAdministratorService - $ViewComposerDomainAdministratorID = ($viewComposerDomainAdministrator_helper.ViewComposerDomainAdministrator_List($services,$vcID) | Where-Object { $_.base.domain -match $netBiosName }) + $lcDomainAdministrators = $viewComposerDomainAdministrator_helper.ViewComposerDomainAdministrator_List($services,$vcID) + $strFilterSet = @() + if (![string]::IsNullOrWhitespace($netBiosName)) { + $strFilterSet += '$_.base.domain -match $netBiosName' + } if (![string]::IsNullOrWhitespace($domainAdmin)) { - $ViewComposerDomainAdministratorID = ($ViewComposerDomainAdministratorID | Where-Object { $_.base.userName -ieq $domainAdmin }).id - } else { - $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id + $strFilterSet += '$_.base.userName -ieq $domainAdmin' + } + $whereClause = [string]::Join(' -and ', $strFilterSet) + $scriptBlock = [Scriptblock]::Create($whereClause) + $ViewComposerDomainAdministratorID = $lcDomainAdministrators | Where $scriptBlock + If ($null -ne $ViewComposerDomainAdministratorID) { + $ViewComposerDomainAdministratorID = $ViewComposerDomainAdministratorID[0].id + } elseif ($null -ne $lcDomainAdministrators) { + $ViewComposerDomainAdministratorID = $lcDomainAdministrators[0].id } if ($null -eq $ViewComposerDomainAdministratorID) { - throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" + throw "No Composer Domain Administrator found with netBiosName: [$netBiosName]" } if ($custType -eq 'SYS_PREP') { $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' @@ -3614,14 +5046,19 @@ function Get-HVPoolCustomizationSetting { 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.ReusePreExistingAccounts = $reusePreExistingAccounts + } elseIf ($custType -eq 'QUICK_PREP') { $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'QUICK_PREP' $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings = Get-CustomizationObject + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.powerOffScriptName = $powerOffScriptName + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.powerOffScriptParameters = $powerOffScriptParameters + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.postSynchronizationScriptName = $postSynchronizationScriptName + $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.QuickprepCustomizationSettings.postSynchronizationScriptParameters = $postSynchronizationScriptParameters } else { throw "The customization type: [$custType] is not supported for LinkedClone Pool" } $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.DomainAdministrator = $ViewComposerDomainAdministratorID - } elseif ($FullClone) { + } elseIf ($FullClone) { if ($custType -eq 'SYS_PREP') { $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = 'SYS_PREP' $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings = Get-CustomizationObject @@ -3632,7 +5069,7 @@ function Get-HVPoolCustomizationSetting { throw "No Sysprep Customization Spec found with Name: [$sysPrepName]" } $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.SysprepCustomizationSettings.CustomizationSpec = $sysPrepIds[0].id - } elseif ($custType -eq 'NONE') { + } elseIf ($custType -eq 'NONE') { $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings = Get-CustomizationObject $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.NoCustomizationSettings.DoNotPowerOnVMsAfterCreation = $false $desktopSpecObj.AutomatedDesktopSpec.CustomizationSettings.CustomizationType = "NONE" @@ -3649,7 +5086,7 @@ function Get-HVPoolCustomizationSetting { function Get-CustomizationObject { if ($InstantClone) { return New-Object VMware.Hv.DesktopCloneprepCustomizationSettings - } elseif ($LinkedClone) { + } elseIf ($LinkedClone) { if ($custType -eq 'QUICK_PREP') { return New-Object VMware.Hv.DesktopQuickPrepCustomizationSettings } else { @@ -3664,7 +5101,7 @@ function Get-CustomizationObject { } } -function Get-HVDesktopSpec { +function Get-DesktopSpec { param( [Parameter(Mandatory = $true)] @@ -3688,7 +5125,7 @@ function Get-HVDesktopSpec { if ($provisioningType -ne 'VIRTUAL_CENTER') { $desktop_spec_helper.getDataObject().AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.ViewComposerStorageSettings = $desktop_helper.getDesktopViewComposerStorageSettingsHelper().getDataObject() } - } elseif ($poolType -eq 'MANUAL') { + } 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() @@ -3699,6 +5136,119 @@ function Get-HVDesktopSpec { } +function Test-HVPoolSpec { + param( + [Parameter(Mandatory = $true)] + $PoolObject + ) + if ($null -eq $PoolObject.type) { + Throw "Pool type is empty, need to be configured" + } + if ($null -eq $PoolObject.Base.Name) { + Throw "Pool name is empty, need to be configured" + } + if ($null -eq $PoolObject.Base.AccessGroup) { + Throw "AccessGroup of pool is empty, need to be configured" + } + if ($PoolObject.type -eq "AUTOMATED") { + if (! (($PoolObject.AutomatedDesktopSpec.UserAssignment.UserAssignment -eq "FLOATING") -or ($PoolObject.AutomatedDesktopSpec.UserAssignment.UserAssignment -eq "DEDICATED")) ) { + Throw "UserAssignment must be FLOATING or DEDICATED" + } + if ($PoolObject.AutomatedDesktopSpec.ProvisioningType -eq $null) { + Throw "Pool Provisioning type is empty, need to be configured" + } + $provisionTypeArray = @('VIRTUAL_CENTER', 'VIEW_COMPOSER', 'INSTANT_CLONE_ENGINE') + if (! ($provisionTypeArray -contains $PoolObject.AutomatedDesktopSpec.provisioningType)) { + Throw "ProvisioningType of pool is invalid" + } + if ($null -eq $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.EnableProvisioning) { + Throw "Whether to enable provisioning immediately or not, need to be configured" + } + if ($null -eq $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.StopProvisioningOnError) { + Throw "Whether to stop provisioning immediately or not on error, need to be configured" + } + if ($null -eq $PoolObject.AutomatedDesktopSpec.VmNamingSpec.NamingMethod) { + Throw "Determines how the VMs in the desktop are named, need to be configured" + } + if ($null -ne $PoolObject.AutomatedDesktopSpec.VmNamingSpec.NamingMethod) { + $namingMethodArray = @('PATTERN','SPECIFIED') + if (! ($namingMethodArray -contains $PoolObject.AutomatedDesktopSpec.VmNamingSpec.NamingMethod)) { + Throw "NamingMethod property must to be one of these SPECIFIED or PATTERN" + } + if (($null -eq $PoolObject.AutomatedDesktopSpec.VmNamingSpec.patternNamingSettings) -and ($null -eq $PoolObject.AutomatedDesktopSpec.VmNamingSpec.specificNamingSpec)) { + Throw "Naming pattern (or) Specified name settings need to be configured" + } + } + if ($null -eq $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.UseVSan) { + Throw "Must specify whether to use virtual SAN or not" + } + $jsonTemplate = $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.Template + $jsonParentVm = $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.ParentVm + $jsonSnapshot = $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.Snapshot + $jsonVmFolder = $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.VmFolder + $jsonHostOrCluster = $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.HostOrCluster + $ResourcePool = $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.virtualCenterProvisioningData.ResourcePool + if (! (($null -ne $jsonTemplate) -or (($null -ne $jsonParentVm) -and ($null -ne $jsonSnapshot) ))) { + Throw "Must specify Template or (ParentVm and Snapshot) names" + } + if ($null -eq $jsonVmFolder) { + Throw "Must specify VM folder to deploy the VMs" + } + if ($null -eq $jsonHostOrCluster) { + Throw "Must specify HostOrCluster to deploy the VMs" + } + if ($null -eq $resourcePool) { + Throw "Must specify Resource pool to deploy the VMs" + } + if ($null -eq $PoolObject.AutomatedDesktopSpec.VirtualCenterProvisioningSettings.VirtualCenterStorageSettings.Datastores) { + Throw "Must specify datastores names" + } + if ($null -eq $PoolObject.AutomatedDesktopSpec.VirtualCenterManagedCommonSettings.transparentPageSharingScope) { + Throw "Must specify transparent page sharing scope" + } + $jsonCustomizationType = $PoolObject.AutomatedDesktopSpec.CustomizationSettings.CustomizationType + switch ($jsonCustomizationType) { + "NONE" { + if ($null -eq $PoolObject.AutomatedDesktopSpec.CustomizationSettings.noCustomizationSettings) { + Throw "Specify noCustomization Settings" + } + } + "QUICK_PREP" { + if ($null -eq $PoolObject.AutomatedDesktopSpec.CustomizationSettings.quickprepCustomizationSettings) { + Throw "Specify quickPrep customizationSettings" + } + } + "SYS_PREP" { + if ($null -eq $PoolObject.AutomatedDesktopSpec.CustomizationSettings.sysprepCustomizationSettings) { + Throw "Specify sysPrep customizationSettings" + } + } + "CLONE_PREP" { + if ($null -eq $PoolObject.AutomatedDesktopSpec.CustomizationSettings.cloneprepCustomizationSettings) { + Throw "Specify clonePrep customizationSettings" + } + } + } + } elseIf ($PoolObject.Type -eq "MANUAL") { + $jsonUserAssignment = $PoolObject.ManualDesktopSpec.UserAssignment.UserAssignment + if (! (($jsonUserAssignment -eq "FLOATING") -or ($jsonUserAssignment -eq "DEDICATED")) ) { + Throw "UserAssignment must be FLOATING or DEDICATED" + } + $jsonSource = @('VIRTUAL_CENTER','UNMANAGED') + if (! ($jsonSource -contains $PoolObject.ManualDesktopSpec.Source)) { + Throw "The Source of machines must be VIRTUAL_CENTER or UNMANAGED" + } + if ($null -eq $PoolObject.ManualDesktopSpec.Machines) { + Throw "Specify list of virtual machines to be added to this pool" + } + } + elseIf ($PoolObject.type -eq "RDS") { + if ($null -eq $PoolObject.RdsDesktopSpec.Farm) { + Throw "Specify farm needed to create RDS desktop" + } + } +} + function Remove-HVFarm { <# .SYNOPSIS @@ -3714,29 +5264,32 @@ function Remove-HVFarm { 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. + 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 in-place of hvServer. .EXAMPLE - Remove-HVFarm -FarmName 'Farm-01' -HvServer $hvServer + Remove-HVFarm -FarmName 'Farm-01' -HvServer $hvServer -Confirm:$false + Delete a given farm. For an automated farm, all the RDS Server VMs are deleted from disk whereas for a manual farm only the RDS Server associations are removed. .EXAMPLE $farm_array | Remove-HVFarm -HvServer $hvServer + Deletes a given Farm object(s). For an automated farm, all the RDS Server VMs are deleted from disk whereas for a manual farm only the RDS Server associations are removed. .EXAMPLE - $farm1 = Get-HVFarm -FarmName 'Farm-01' - Remove-HVFarm -Farm $farm1 + C:\PS>$farm1 = Get-HVFarm -FarmName 'Farm-01' + C:\PS>Remove-HVFarm -Farm $farm1 + Deletes a given Farm object. For an automated farm, all the RDS Server VMs are deleted from disk whereas for a manual farm only the RDS Server associations are removed. .OUTPUTS None .NOTES - Author : Ankit Gupta. - Author email : guptaa@vmware.com - Version : 1.0 + Author : praveen mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -3765,26 +5318,27 @@ function Remove-HVFarm { } } process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys $farmList = @() if ($farmName) { try { - $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer + $farmSpecObj = Get-HVFarm -farmName $farmName -hvServer $hvServer -SuppressInfo $true } catch { Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" break } if ($farmSpecObj) { foreach ($farmObj in $farmSpecObj) { - $farmList += $farmObj.id + $farmList += @{"id" = $farmObj.id; "Name" = $farmObj.data.name} } } else { Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farmName]" break } - } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Farm) { foreach ($item in $farm) { - if ($item.GetType().name -eq 'FarmInfo' -or $item.GetType().name -eq 'FarmSummaryView') { - $farmList += $item.id + if (($item.GetType().name -eq 'FarmInfo') -or ($item.GetType().name -eq 'FarmSummaryView')) { + $farmList += @{"id" = $item.id; "Name" = $item.data.name} } else { Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" @@ -3795,10 +5349,11 @@ function Remove-HVFarm { } $farm_service_helper = New-Object VMware.Hv.FarmService foreach ($item in $farmList) { - $farm_service_helper.Farm_Delete($services, $item) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($item.Name)) { + $farm_service_helper.Farm_Delete($services, $item.id) + } + Write-Host "Farm Deleted: " $item.Name } - Write-Host "Farm Deleted" - } end { [System.gc]::collect() @@ -3830,13 +5385,16 @@ function Remove-HVPool { 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 + Remove-HVPool -HvServer $hvServer -PoolName 'FullClone' -DeleteFromDisk -Confirm:$false + Deletes pool from disk with given parameters PoolName etc. .EXAMPLE $pool_array | Remove-HVPool -HvServer $hvServer -DeleteFromDisk + Deletes specified pool from disk .EXAMPLE Remove-HVPool -Pool $pool1 + Deletes specified pool and VM(s) associations are removed from view Manager .OUTPUTS None @@ -3844,11 +5402,11 @@ function Remove-HVPool { .NOTES Author : Praveen Mathamsetty. Author email : pmathamsetty@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -3857,7 +5415,7 @@ function Remove-HVPool { ConfirmImpact = 'High' )] param( - [Parameter(Mandatory = $false,ParameterSetName = 'option')] + [Parameter(Mandatory = $true,ParameterSetName = 'option')] [string] $poolName, # PoolObject @@ -3883,26 +5441,30 @@ function Remove-HVPool { } process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys $poolList = @() if ($poolName) { try { - $myPools = Get-HVPoolSummary -poolName $poolName -hvServer $hvServer + $myPools = Get-HVPoolSummary -poolName $poolName -suppressInfo $true -hvServer $hvServer } catch { Write-Error "Make sure Get-HVPoolSummary advanced function is loaded, $_" break } if ($myPools) { foreach ($poolObj in $myPools) { - $poolList += $poolObj.id + $poolList += @{id = $poolObj.id; name = $poolObj.desktopSummaryData.name} } } else { Write-Error "No desktopsummarydata found with pool name: [$pool]" break } - } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Pool) { foreach ($item in $pool) { - if (($item.GetType().name -eq 'DesktopInfo') -or ($item.GetType().name -eq 'DesktopSummaryView')) { - $poolList += $item.id + if ($item.GetType().name -eq 'DesktopSummaryView') { + $poolList += @{id = $item.id; name = $item.desktopSummaryData.name} + } + elseif ($item.GetType().name -eq 'DesktopInfo') { + $poolList += @{id = $item.id; name = $item.base.name} } else { Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" @@ -3917,9 +5479,8 @@ function Remove-HVPool { foreach ($item in $poolList) { if ($terminateSession) { #Terminate session - $queryResults = Get-HVQueryResults MachineSummaryView (Get-HVQueryFilter base.desktop -eq $item) + $queryResults = Get-HVQueryResult MachineSummaryView (Get-HVQueryFilter base.desktop -eq $item.id) $sessions += $queryResults.base.session - if ($null -ne $sessions) { $session_service_helper = New-Object VMware.Hv.SessionService try { @@ -3932,8 +5493,10 @@ function Remove-HVPool { Write-Host "No session found." } } - Write-Host "Deleting Pool" - $desktop_service_helper.Desktop_Delete($services,$item,$deleteSpec) + Write-Host "Deleting Pool: " $item.Name + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($item.Name)) { + $desktop_service_helper.Desktop_Delete($services,$item.id,$deleteSpec) + } } } @@ -3978,34 +5541,39 @@ function Set-HVFarm { 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. + 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 in-place of hvServer. .EXAMPLE - Set-HVFarm -FarmName 'Farm-o1' -Spec 'C:\Edit-HVFarm\ManualEditFarm.json' + Set-HVFarm -FarmName 'Farm-01' -Spec 'C:\Edit-HVFarm\ManualEditFarm.json' -Confirm:$false + Updates farm configuration by using json file .EXAMPLE - Set-HVFarm -FarmName 'Farm-o1' -Key 'base.description' -Value 'updated description' + Set-HVFarm -FarmName 'Farm-01' -Key 'base.description' -Value 'updated description' + Updates farm configuration with given parameters key and value .EXAMPLE $farm_array | Set-HVFarm -Key 'base.description' -Value 'updated description' + Updates farm(s) configuration with given parameters key and value .EXAMPLE Set-HVFarm -farm 'Farm2' -Start + Enables provisioning to specified farm .EXAMPLE Set-HVFarm -farm 'Farm2' -Enable + Enables specified farm .OUTPUTS None .NOTES - Author : Ankit Gupta. - Author email : guptaa@vmware.com - Version : 1.0 + Author : praveen mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -4054,12 +5622,13 @@ function Set-HVFarm { } process { - $farmList = @() + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + $farmList = @{} if ($farmName) { try { - $farmSpecObj = Get-HVFarmSummary -farmName $farmName -hvServer $hvServer + $farmSpecObj = Get-HVFarmSummary -farmName $farmName -hvServer $hvServer -suppressInfo $true } catch { - Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" + Write-Error "Make sure Get-HVFarmSummary advanced function is loaded, $_" break } if ($farmSpecObj) { @@ -4068,7 +5637,7 @@ function Set-HVFarm { Write-Error "Start/Stop operation is not supported for farm with name : [$farmObj.Data.Name]" return } - $farmList += $farmObj.id + $farmList.add($farmObj.id, $farmObj.data.name) } } else { Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farmName]" @@ -4081,14 +5650,14 @@ function Set-HVFarm { Write-Error "Start/Stop operation is not supported for farm with name : [$item.Data.Name]" return } - $farmList += $item.id + $farmList.add($item.id, $item.data.name) } elseif ($item.GetType().name -eq 'FarmInfo') { if (($Start -or $Stop) -and ("AUTOMATED" -ne $item.Type)) { Write-Error "Start/Stop operation is not supported for farm with name : [$item.Data.Name]" return } - $farmList += $item.id + $farmList.add($item.id, $item.data.name) } else { Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" @@ -4125,8 +5694,11 @@ function Set-HVFarm { -value $false } $farm_service_helper = New-Object VMware.Hv.FarmService - foreach ($item in $farmList) { - $farm_service_helper.Farm_Update($services,$item,$updates) + foreach ($item in $farmList.Keys) { + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($farmList.$item)) { + $farm_service_helper.Farm_Update($services,$item,$updates) + } + Write-Host "Update successful for farm: " $farmList.$item } } @@ -4175,22 +5747,28 @@ function Set-HVPool { Path of the JSON specification file containing key/value pair. .EXAMPLE - Set-HVPool -PoolName 'ManualPool' -Spec 'C:\Edit-HVPool\EditPool.json' + Set-HVPool -PoolName 'ManualPool' -Spec 'C:\Edit-HVPool\EditPool.json' -Confirm:$false + Updates pool configuration by using json file .EXAMPLE Set-HVPool -PoolName 'RDSPool' -Key 'base.description' -Value 'update description' + Updates pool configuration with given parameters key and value .Example Set-HVPool -PoolName 'LnkClone' -Disable + Disables specified pool .Example Set-HVPool -PoolName 'LnkClone' -Enable + Enables specified pool .Example Set-HVPool -PoolName 'LnkClone' -Start + Enables provisioning to specified pool .Example Set-HVPool -PoolName 'LnkClone' -Stop + Disables provisioning to specified pool .OUTPUTS None @@ -4198,11 +5776,11 @@ function Set-HVPool { .NOTES Author : Praveen Mathamsetty. Author email : pmathamsetty@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -4253,10 +5831,11 @@ function Set-HVPool { } process { - $poolList = @() + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + $poolList = @{} if ($poolName) { try { - $desktopPools = Get-HVPoolSummary -poolName $poolName -hvServer $hvServer + $desktopPools = Get-HVPoolSummary -poolName $poolName -suppressInfo $true -hvServer $hvServer } catch { Write-Error "Make sure Get-HVPoolSummary advanced function is loaded, $_" break @@ -4267,24 +5846,27 @@ function Set-HVPool { Write-Error "Start/Stop operation is not supported for Poll with name : [$item.DesktopSummaryData.Name]" return } - $poolList += $desktopObj.id + $poolList.add($desktopObj.id, $desktopObj.DesktopSummaryData.Name) } + } else { + Write-Error "No desktopsummarydata found with pool name: [$poolName]" + break } - } elseif ($PSCmdlet.MyInvocation.ExpectingInput) { + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Pool) { foreach ($item in $pool) { if ($item.GetType().name -eq 'DesktopInfo') { if (($Start -or $Stop) -and ("AUTOMATED" -ne $item.Type)) { Write-Error "Start/Stop operation is not supported for Pool with name : [$item.Base.Name]" return } - $poolList += $item.id + $poolList.add($item.id, $item.Base.Name) } elseif ($item.GetType().name -eq 'DesktopSummaryView') { if (($Start -or $Stop) -and ("AUTOMATED" -ne $item.DesktopSummaryData.Type)) { Write-Error "Start/Stop operation is not supported for Poll with name : [$item.DesktopSummaryData.Name]" return } - $poolList += $item.id + $poolList.add($item.id, $item.DesktopSummaryData.Name) } else { Write-Error "In pipeline did not get object of expected type DesktopSummaryView/DesktopInfo" @@ -4325,8 +5907,11 @@ function Set-HVPool { -value $false } $desktop_helper = New-Object VMware.Hv.DesktopService - foreach ($item in $poolList) { - $desktop_helper.Desktop_Update($services,$item,$updates) + foreach ($item in $poolList.Keys) { + Write-Host "Updating the Pool: " $poolList.$item + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($poolList.$item)) { + $desktop_helper.Desktop_Update($services,$item,$updates) + } } } @@ -4338,10 +5923,10 @@ function Set-HVPool { function Start-HVFarm { <# .SYNOPSIS - Perform maintenance tasks on the farm(s). + Performs maintenance tasks on the farm(s). .DESCRIPTION - This function is used to perform maintenance tasks like enable/disable, start/stop and recompose the farm. + This function is used to perform maintenance tasks like enable/disable, start/stop and recompose the farm. This function is also used for scheduling maintenance operation on instant-clone farm(s). .PARAMETER Farm Name/Object(s) of the farm. Object(s) should be of type FarmSummaryView/FarmInfo. @@ -4349,16 +5934,23 @@ function Start-HVFarm { .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 ScheduleMaintenance + Switch for ScheduleMaintenance operation. Requests for scheduling maintenance operation on RDS Servers in the specified Instant clone farm. This marks the RDS Servers for scheduled maintenance, which is performed according to the schedule. + +.PARAMETER CancelMaintenance + Switch for cancelling maintenance operation. Requests for cancelling a scheduled maintenance operation on the specified Instant clone farm. This stops further maintenance operation on the given farm. + .PARAMETER StartTime - Specifies when to start the operation. If unset, the operation will begin immediately. + Specifies when to start the recompose/ScheduleMaintenance operation. If unset, the recompose operation will begin immediately. + For IMMEDIATE maintenance if unset, maintenance will begin immediately. For RECURRING maintenance if unset, will be calculated based on recurring maintenance configuration. If in the past, maintenance 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). + "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). This is the default value. "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. + Indicates that the operation should stop on first error. Defaults to true. .PARAMETER Servers The RDS Server(s) id to recompose. Provide a comma separated list for multiple RDSServerIds. @@ -4372,27 +5964,65 @@ function Start-HVFarm { .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 MaintenanceMode + The mode of schedule maintenance for Instant Clone Farm. This property will be one of: + "IMMEDIATE" - All server VMs will be refreshed once, immediately or at user scheduled time. + "RECURRING" - All server VMs will be periodically refreshed based on MaintenancePeriod and MaintenanceStartTime. + +.PARAMETER MaintenanceStartTime + Configured start time for the recurring maintenance. This property must be in the form hh:mm in 24 hours format. + +.PARAMETER MaintenancePeriod + This represents the frequency at which to perform recurring maintenance. This property will be one of: + "DAILY" - Daily recurring maintenance + "WEEKLY" - Weekly recurring maintenance + "MONTHLY" - Monthly recurring maintenance + +.PARAMETER StartInt + Start index for weekly or monthly maintenance. Weekly: 1-7 (Sun-Sat), Monthly: 1-31. + This property is required if maintenancePeriod is set to "WEEKLY"or "MONTHLY". + This property has values 1-7 for maintenancePeriod "WEEKLY". + This property has values 1-31 for maintenancePeriod "MONTHLY". + +.PARAMETER EveryInt + How frequently to repeat maintenance, expressed as a multiple of the maintenance period. e.g. Every 2 weeks. + This property has a default value of 1. This property has values 1-100. + .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. + 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 in-place of hvServer. .EXAMPLE - Start-HVFarm -Recompose -Farm 'Farm-01' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' + Start-HVFarm -Recompose -Farm 'Farm-01' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' -Confirm:$false + Requests a recompose of RDS Servers in the specified automated farm .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 + C:\PS>$myTime = Get-Date '10/03/2016 12:30:00' + C:\PS>Start-HVFarm -Farm 'Farm-01' -Recompose -LogoffSetting 'FORCE_LOGOFF' -ParentVM 'ParentVM' -SnapshotVM 'SnapshotVM' -StartTime $myTime + Requests a recompose task for automated farm in specified time + +.EXAMPLE + Start-HVFarm -Farm 'ICFarm-01' -ScheduleMaintenance -MaintenanceMode IMMEDIATE + Requests a ScheduleMaintenance task for instant-clone farm. Schedules an IMMEDIATE maintenance. + +.EXAMPLE + Start-HVFarm -ScheduleMaintenance -Farm 'ICFarm-01' -MaintenanceMode RECURRING -MaintenancePeriod WEEKLY -MaintenanceStartTime '11:30' -StartInt 6 -EveryInt 1 -ParentVM 'vm-rdsh-ic' -SnapshotVM 'Snap_Updated' + Requests a ScheduleMaintenance task for instant-clone farm. Schedules a recurring weekly maintenace every Saturday night at 23:30 and updates the parentVM and snapshot. + +.EXAMPLE + Start-HVFarm -CancelMaintenance -Farm 'ICFarm-01' -MaintenanceMode RECURRING + Requests a CancelMaintenance task for instant-clone farm. Cancels recurring maintenance. .OUTPUTS None .NOTES - Author : Ankit Gupta. - Author email : guptaa@vmware.com - Version : 1.0 + Author : praveen mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -4407,28 +6037,61 @@ function Start-HVFarm { [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] [switch]$Recompose, + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] + [switch]$ScheduleMaintenance, + + [Parameter(Mandatory = $false,ParameterSetName = 'CANCELMAINTENANCE')] + [switch]$CancelMaintenance, + [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] [System.DateTime]$StartTime, [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] [ValidateSet('FORCE_LOGOFF','WAIT_FOR_LOGOFF')] - [string]$LogoffSetting, + [string]$LogoffSetting = 'FORCE_LOGOFF', [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] [boolean]$StopOnFirstError = $true, [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] [string []]$Servers, [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] [string]$ParentVM, [Parameter(Mandatory = $true,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] [string]$SnapshotVM, [Parameter(Mandatory = $false,ParameterSetName = 'RECOMPOSE')] + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] [string]$Vcenter, + [Parameter(Mandatory = $true,ParameterSetName = 'SCHEDULEMAINTENANCE')] + [Parameter(Mandatory = $true,ParameterSetName = 'CANCELMAINTENANCE')] + [ValidateSet('IMMEDIATE','RECURRING')] + [string]$MaintenanceMode, + + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] + [ValidatePattern('^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$')] + [string]$MaintenanceStartTime, + + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] + [ValidateSet('DAILY','WEEKLY','MONTHLY')] + [string]$MaintenancePeriod, + + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] + [ValidateRange(1, 31)] + [int]$StartInt, + + [Parameter(Mandatory = $false,ParameterSetName = 'SCHEDULEMAINTENANCE')] + [ValidateRange(1, 100)] + [int]$EveryInt = 1, + [Parameter(Mandatory = $false)] $HvServer = $null ) @@ -4442,6 +6105,7 @@ function Start-HVFarm { } process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys $farmList = @{} $farmType = @{} $farmSource = @{} @@ -4451,15 +6115,17 @@ function Start-HVFarm { $id = $farm.id $name = $farm.data.name $type = $farm.type + $source = $farm.source } elseif ($farm.GetType().name -eq 'FarmSummaryView') { $id = $farm.id $name = $farm.data.name $type = $farm.data.type + $source = $farm.data.source } elseif ($farm.GetType().name -eq 'String') { try { - $farmSpecObj = Get-HVFarm -farmName $farm -hvServer $hvServer + $farmSpecObj = Get-HVFarm -farmName $farm -hvServer $hvServer -SuppressInfo $true } catch { Write-Error "Make sure Get-HVFarm advanced function is loaded, $_" break @@ -4467,7 +6133,8 @@ function Start-HVFarm { if ($farmSpecObj) { $id = $farmSpecObj.id $name = $farmSpecObj.data.name - $type = $farmSpecObj.data.type + $type = $farmSpecObj.type + $source = $farmSpecObj.source } else { Write-Error "Unable to retrieve FarmSummaryView with given farmName [$farm]" break @@ -4476,7 +6143,7 @@ function Start-HVFarm { Write-Error "In pipeline did not get object of expected type FarmSummaryView/FarmInfo" break } - if ($type -eq 'AUTOMATED') { + if (!$source) { $source = 'VIEW_COMPOSER' } $farmList.Add($id,$name) @@ -4519,12 +6186,73 @@ function Start-HVFarm { $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) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($farmList.$item)) { + $farm_service_helper.Farm_Update($services,$item,$updates) + $farm_service_helper.Farm_Recompose($services,$item,$spec) + } + Write-Host "Performed recompose task on farm: " $farmList.$item + } + } + 'SCHEDULEMAINTENANCE' { + if ($farmSource.$item -ne 'INSTANT_CLONE_ENGINE') { + Write-Error "SCHEDULEMAINTENANCE operation is not supported for farm with name [$farmList.$item]. It is only supported for instant-clone farms." + break + } else { + $spec = New-Object VMware.Hv.FarmMaintenanceSpec + $spec.MaintenanceMode = $MaintenanceMode + if ($startTime) { + $spec.ScheduledTime = $StartTime + } + $spec.LogoffSetting = $LogoffSetting + $spec.StopOnFirstError = $StopOnFirstError + if ($MaintenanceMode -eq "RECURRING") { + $spec.RecurringMaintenanceSettings = New-Object VMware.Hv.FarmRecurringMaintenanceSettings + $spec.RecurringMaintenanceSettings.MaintenancePeriod = $MaintenancePeriod + $spec.RecurringMaintenanceSettings.EveryInt = $EveryInt + if (!$MaintenanceStartTime) { + Write-Error "MaintenanceStartTime must be defined for MaintenanceMode = RECURRING." + break; + } else { + $spec.RecurringMaintenanceSettings.StartTime = $MaintenanceStartTime + } + if ($MaintenancePeriod -ne 'DAILY') { + if (!$StartInt) { + Write-Error "StartInt must be defined for MaintenancePeriod WEEKLY or MONTHLY." + break; + } else { + $spec.RecurringMaintenanceSettings.StartInt = $StartInt + } + } + } + #image settings are specified + if ($ParentVM -and $SnapshotVM) { + $spec.ImageMaintenanceSettings = New-Object VMware.Hv.FarmImageMaintenanceSettings + $vcId = Get-VcenterID -services $services -vCenter $Vcenter + if ($null -eq $vcId) { + Write-Error "VCenter is required if you specify ParentVM name." + break + } + try { + $spec.ImageMaintenanceSettings = Set-HVFarmSpec -vcId $vcId -spec $spec.ImageMaintenanceSettings + } catch { + Write-Error "SCHEDULEMAINTENANCE task failed with error: $_" + break + } + } + # call scheduleMaintenance service on farm + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($farmList.$item)) { + $farm_service_helper.Farm_ScheduleMaintenance($services, $item, $spec) + Write-Host "Performed SCHEDULEMAINTENANCE task on farm: " $farmList.$item + } + } + } + 'CANCELMAINTENANCE' { + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($farmList.$item)) { + $farm_service_helper.Farm_CancelScheduleMaintenance($services, $item, $MaintenanceMode) + Write-Host "Performed CANCELMAINTENANCE task on farm: " $farmList.$item + } } } - } return } } @@ -4645,19 +6373,24 @@ function Start-HVPool { .EXAMPLE Start-HVPool -Recompose -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -ParentVM 'View-Agent-Win8' -SnapshotVM 'Snap_USB' + Requests a recompose of machines in the specified pool .EXAMPLE - Start-HVPool -Refresh -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF + Start-HVPool -Refresh -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -Confirm:$false + Requests a refresh of machines in the specified pool .EXAMPLE - $myTime = Get-Date '10/03/2016 12:30:00' - Start-HVPool -Rebalance -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -StartTime $myTime + C:\PS>$myTime = Get-Date '10/03/2016 12:30:00' + C:\PS>Start-HVPool -Rebalance -Pool 'LCPool3' -LogoffSetting FORCE_LOGOFF -StartTime $myTime + Requests a rebalance of machines in a pool with specified time .EXAMPLE Start-HVPool -SchedulePushImage -Pool 'InstantPool' -LogoffSetting FORCE_LOGOFF -ParentVM 'InsParentVM' -SnapshotVM 'InsSnapshotVM' + Requests an update of push image operation on the specified Instant Clone Engine sourced pool .EXAMPLE Start-HVPool -CancelPushImage -Pool 'InstantPool' + Requests a cancellation of the current scheduled push image operation on the specified Instant Clone Engine sourced pool .OUTPUTS None @@ -4665,11 +6398,11 @@ function Start-HVPool { .NOTES Author : Praveen Mathamsetty. Author email : pmathamsetty@vmware.com - Version : 1.0 + Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -4747,7 +6480,7 @@ function Start-HVPool { } process { - + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys $poolList = @{} $poolType = @{} $poolSource = @{} @@ -4765,7 +6498,7 @@ function Start-HVPool { $type = $item.desktopsummarydata.type } elseif ($item.GetType().name -eq 'String') { try { - $poolObj = Get-HVPoolSummary -poolName $item -hvServer $hvServer + $poolObj = Get-HVPoolSummary -poolName $item -suppressInfo $true -hvServer $hvServer } catch { Write-Error "Make sure Get-HVPoolSummary advanced function is loaded, $_" break @@ -4800,14 +6533,20 @@ function Start-HVPool { $spec = Get-HVTaskSpec -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) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($poolList.$item)) { + $desktop_helper.Desktop_Rebalance($services,$item,$spec) + } + Write-Host "Performed rebalance task on Pool: " $PoolList.$item } } 'REFRESH' { $spec = Get-HVTaskSpec -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) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($poolList.$item)) { + $desktop_helper.Desktop_Refresh($services,$item,$spec) + } + Write-Host "Performed refresh task on Pool: " $PoolList.$item } } 'RECOMPOSE' { @@ -4823,8 +6562,10 @@ function Start-HVPool { $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) - + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($poolList.$item)) { + $desktop_helper.Desktop_Update($services,$item,$updates) + } + Write-Host "Performed recompose task on Pool: " $PoolList.$item } } 'PUSH_IMAGE' { @@ -4839,7 +6580,10 @@ function Start-HVPool { $spec.Settings.LogoffSetting = $logoffSetting $spec.Settings.StopOnFirstError = $stopOnFirstError if ($startTime) { $spec.Settings.startTime = $startTime } - $desktop_helper.Desktop_SchedulePushImage($services,$item,$spec) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($poolList.$item)) { + $desktop_helper.Desktop_SchedulePushImage($services,$item,$spec) + } + Write-Host "Performed push_image task on Pool: " $PoolList.$item } } 'CANCEL_PUSH_IMAGE' { @@ -4847,7 +6591,10 @@ function Start-HVPool { Write-Error "$poolList.$item is not a INSTANT CLONE pool" break } else { - $desktop_helper.Desktop_CancelScheduledPushImage($services,$item) + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($poolList.$item)) { + $desktop_helper.Desktop_CancelScheduledPushImage($services,$item) + } + Write-Host "Performed cancel_push_image task on Pool: " $PoolList.$item } } } @@ -4954,9 +6701,9 @@ function Find-HVMachine { try { if ($params['PoolName']) { - $poolObj = Get-HVPoolSummary -poolName $params['PoolName'] -hvServer $params['HvServer'] + $poolObj = Get-HVPoolSummary -poolName $params['PoolName'] -suppressInfo $true -hvServer $params['HvServer'] if ($poolObj.Length -ne 1) { - Write-Host "Failed to retrieve specific pool object with given PoolName : "$params['PoolName'] + Write-Host "Failed to retrieve specific pool object with given PoolName : " $params['PoolName'] break; } else { $desktopId = $poolObj.Id @@ -5065,19 +6812,23 @@ function Get-HVMachine { .PARAMETER HvServer Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then - first element from global:DefaultHVServers would be considered inplace of hvServer + first element from global:DefaultHVServers would be considered in-place of hvServer .EXAMPLE - Get-HVDesktop -PoolName 'ManualPool' + Get-HVMachine -PoolName 'ManualPool' + Queries VM(s) with given parameter poolName .EXAMPLE - Get-HVDesktop -MachineName 'PowerCLIVM' + Get-HVMachine -MachineName 'PowerCLIVM' + Queries VM(s) with given parameter machineName .EXAMPLE - Get-HVDesktop -State CUSTOMIZING + Get-HVMachine -State CUSTOMIZING + Queries VM(s) with given parameter vm state .EXAMPLE - Get-HVDesktop -DnsName 'powercli-*' -State CUSTOMIZING + Get-HVMachine -DnsName 'powercli-*' + Queries VM(s) with given parameter dnsName with wildcard character * .OUTPUTS Returns list of objects of type MachineInfo @@ -5088,8 +6839,8 @@ function Get-HVMachine { Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2, 7.0.3 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -5137,7 +6888,7 @@ function Get-HVMachine { $machineList = Find-HVMachine -Param $PSBoundParameters if (!$machineList) { - Write-Host "No Virtual Machine(s) Found with given search parameters" + Write-Host "Get-HVMachine: No Virtual Machine(s) Found with given search parameters" break } $queryResults = @() @@ -5180,21 +6931,28 @@ function Get-HVMachineSummary { If the value is null or not provided then filter will not be applied, otherwise the virtual machines which has display name same as value will be returned. +.PARAMETER SuppressInfo + Suppress text info, when no machine found with given search parameters + .PARAMETER HvServer Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then - first element from global:DefaultHVServers would be considered inplace of hvServer + first element from global:DefaultHVServers would be considered in-place of hvServer .EXAMPLE - Get-HVDesktopSummary -PoolName 'ManualPool' + Get-HVMachineSummary -PoolName 'ManualPool' + Queries VM(s) with given parameter poolName .EXAMPLE - Get-HVDesktopSummary -MachineName 'PowerCLIVM' + Get-HVMachineSummary -MachineName 'PowerCLIVM' + Queries VM(s) with given parameter machineName .EXAMPLE - Get-HVDesktopSummary -State CUSTOMIZING + Get-HVMachineSummary -State CUSTOMIZING + Queries VM(s) with given parameter vm state .EXAMPLE - Get-HVDesktopSummary -DnsName 'powercli-*' -State CUSTOMIZING + Get-HVMachineSummary -DnsName 'powercli-*' + Queries VM(s) with given parameter dnsName with wildcard character * .OUTPUTS Returns list of objects of type MachineNamesView @@ -5205,8 +6963,8 @@ function Get-HVMachineSummary { Version : 1.1 ===Tested Against Environment==== - Horizon View Server Version : 7.0.2, 7.0.3 - PowerCLI Version : PowerCLI 6.5 + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 PowerShell Version : 5.0 #> @@ -5242,6 +7000,10 @@ function Get-HVMachineSummary { [string] $JsonFilePath, + [Parameter(Mandatory = $false)] + [boolean] + $SuppressInfo = $false, + [Parameter(Mandatory = $false)] $HvServer = $null ) @@ -5253,8 +7015,1688 @@ function Get-HVMachineSummary { } $machineList = Find-HVMachine -Param $PSBoundParameters + if (!$machineList -and !$SuppressInfo) { + Write-Host "Get-HVMachineSummary: No machine(s) found with given search parameters" + } return $machineList } -Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool +function Get-HVPoolSpec { +<# +.Synopsis + Gets desktop specification +.DESCRIPTION + Converts DesktopInfo Object to DesktopSpec. Also Converts view API Ids to human readable names + +.PARAMETER DesktopInfo + An object with detailed description of a desktop instance. + +.PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + +.EXAMPLE + Get-HVPoolSpec -DesktopInfo $DesktopInfoObj + Converts DesktopInfo to DesktopSpec + +.EXAMPLE + Get-HVPool -PoolName 'LnkClnJson' | Get-HVPoolSpec -FilePath "C:\temp\LnkClnJson.json" + Converts DesktopInfo to DesktopSpec and also dumps json object + +.OUTPUTS + Returns desktop specification + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + + param( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [VMware.HV.DesktopInfo] + $DesktopInfo, + + [Parameter(Mandatory = $false)] + [String] + $FilePath, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + $DesktopSpec = New-Object VMware.HV.DesktopSpec + $DesktopPsObj = (($DesktopSpec | ConvertTo-Json -Depth 14) | ConvertFrom-Json) + $DesktopInfoPsObj = (($DesktopInfo | ConvertTo-Json -Depth 14) | ConvertFrom-Json) + $DesktopPsObj.Type = $DesktopInfoPsObj.Type + $DesktopPsObj.DesktopSettings = $DesktopInfoPsObj.DesktopSettings + + $entityId = New-Object VMware.HV.EntityId + $entityId.Id = $DesktopInfoPsObj.Base.AccessGroup.Id + $DesktopPsObj.Base = New-Object PsObject -Property @{ + name = $DesktopInfoPsObj.Base.Name; + displayName = $DesktopInfoPsObj.Base.displayName; + accessGroup = (Get-HVInternalName -EntityId $entityId); + description = $DesktopInfoPsObj.Base.description; + } + + if (! $DesktopInfoPsObj.GlobalEntitlementData.GlobalEntitlement) { + $DesktopPsObj.GlobalEntitlementData = $null + } else { + $entityId.Id = $DesktopInfoPsObj.GlobalEntitlementData.GlobalEntitlement.Id + $DesktopPsObj.GlobalEntitlementData = Get-HVInternalName -EntityId $entityId + } + + Switch ($DesktopInfo.Type) { + "AUTOMATED" { + $specificNamingSpecObj = $null + if ("SPECIFIED" -eq $DesktopInfoPsObj.AutomatedDesktopData.vmNamingSettings.NamingMethod) { + $specificNamingSpecObj = New-Object PsObject -Property @{ + specifiedNames = $null; + startMachinesInMaintenanceMode = $DesktopInfoPsObj.AutomatedDesktopData.vmNamingSettings.SpecificNamingSettings.StartMachinesInMaintenanceMode; + numUnassignedMachinesKeptPoweredOn = $DesktopInfoPsObj.AutomatedDesktopData.vmNamingSettings.SpecificNamingSettings.NumUnassignedMachinesKeptPoweredOn; + } + } + $vmNamingSpecObj = New-Object PsObject -Property @{ + namingMethod = $DesktopInfoPsObj.AutomatedDesktopData.vmNamingSettings.NamingMethod; + patternNamingSettings = $DesktopInfoPsObj.AutomatedDesktopData.VmNamingSettings.PatternNamingSettings; + specificNamingSpec = $specificNamingSpecObj; + } + $virtualCenterProvisioningDataObj = New-Object PsObject @{ + template = $null; + parentVm = $null; + snapshot = $null; + datacenter = $null; + vmFolder = $null; + hostOrCluster = $null; + resourcePool= $null; + } + $ProvisioningSettingsObj = $DesktopInfoPsObj.AutomatedDesktopData.VirtualCenterProvisioningSettings + if ($ProvisioningSettingsObj.VirtualCenterProvisioningData.Datacenter){ + $entityId.Id = $ProvisioningSettingsObj.VirtualCenterProvisioningData.Datacenter.Id + $virtualCenterProvisioningDataObj.Datacenter = Get-HVInternalName -EntityId $entityId + } + if ($ProvisioningSettingsObj.VirtualCenterProvisioningData.HostOrCluster){ + $entityId.Id = $ProvisioningSettingsObj.VirtualCenterProvisioningData.HostOrCluster.Id + $virtualCenterProvisioningDataObj.HostOrCluster = Get-HVInternalName -EntityId $entityId + } + if ($ProvisioningSettingsObj.VirtualCenterProvisioningData.ResourcePool){ + $entityId.Id = $ProvisioningSettingsObj.VirtualCenterProvisioningData.ResourcePool.Id + $virtualCenterProvisioningDataObj.ResourcePool = Get-HVInternalName -EntityId $entityId + } + if ($ProvisioningSettingsObj.VirtualCenterProvisioningData.ParentVm){ + $entityId.Id = $ProvisioningSettingsObj.VirtualCenterProvisioningData.ParentVm.Id + $virtualCenterProvisioningDataObj.ParentVm = Get-HVInternalName -EntityId $entityId ` + -VcId $DesktopInfo.AutomatedDesktopData.virtualCenter + } + if ($ProvisioningSettingsObj.VirtualCenterProvisioningData.Snapshot){ + $entityId.Id = $ProvisioningSettingsObj.VirtualCenterProvisioningData.Snapshot.Id + $virtualCenterProvisioningDataObj.Snapshot = Get-HVInternalName -EntityId $entityId ` + -BaseImageVmId $DesktopInfo.AutomatedDesktopData.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData.ParentVm + } + if ($ProvisioningSettingsObj.VirtualCenterProvisioningData.Template){ + $entityId.Id = $ProvisioningSettingsObj.VirtualCenterProvisioningData.Template.Id + $virtualCenterProvisioningDataObj.Template = Get-HVInternalName -EntityId $entityId + } + if ($ProvisioningSettingsObj.VirtualCenterProvisioningData.VmFolder){ + $entityId.Id = $ProvisioningSettingsObj.VirtualCenterProvisioningData.VmFolder.Id + $virtualCenterProvisioningDataObj.VmFolder = Get-HVInternalName -EntityId $entityId + } + + $DesktopInfoPsObj.AutomatedDesktopData.VirtualCenterProvisioningSettings.VirtualCenterProvisioningData = ` + $virtualCenterProvisioningDataObj + $datastores = $DesktopInfoPsObj.AutomatedDesktopData.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.datastores + $dataStoresObj = Get-DataStoreName -datastores $datastores + $DesktopInfoPsObj.AutomatedDesktopData.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.datastores = ` + $dataStoresObj + $virtualCenterStorageSettingsObj = ` + $DesktopInfoPsObj.AutomatedDesktopData.VirtualCenterProvisioningSettings.virtualCenterStorageSettings + if($virtualCenterStorageSettingsObj.replicaDiskDatastore) { + $entityId.Id = $virtualCenterStorageSettingsObj.replicaDiskDatastore.Id + $DesktopInfoPsObj.AutomatedDesktopData.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.replicaDiskDatastore =` + Get-HVInternalName -EntityId $entityId + } + if($virtualCenterStorageSettingsObj.persistentDiskSettings) { + $datastores = $virtualCenterStorageSettingsObj.persistentDiskSettings.persistentDiskDatastores + $dataStoresObj = Get-DataStoreName -datastores $datastores + $DesktopInfoPsObj.AutomatedDesktopData.VirtualCenterProvisioningSettings.virtualCenterStorageSettings.persistentDiskSettings.persistentDiskDatastores = ` + $dataStoresObj + } + if ($DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.domainAdministrator) { + $entityId.Id = $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.domainAdministrator.Id + $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.domainAdministrator = Get-HVInternalName -EntityId $entityId + } + if ($DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.adContainer) { + $entityId.Id = $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.adContainer.Id + $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.adContainer = Get-HVInternalName -EntityId $entityId + } + if ($DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.sysprepCustomizationSettings) { + $entityId.Id = ` + $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.sysprepCustomizationSettings.customizationSpec.Id + $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.sysprepCustomizationSettings.customizationSpec = ` + Get-HVInternalName -EntityId $entityId + } + if ($DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.cloneprepCustomizationSettings) { + $entityId.Id = ` + $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.cloneprepCustomizationSettings.instantCloneEngineDomainAdministrator.Id + $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings.cloneprepCustomizationSettings.instantCloneEngineDomainAdministrator = ` + Get-HVInternalName -EntityId $entityId + } + + $DesktopPsObj.AutomatedDesktopSpec = New-Object PsObject -Property @{ + provisioningType = $DesktopInfoPsObj.AutomatedDesktopData.ProvisioningType; + virtualCenter = $null; + userAssignment = $DesktopInfoPsObj.AutomatedDesktopData.UserAssignment; + virtualCenterProvisioningSettings = $DesktopInfoPsObj.AutomatedDesktopData.VirtualCenterProvisioningSettings; + virtualCenterManagedCommonSettings = $DesktopInfoPsObj.AutomatedDesktopData.virtualCenterManagedCommonSettings; + customizationSettings = $DesktopInfoPsObj.AutomatedDesktopData.customizationSettings; + vmNamingSpec = $VmNamingSpecObj; + } + if ($DesktopInfoPsObj.AutomatedDesktopData.virtualCenter) { + $entityId.Id = $DesktopInfoPsObj.AutomatedDesktopData.virtualCenter.Id + $DesktopPsObj.AutomatedDesktopSpec.virtualCenter = Get-HVInternalName ` + -EntityId $entityId + } + break + } + "MANUAL" { + $DesktopPsObj.ManualDesktopSpec = New-Object PsObject -Property @{ + userAssignment = $DesktopInfoPsObj.ManualDesktopData.UserAssignment; + source = $DesktopInfoPsObj.ManualDesktopData.Source; + virtualCenter = $null; + machines = $null; + viewStorageAcceleratorSettings = $DesktopInfoPsObj.ManualDesktopData.ViewStorageAcceleratorSettings; + virtualCenterManagedCommonSettings = $DesktopInfoPsObj.ManualDesktopData.VirtualCenterManagedCommonSettings; + } + if ($DesktopInfoPsObj.ManualDesktopData.virtualCenter) { + $entityId.Id = $DesktopInfoPsObj.ManualDesktopData.virtualCenter.Id + $DesktopPsObj.ManualDesktopSpec.virtualCenter = Get-HVInternalName ` + -EntityId $entityId + } + break + } + "RDS" { + $DesktopPsObj.rdsDesktopSpec = New-Object PsObject -Property @{ + farm = $null; + } + break + } + } + $DesktopSpecJson = ($DesktopPsObj | ConvertTo-Json -Depth 14) + if ($filePath) { + $DesktopSpecJson | Out-File -FilePath $filePath + } + return $DesktopSpecJson +} + +function Get-DataStoreName { + param( + [Parameter(Mandatory = $true)] + $datastores + ) + $dataStoresObj = @() + $entityId = New-Object VMware.Hv.EntityId + $datastores | % { + $entityId.Id = $_.datastore.Id + $dataStoresObj += , (New-Object PsObject -Property @{ + datastore = Get-HVInternalName -EntityId $entityId; + storageOvercommit = $_.storageOvercommit; + }) + } + return $dataStoresObj +} + +function Get-HVInternalName { +<# +.Synopsis + Gets human readable name + +.DESCRIPTION + Converts Horizon API Ids to human readable names. Horizon API Ids are base64 encoded, this function + will decode and returns internal/human readable names. + +.PARAMETER EntityId + Representation of a manageable entity id. + +.PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + +.EXAMPLE + Get-HVInternalName -EntityId $entityId + Decodes Horizon API Id and returns human readable name + +.OUTPUTS + Returns human readable name + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + param( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [VMware.HV.EntityId] + $EntityId, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [VMware.HV.VirtualCenterId] + $VcId, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [VMware.HV.BaseImageVmId] + $BaseImageVmId, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $tokens = ($EntityId.id -split "/") + $serviceName = $tokens[0] + Switch ($serviceName) { + 'VirtualCenter' { + $vc_id = New-Object VMware.HV.VirtualCenterId + $vc_id.Id = $EntityId.Id + return ($services.VirtualCenter.VirtualCenter_Get($vc_id)).serverSpec.serverName + } + 'InstantCloneEngineDomainAdministrator' { + $Icid = New-Object VMware.HV.InstantCloneEngineDomainAdministratorId + $Icid.Id = $EntityId.Id + $Info = $services.InstantCloneEngineDomainAdministrator.InstantCloneEngineDomainAdministrator_Get($Icid) + return $Info.Base.Username + } + 'BaseImageVm' { + $info = $services.BaseImageVm.BaseImageVm_List($VcId) | where { $_.id.id -eq $EntityId.id } + return $info.name + } + 'BaseImageSnapshot' { + $info = $services.BaseImageSnapshot.BaseImageSnapshot_List($BaseImageVmId) | where { $_.id.id -eq $EntityId.id } + return $info.name + } + 'VmTemplate' { + $info = $services.VmTemplate.VmTemplate_List($VcId) | where { $_.id.id -eq $EntityId.id } + return $info.name + } + 'ViewComposerDomainAdministrator' { + $AdministratorId = New-Object VMware.HV.ViewComposerDomainAdministratorId + $AdministratorId.id = $EntityId.id + $info = $services.ViewComposerDomainAdministrator.ViewComposerDomainAdministrator_Get($AdministratorId) + return $info.base.userName + } + default { + $base64String = $tokens[$tokens.Length-1] + $mod = $base64String.Length % 4 + if ($mod -ne 0) { + #Length of a string must be multiples of 4 + $base64String = $base64String.PadRight(($base64String.Length + (4 - $mod)), "=") + } + #Convert 4 bytes to 3 bytes base64 decoding + return ([System.Text.Encoding]::ASCII.GetString([System.Convert]:: ` + FromBase64String($base64String))) + } + } + } + end { + [System.gc]::collect() + } +} + + +function Get-UserInfo { + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + param( + [Parameter(Mandatory = $true)] + [ValidatePattern("^.+?[@\\].+?$")] + [String] + $UserName + ) + + if ($UserName -match '^.+?[@].+?$') { + $info = $UserName -split "@" + $Domain = $info[1] + $Name = $Info[0] + } else { + $info = $UserName -split "\\" + $Domain = $info[0] + $Name = $Info[1] + } + return @{'Name' = $Name; 'Domain' = $Domain} +} + +function New-HVEntitlement { +<# +.Synopsis + Associates a user/group with a resource + +.DESCRIPTION + This represents a simple association between a single user/group and a resource that they can be assigned. + +.PARAMETER User + User principal name of user or group + +.PARAMETER ResourceName + The resource(Application, Desktop etc.) name. + Supports only wildcard character '*' when resource type is desktop. + +.PARAMETER Resource + Object(s) of the resource(Application, Desktop etc.) to entitle + +.PARAMETER ResourceType + Type of Resource(Application, Desktop etc) + +.PARAMETER Type + Whether or not this is a group or a user. + +.PARAMETER HvServer + Reference to Horizon View Server. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + +.EXAMPLE + New-HVEntitlement -User 'administrator@adviewdev.eng.vmware.com' -ResourceName 'InsClnPol' -Confirm:$false + Associate a user/group with a pool + +.EXAMPLE + New-HVEntitlement -User 'adviewdev\administrator' -ResourceName 'Calculator' -ResourceType Application + Associate a user/group with a application + +.EXAMPLE + New-HVEntitlement -User 'adviewdev.eng.vmware.com\administrator' -ResourceName 'UrlSetting1' -ResourceType URLRedirection + Associate a user/group with a URLRedirection settings + +.EXAMPLE + New-HVEntitlement -User 'adviewdev.eng.vmware.com\administrator' -ResourceName 'GE1' -ResourceType GlobalEntitlement + Associate a user/group with a desktop entitlement + +.EXAMPLE + New-HVEntitlement -User 'adviewdev\administrator' -ResourceName 'GEAPP1' -ResourceType GlobalApplicationEntitlement + Associate a user/group with a application entitlement + +.EXAMPLE + $pools = Get-HVPool; $pools | New-HVEntitlement -User 'adviewdev\administrator' -Confirm:$false + Associate a user/group with list of pools + + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + param( + [Parameter(Mandatory = $true)] + [ValidatePattern("^.+?[@\\].+?$")] + [String] + $User, + + [Parameter(Mandatory = $true,ParameterSetName ='Default')] + [ValidateNotNullOrEmpty()] + [String] + $ResourceName, + + [Parameter(Mandatory = $true,ValueFromPipeline = $true,ParameterSetName ='PipeLine')] + $Resource, + + [Parameter(Mandatory = $false)] + [ValidateSet('Application','Desktop','GlobalApplicationEntitlement','GlobalEntitlement', + 'URLRedirection')] + [String] + $ResourceType = 'Desktop', + + [Parameter(Mandatory = $false)] + [ValidateSet('User','Group')] + [String] + $Type = 'User', + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + $userInfo = Get-UserInfo -UserName $User + $UserOrGroupName = $userInfo.Name + $Domain = $userInfo.Domain + $IsGroup = ($Type -eq 'Group') + $filter1 = Get-HVQueryFilter 'base.name' -Eq $UserOrGroupName + $filter2 = Get-HVQueryFilter 'base.domain' -Eq $Domain + $filter3 = Get-HVQueryFilter 'base.group' -Eq $IsGroup + $andFilter = Get-HVQueryFilter -And -Filters @($filter1, $filter2, $filter3) + $results = Get-HVQueryResult -EntityType ADUserOrGroupSummaryView -Filter $andFilter -HvServer $HvServer + if ($results.length -ne 1) { + Write-Host "Unable to find specific user or group with given search parameters" + return + } + $ResourceObjs = $null + $info = $services.PodFederation.PodFederation_get() + switch($ResourceType){ + "Desktop" { + if ($ResourceName) { + $ResourceObjs = Get-HVPool -PoolName $ResourceName -suppressInfo $true -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No pool found with given resourceName: " $ResourceName + return + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Resource) { + foreach ($item in $Resource) { + if ($item.GetType().name -eq 'DesktopInfo') { + $ResourceObjs += ,$item + } + elseif ($item.GetType().name -eq 'DesktopSummaryView') { + $ResourceObjs += ,$item + } + else { + Write-Error "In pipeline didn't received object(s) of expected type DesktopSummaryView/DesktopInfo" + return + } + } + } + } + "Application" { + if ($ResourceName) { + $eqFilter = Get-HVQueryFilter 'data.name' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType ApplicationInfo -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No Application found with given resourceName: " $ResourceName + return + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Resource) { + foreach ($item in $Resource) { + if ($item.GetType().name -eq 'ApplicationInfo') { + $ResourceObjs += ,$item + + } else { + Write-Error "In pipeline didn't received object(s) of expected type ApplicationInfo" + return + } + } + } + } + "URLRedirection" { + if ($ResourceName) { + $UrlRedirectionList = $services.URLRedirection.URLRedirection_List() + $ResourceObjs = $UrlRedirectionList | Where-Object { $_.urlRedirectionData.displayName -like $ResourceName} + if (! $ResourceObjs) { + Write-Host "No URLRedirectionData found with given resourceName: " $ResourceName + return + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Resource) { + foreach ($item in $Resource) { + if ($item.GetType().name -eq 'URLRedirectionInfo') { + $ResourceObjs += ,$item + } else { + Write-Error "In pipeline didn't received object(s) of expected type URLRedirectionInfo" + return + } + } + } + } + "GlobalApplicationEntitlement" { + if ("ENABLED" -eq $info.localPodStatus.status) { + if ($ResourceName) { + $eqFilter = Get-HVQueryFilter 'base.displayName' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType GlobalApplicationEntitlementInfo -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No globalApplicationEntitlementInfo found with given resourceName: " $ResourceName + return + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Resource) { + foreach ($item in $Resource) { + if ($item.GetType().name -eq 'GlobalApplicationEntitlementInfo') { + $ResourceObjs += ,$item + } else { + Write-Error "In pipeline didn't received object(s) of expected type globalApplicationEntitlementInfo" + return + } + } + } + } + } else { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + } + "GlobalEntitlement" { + if ("ENABLED" -eq $info.localPodStatus.status) { + if ($ResourceName) { + $eqFilter = Get-HVQueryFilter 'base.displayName' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType GlobalEntitlementSummaryView -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No globalEntitlementSummary found with given resourceName: " $ResourceName + return + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Resource) { + foreach ($item in $Resource) { + if ($item.GetType().name -eq 'GlobalEntitlementSummaryView') { + $ResourceObjs += ,$item + } else { + Write-Error "In pipeline didn't received object(s) of expected type GlobalEntitlementSummaryView" + return + } + } + } + } + } else { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + } + } + $base = New-Object VMware.HV.UserEntitlementBase + $base.UserOrGroup = $results.id + Write-host $ResourceObjs.Length " resource(s) will be entitled with UserOrGroup: " $User + foreach ($ResourceObj in $ResourceObjs) { + $base.Resource = $ResourceObj.id + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) { + $id = $services.UserEntitlement.UserEntitlement_Create($base) + } + } + } + end { + [System.gc]::collect() + } +} + + +function Get-HVEntitlement { +<# +.Synopsis + Gets association data between a user/group and a resource + +.DESCRIPTION + Provides entitlement Info between a single user/group and a resource that they can be assigned. + +.PARAMETER User + User principal name of user or group + +.PARAMETER ResourceName + The resource(Application, Desktop etc.) name. + Supports only wildcard character '*' when resource type is desktop. + +.PARAMETER Resource + Object(s) of the resource(Application, Desktop etc.) to entitle + +.PARAMETER ResourceType + Type of Resource(Application, Desktop etc.) + +.PARAMETER Type + Whether or not this is a group or a user. + +.PARAMETER HvServer + Reference to Horizon View Server. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + +.EXAMPLE + Get-HVEntitlement -ResourceType Application + Gets all the entitlements related to application pool + +.EXAMPLE + Get-HVEntitlement -User 'adviewdev.eng.vmware.com\administrator' -ResourceName 'calculator' -ResourceType Application + Gets entitlements specific to user or group name and application resource + +.EXAMPLE + Get-HVEntitlement -User 'adviewdev.eng.vmware.com\administrator' -ResourceName 'UrlSetting1' -ResourceType URLRedirection + Gets entitlements specific to user or group and URLRedirection resource + +.EXAMPLE + Get-HVEntitlement -User 'administrator@adviewdev.eng.vmware.com' -ResourceName 'GE1' -ResourceType GlobalEntitlement + Gets entitlements specific to user or group and GlobalEntitlement resource + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + param( + [Parameter(Mandatory = $false)] + [ValidatePattern("^.+?[@\\].+?$")] + [String] + $User, + + [Parameter(Mandatory = $false)] + [ValidateSet('User','Group')] + [String] + $Type = 'User', + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [String] + $ResourceName, + + [Parameter(Mandatory = $false)] + [ValidateSet('Application','Desktop','GlobalApplicationEntitlement','GlobalEntitlement', + 'URLRedirection')] + [String] + $ResourceType = 'Desktop', + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $AndFilter = @() + $results = @() + $ResourceObjs = $null + if ($User) { + $userInfo = Get-UserInfo -UserName $User + $UserOrGroupName = $userInfo.Name + $Domain = $userInfo.Domain + $nameFilter = Get-HVQueryFilter 'base.name' -Eq $UserOrGroupName + $AndFilter += $nameFilter + $doaminFilter = Get-HVQueryFilter 'base.domain' -Eq $Domain + $AndFilter += $doaminFilter + } + $IsGroup = ($Type -eq 'Group') + $groupFilter = Get-HVQueryFilter 'base.group' -Eq $IsGroup + $AndFilter += $groupFilter + $info = $services.PodFederation.PodFederation_get() + $cpaEnabled = ("ENABLED" -eq $info.localPodStatus.status) + switch($ResourceType) { + "Desktop" { + if ($ResourceName) { + $ResourceObjs = Get-HVPool -PoolName $ResourceName -suppressInfo $true -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No pool found with given resourceName: " $ResourceName + return + } + $AndFilter += Get-HVQueryFilter 'localData.desktops' -Contains ([VMware.Hv.DesktopId[]]$ResourceObjs.Id) + } + $AndFilter = Get-HVQueryFilter -And -Filters $AndFilter + $results = (Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $AndFilter -HvServer $HvServer) + $results = $results | where {$_.localData.desktops -ne $null} + } + "Application" { + if ($ResourceName) { + $eqFilter = Get-HVQueryFilter 'data.name' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType ApplicationInfo -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No Application found with given resourceName: " $ResourceName + return + } + $AndFilter += Get-HVQueryFilter 'localData.applications' -Contains ([VMware.Hv.ApplicationId[]]$ResourceObjs.Id) + } + $AndFilter = Get-HVQueryFilter -And -Filters $AndFilter + $results = (Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $AndFilter -HvServer $HvServer) + $results = $results | where {$_.localData.applications -ne $null} + } + "URLRedirection" { + $localFilter = @() + $globalFilter = @() + $localFilter += $AndFilter + $globalFilter += $AndFilter + if ($ResourceName) { + $UrlRedirectionList = $services.URLRedirection.URLRedirection_List() + $ResourceObjs = $UrlRedirectionList | Where-Object { $_.urlRedirectionData.displayName -like $ResourceName} + if (! $ResourceObjs) { + Write-Host "No URLRedirectionData found with given resourceName: " $ResourceName + return + } + $localFilter += Get-HVQueryFilter 'localData.urlRedirectionSettings' -Contains ([VMware.Hv.URLRedirectionId[]]$ResourceObjs.Id) + if ($cpaEnabled) { + $globalFilter += Get-HVQueryFilter 'globalData.urlRedirectionSettings' -Contains ([VMware.Hv.URLRedirectionId[]]$ResourceObjs.Id) + } + } + $localFilter = Get-HVQueryFilter -And -Filters $localFilter + $localResults = Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $localFilter -HvServer $HvServer + $results += ($localResults | where {$_.localData.urlRedirectionSettings -ne $null}) + if ($cpaEnabled) { + $globalFilter = Get-HVQueryFilter -And -Filters $globalFilter + $globalResults = Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $globalFilter -HvServer $HvServer + $globalResults = $globalResults | where {$_.globalData.urlRedirectionSettings -ne $null} + $results += $globalResults + } + } + "GlobalApplicationEntitlement" { + if (! $cpaEnabled) { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + if ($ResourceName) { + $eqFilter = Get-HVQueryFilter 'base.displayName' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType GlobalApplicationEntitlementInfo -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No globalApplicationEntitlementInfo found with given resourceName: " $ResourceName + return + } + $AndFilter += Get-HVQueryFilter 'globalData.globalApplicationEntitlements' -Contains ([VMware.Hv.GlobalApplicationEntitlementId[]]$ResourceObjs.Id) + } + $AndFilter = Get-HVQueryFilter -And -Filters $AndFilter + $results = (Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $AndFilter -HvServer $HvServer) + $results = $results| where {$_.globalData.globalApplicationEntitlements -ne $null} + } + "GlobalEntitlement" { + if (! $cpaEnabled) { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + if ($ResourceName) { + $eqFilter = Get-HVQueryFilter 'base.displayName' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType GlobalEntitlementSummaryView -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No globalEntitlementSummary found with given resourceName: " $ResourceName + return + } + $AndFilter += Get-HVQueryFilter 'globalData.globalEntitlements' -Contains ([VMware.Hv.GlobalEntitlementId[]]$ResourceObjs.Id) + } + $AndFilter = Get-HVQueryFilter -And -Filters $AndFilter + $results = (Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $AndFilter -HvServer $HvServer) + $results = $results | where {$_.globalData.globalEntitlements -ne $null} + } + } + if (! $results) { + Write-Host "Get-HVEntitlement: No entitlements found with given search parameters" + break + } + return $results + } + end { + [System.gc]::collect() + } +} + +function Remove-HVEntitlement { +<# +.Synopsis + Deletes association data between a user/group and a resource + +.DESCRIPTION + Removes entitlement between a single user/group and a resource that already been assigned. + +.PARAMETER User + User principal name of user or group + +.PARAMETER ResourceName + The resource(Application, Desktop etc.) name. + Supports only wildcard character '*' when resource type is desktop. + +.PARAMETER Resource + Object(s) of the resource(Application, Desktop etc.) to entitle + +.PARAMETER ResourceType + Type of Resource(Application, Desktop etc) + +.PARAMETER Type + Whether or not this is a group or a user. + +.PARAMETER HvServer + Reference to Horizon View Server. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + +.EXAMPLE + Remove-HVEntitlement -User 'administrator@adviewdev' -ResourceName LnkClnJSon -Confirm:$false + Deletes entitlement between a user/group and a pool resource + +.EXAMPLE + Remove-HVEntitlement -User 'adviewdev\puser2' -ResourceName 'calculator' -ResourceType Application + Deletes entitlement between a user/group and a Application resource + +.EXAMPLE + Remove-HVEntitlement -User 'adviewdev\administrator' -ResourceName 'GEAPP1' -ResourceType GlobalApplicationEntitlement + Deletes entitlement between a user/group and a GlobalApplicationEntitlement resource + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + param( + [Parameter(Mandatory = $true)] + [ValidatePattern("^.+?[@\\].+?$")] + [String] + $User, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [String] + $ResourceName, + + [Parameter(Mandatory = $false)] + [ValidateSet('User','Group')] + [String] + $Type = 'User', + + [Parameter(Mandatory = $false)] + [ValidateSet('Application','Desktop','GlobalApplicationEntitlement','GlobalEntitlement', + 'URLRedirection')] + [String] + $ResourceType = 'Desktop', + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + $AndFilter = @() + $results = $null + $userInfo = Get-UserInfo -UserName $User + $UserOrGroupName = $userInfo.Name + $Domain = $userInfo.Domain + $nameFilter = Get-HVQueryFilter 'base.name' -Eq $UserOrGroupName + $doaminFilter = Get-HVQueryFilter 'base.domain' -Eq $Domain + $IsGroup = ($Type -eq 'Group') + $groupFilter = Get-HVQueryFilter 'base.group' -Eq $IsGroup + [VMware.Hv.UserEntitlementId[]] $userEntitlements = $null + if ($ResourceName) { + $info = $services.PodFederation.PodFederation_get() + switch($ResourceType) { + "Desktop" { + $ResourceObjs = Get-HVPool -PoolName $ResourceName -suppressInfo $true -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No pool found with given resourceName: " $ResourceName + return + } + $AndFilter += Get-HVQueryFilter 'localData.desktops' -Contains ([VMware.HV.DesktopId[]] $ResourceObjs.Id) + $filters = Get-HVQueryFilter -And -Filters $AndFilter + $results = Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $filters -HvServer $HvServer + if ($results) { + foreach ($result in $Results) { + $userEntitlements = $result.localData.desktopUserEntitlements + Write-Host $userEntitlements.Length " desktopUserEntitlement(s) will be removed for UserOrGroup " $user + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) { + $services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($userEntitlements) + } + } + } + } + "Application" { + $eqFilter = Get-HVQueryFilter 'data.name' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType ApplicationInfo -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No Application found with given resourceName: " $ResourceName + return + } + $AndFilter += Get-HVQueryFilter 'localData.applications' -Contains ([VMware.HV.ApplicationId[]] $ResourceObjs.Id) + $AndFilter = Get-HVQueryFilter -And -Filters $AndFilter + $results = Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $AndFilter -HvServer $HvServer + if ($results) { + foreach ($result in $Results) { + $userEntitlements = $result.localData.applicationUserEntitlements + Write-Host $userEntitlements.Length " applicationUserEntitlement(s) will be removed for UserOrGroup " $user + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) { + $services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($userEntitlements) + } + } + } + } + "URLRedirection" { + $UrlRedirectionList = $services.URLRedirection.URLRedirection_List() + $ResourceObjs = $UrlRedirectionList | Where-Object { $_.urlRedirectionData.displayName -like $ResourceName} + if (! $ResourceObjs) { + Write-Host "No URLRedirectionData found with given resourceName: " $ResourceName + return + } + $localFilter = @() + $localFilter += $AndFilter + $localFilter += (Get-HVQueryFilter 'localData.urlRedirectionSettings' -Contains ([VMware.HV.URLRedirectionId[]]$ResourceObjs.Id)) + $localFilter = Get-HVQueryFilter -And -Filters $localFilter + $results = Get-HVQueryResult -EntityType EntitledUserOrGroupLocalSummaryView -Filter $localFilter -HvServer $HvServer + if ("ENABLED" -eq $info.localPodStatus.status) { + $globalFilter = @() + $globalFilter += $AndFilter + $globalFilter += Get-HVQueryFilter 'globalData.urlRedirectionSettings' -Contains ([VMware.HV.URLRedirectionId[]]$ResourceObjs.Id) + $globalFilter = Get-HVQueryFilter -And -Filters $globalFilter + $results += Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $globalFilter -HvServer $HvServer + } + if ($results) { + foreach ($result in $Results) { + if ($result.GetType().Name -eq 'EntitledUserOrGroupLocalSummaryView') { + $userEntitlements = $result.localData.urlRedirectionUserEntitlements + Write-Host $userEntitlements.Length " urlRedirectionUserEntitlement(s) will be removed for UserOrGroup " $user + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) { + $services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($userEntitlements) + } + } else { + $userEntitlements = $result.globalData.urlRedirectionUserEntitlements + Write-Host $userEntitlements.Length " urlRedirectionUserEntitlement(s) will be removed for UserOrGroup " $user + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) { + $services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($userEntitlements) + } + } + } + } + } + "GlobalApplicationEntitlement" { + if ("ENABLED" -ne $info.localPodStatus.status) { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + $eqFilter = Get-HVQueryFilter 'base.displayName' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType GlobalApplicationEntitlementInfo -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No globalApplicationEntitlementInfo found with given resourceName: " $ResourceName + return + } + $AndFilter += Get-HVQueryFilter 'globalData.globalApplicationEntitlements' -Contains ([VMware.Hv.GlobalApplicationEntitlementId[]]$ResourceObjs.Id) + $AndFilter = Get-HVQueryFilter -And -Filters $AndFilter + $results = Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $AndFilter -HvServer $HvServer + if ($results) { + foreach ($result in $Results) { + $userEntitlements = $result.globalData.globalUserApplicationEntitlements + Write-Host $userEntitlements.Length " GlobalApplicationEntitlement(s) will be removed for UserOrGroup " $user + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) { + $services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($userEntitlements) + } + } + } + } + "GlobalEntitlement" { + if ("ENABLED" -ne $info.localPodStatus.status) { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + $eqFilter = Get-HVQueryFilter 'base.displayName' -Eq $ResourceName + $ResourceObjs = Get-HVQueryResult -EntityType GlobalEntitlementSummaryView -Filter $eqFilter -HvServer $HvServer + if (! $ResourceObjs) { + Write-Host "No globalEntitlementSummary found with given resourceName: " $ResourceName + return + } + $AndFilter += Get-HVQueryFilter 'globalData.globalEntitlements' -Contains ([VMware.Hv.GlobalEntitlementId[]]$ResourceObjs.Id) + $AndFilter = Get-HVQueryFilter -And -Filters $AndFilter + $results = Get-HVQueryResult -EntityType EntitledUserOrGroupGlobalSummaryView -Filter $AndFilter -HvServer $HvServer + if ($results) { + foreach ($result in $Results) { + $userEntitlements = $result.globalData.globalUserEntitlements + Write-Host $userEntitlements.Length " GlobalEntitlement(s) will be removed for UserOrGroup " $user + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($User)) { + $services.UserEntitlement.UserEntitlement_DeleteUserEntitlements($userEntitlements) + } + } + + } + } + } + } + if (! $results) { + Write-Host "Remove-HVEntitlement: No entitlements found with given search parameters" + return + } + } + end { + [System.gc]::collect() + } +} + +function Set-HVMachine { +<# +.Synopsis + Sets existing virtual Machine(s). + +.DESCRIPTION + This cmdlet allows user to edit Machine configuration by passing key/value pair. + Allows the machine in to Maintenance mode and vice versa + +.PARAMETER MachineName + The name of the Machine to edit. + +.PARAMETER Machine + Object(s) of the virtual Machine(s) to edit. + +.PARAMETER Maintenance + The virtual machine is in maintenance mode. Users cannot log in or use the virtual machine + +PARAMETER Key + Property names path separated by . (dot) from the root of machine info spec. + +.PARAMETER Value + Property value corresponds to above key name. + +.PARAMETER HvServer + Reference to Horizon View Server to query the virtual machines from. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + +.EXAMPLE + Set-HVMachine -MachineName 'Agent_Praveen' -Maintenance ENTER_MAINTENANCE_MODE + Moving the machine in to Maintenance mode using machine name + +.EXAMPLE + Get-HVMachine -MachineName 'Agent_Praveen' | Set-HVMachine -Maintenance ENTER_MAINTENANCE_MODE + Moving the machine in to Maintenance mode using machine object(s) + +.EXAMPLE + $machine = Get-HVMachine -MachineName 'Agent_Praveen'; Set-HVMachine -Machine $machine -Maintenance EXIT_MAINTENANCE_MODE + Moving the machine in to Maintenance mode using machine object(s) + +.OUTPUTS + None + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + + [CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + + param( + + [Parameter(Mandatory = $true ,ParameterSetName = 'option')] + [string] + $MachineName, + + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'pipeline')] + $Machine, + + [Parameter(Mandatory = $false)] + [ValidateSet('ENTER_MAINTENANCE_MODE', 'EXIT_MAINTENANCE_MODE')] + [string] + $Maintenance, + + [Parameter(Mandatory = $false)] + [string]$Key, + + [Parameter(Mandatory = $false)] + $Value, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + + process { + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + $machineList = @{} + if ($machineName) { + try { + $machines = Get-HVMachineSummary -MachineName $machineName -suppressInfo $true -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVMachineSummary advanced function is loaded, $_" + break + } + if ($machines) { + foreach ($macineObj in $machines) { + $machineList.add($macineObj.id, $macineObj.base.Name) + } + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $Machine) { + foreach ($item in $machine) { + if (($item.GetType().name -eq 'MachineNamesView') -or ($item.GetType().name -eq 'MachineInfo')) { + $machineList.add($item.id, $item.Base.Name) + } else { + Write-Error "In pipeline did not get object of expected type MachineNamesView/MachineInfo" + [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 ($Maintenance) { + if ($Maintenance -eq 'ENTER_MAINTENANCE_MODE') { + $updates += Get-MapEntry -key 'managedMachineData.inMaintenanceMode' -value $true + } else { + $updates += Get-MapEntry -key 'managedMachineData.inMaintenanceMode' -value $false + } + } + $machine_helper = New-Object VMware.Hv.MachineService + foreach ($item in $machineList.Keys) { + Write-Host "Updating the Machine: " $machineList.$item + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($machineList.$item)) { + $machine_helper.Machine_Update($services,$item,$updates) + } + } + } + + end { + [System.gc]::collect() + } + +} + +function New-HVGlobalEntitlement { + + <# +.Synopsis + Creates a Global Entitlement. + +.DESCRIPTION + Global entitlements are used to route users to their resources across multiple pods. + These are persisted in a global ldap instance that is replicated across all pods in a linked mode view set. + +.PARAMETER DisplayName + Display Name of Global Entitlement. + +.PARAMETER Type + Specify whether to create desktop/app global entitlement + +.PARAMETER Description + Description of Global Entitlement. + +.PARAMETER Scope + Scope for this global entitlement. Visibility and Placement policies are defined by this value. + +.PARAMETER Dedicated + Specifies whether dedicated/floating resources associated with this global entitlement. + +.PARAMETER FromHome + This value defines the starting location for resource placement and search. + When true, a pod in the user's home site is used to start the search. When false, the current site is used. + +.PARAMETER RequireHomeSite + This value determines whether we fail if a home site isn't defined for this global entitlement. + +.PARAMETER MultipleSessionAutoClean + This value is used to determine if automatic session clean up is enabled. + This cannot be enabled when this Global Entitlement is associated with a Desktop that has dedicated user assignment. + +.PARAMETER Enabled + If this Global Entitlement is enabled. + +.PARAMETER SupportedDisplayProtocols + The set of supported display protocols for the global entitlement. + +.PARAMETER DefaultDisplayProtocol + The default display protocol for the global entitlement. + +.PARAMETER AllowUsersToChooseProtocol + Whether the users can choose the protocol used. + +.PARAMETER AllowUsersToResetMachines + Whether users are allowed to reset/restart their machines. + +.PARAMETER EnableHTMLAccess + If set to true, the desktops that are associated with this GlobalEntitlement must also have HTML Access enabled. + +.PARAMETER HvServer + Reference to Horizon View Server. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + +.EXAMPLE + New-HVGlobalEntitlement -DisplayName 'GE_APP' -Type APPLICATION_ENTITLEMENT + Creates new global application entitlement + +.EXAMPLE + New-HVGlobalEntitlement -DisplayName 'GE_DESKTOP' -Type DESKTOP_ENTITLEMENT + Creates new global desktop entitlement + + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + +[CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + param( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [String] + $DisplayName, + + [Parameter(Mandatory = $true)] + [ValidateSet('DESKTOP_ENTITLEMENT','APPLICATION_ENTITLEMENT')] + [String] + $Type, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [String] + $Description, + + [Parameter(Mandatory = $false)] + [ValidateSet('LOCAL','SITE','ANY')] + [String] + $Scope = "ANY", + + [Parameter(Mandatory = $false)] + [Boolean] + $Dedicated, + + [Parameter(Mandatory = $false)] + [Boolean] + $FromHome, + + [Parameter(Mandatory = $false)] + [Boolean] + $RequireHomeSite, + + [Parameter(Mandatory = $false)] + [Boolean] + $MultipleSessionAutoClean, + + [Parameter(Mandatory = $false)] + [Boolean] + $Enabled, + + [Parameter(Mandatory = $false)] + [ValidateSet('RDP', 'PCOIP', 'BLAST')] + [String[]] + $SupportedDisplayProtocols = @("PCOIP","BLAST"), + + [Parameter(Mandatory = $false)] + [ValidateSet("PCOIP",'RDP',"BLAST")] + [String] + $DefaultDisplayProtocol = 'PCOIP', + + [Parameter(Mandatory = $false)] + [Boolean] + $AllowUsersToChooseProtocol = $true, + + [Parameter(Mandatory = $false)] + [Boolean] + $AllowUsersToResetMachines = $false, + + [Parameter(Mandatory = $false)] + [Boolean] + $EnableHTMLAccess = $false, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $info = $services.PodFederation.PodFederation_get() + if ("ENABLED" -ne $info.localPodStatus.status) { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + if ($Type -eq 'DESKTOP_ENTITLEMENT') { + $GeService = New-Object VMware.HV.GlobalEntitlementService + $geBaseHelper = $GeService.getGlobalEntitlementBaseHelper() + $geBase = $geBaseHelper.getDataObject() + $geBase.Dedicated = $dedicated + $geBase.AllowUsersToResetMachines = $AllowUsersToResetMachines + } else { + $GeService = New-Object VMware.Hv.GlobalApplicationEntitlementService + $geBaseHelper = $GeService.getGlobalApplicationEntitlementBaseHelper() + $geBase = $geBaseHelper.getDataObject() + } + $geBase.DisplayName = $displayName + if ($description) { + $geBaseHelper.setDescription($Description) + } + $geBase.Scope = $Scope + $geBase.FromHome = $fromHome + $geBase.RequireHomeSite = $requireHomeSite + $geBase.MultipleSessionAutoClean = $multipleSessionAutoClean + $geBase.Enabled = $enabled + $geBase.DefaultDisplayProtocol = $defaultDisplayProtocol + $geBase.AllowUsersToChooseProtocol = $AllowUsersToChooseProtocol + $geBase.EnableHTMLAccess = $enableHTMLAccess + $geBase.SupportedDisplayProtocols = $supportedDisplayProtocols + Write-Host "Creating new global entitlement with DisplayName: " $DisplayName + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($displayName)) { + if ($type -eq 'DESKTOP_ENTITLEMENT') { + $GeService.GlobalEntitlement_Create($services, $geBase) + } else { + $GeService.GlobalApplicationEntitlement_Create($services, $geBase) + } + } + } + end { + [System.gc]::collect() + } + +} + + +function Find-HVGlobalEntitlement { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + $Param, + [Parameter(Mandatory = $true)] + [String] + $Type + ) + + # This translates the function arguments into the View API properties that must be queried + $GeSelectors = @{ + 'displayName' = 'base.displayName'; + 'description' = 'base.description'; + } + + $params = $Param + + $query_service_helper = New-Object VMware.Hv.QueryServiceService + $query = New-Object VMware.Hv.QueryDefinition + + $wildCard = $false + #Only supports wild card '*' + if ($params['displayName'] -and $params['displayName'].contains('*')) { + $wildcard = $true + } + + # build the query values + $query.queryEntityType = $Type + if (! $wildcard) { + [VMware.Hv.queryfilter[]]$filterSet = @() + foreach ($setting in $GeSelectors.Keys) { + if ($null -ne $params[$setting]) { + $equalsFilter = New-Object VMware.Hv.QueryFilterEquals + $equalsFilter.memberName = $GeSelectors[$setting] + $equalsFilter.value = $params[$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) + $GeList = $queryResults.results + } + if ($wildcard -or [string]::IsNullOrEmpty($GeList)) { + $query.Filter = $null + $queryResults = $query_service_helper.QueryService_Query($services,$query) + $strFilterSet = @() + foreach ($setting in $GeSelectors.Keys) { + if ($null -ne $params[$setting]) { + if ($wildcard -and ($setting -eq 'displayName') ) { + $strFilterSet += '($_.' + $GeSelectors[$setting] + ' -like "' + $params[$setting] + '")' + } else { + $strFilterSet += '($_.' + $GeSelectors[$setting] + ' -eq "' + $params[$setting] + '")' + } + } + } + $whereClause = [string]::Join(' -and ', $strFilterSet) + $scriptBlock = [Scriptblock]::Create($whereClause) + $GeList = $queryResults.results | where $scriptBlock + } + Return $GeList +} + +function Get-HVGlobalEntitlement { + + <# +.Synopsis + Gets Global Entitlement(s) with given search parameters. + +.DESCRIPTION + Queries and returns global entitlement(s) and global application entitlement(s). + Global entitlements are used to route users to their resources across multiple pods. + +.PARAMETER DisplayName + Display Name of Global Entitlement. + +.PARAMETER Description + Description of Global Entitlement. + +.PARAMETER SuppressInfo + Suppress text info, when no global entitlement(s) found with given search parameters + +.PARAMETER HvServer + Reference to Horizon View Server. If the value is not passed or null then + first element from global:DefaultHVServers would be considered in-place of hvServer + +.EXAMPLE + Get-HVGlobalEntitlement -DisplayName 'GEAPP' + Retrieves global application/desktop entitlement(s) with displayName 'GEAPP' + + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + +[CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + param( + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [String] + $DisplayName, + + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [String] + $Description, + + [Parameter(Mandatory = $false)] + [boolean] + $SuppressInfo = $false, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $info = $services.PodFederation.PodFederation_get() + if ("ENABLED" -ne $info.localPodStatus.status) { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + $result = @() + $result += Find-HVGlobalEntitlement -Param $psboundparameters -Type 'GlobalEntitlementSummaryView' + $result += Find-HVGlobalEntitlement -Param $psboundparameters -Type 'GlobalApplicationEntitlementInfo' + if (!$result -and !$SuppressInfo) { + Write-Host "Get-HVGlobalEntitlement: No global entitlement Found with given search parameters" + } + return $result + } + end { + [System.gc]::collect() + } +} + + +function Remove-HVGlobalEntitlement { + + <# +.Synopsis + Deletes a Global Entitlement. + +.DESCRIPTION + Deletes global entitlement(s) and global application entitlement(s). + Optionally, user can pipe the global entitlement(s) as input to this function. + +.PARAMETER DisplayName + Display Name of Global Entitlement. + +.PARAMETER HvServer + Reference to Horizon View Server. If the value is not passed or null then + first element from global:DefaultHVServers would be considered inplace of hvServer + +.EXAMPLE + Remove-HVGlobalEntitlement -DisplayName 'GE_APP' + Deletes global application/desktop entitlement with displayName 'GE_APP' + +.EXAMPLE + Get-HVGlobalEntitlement -DisplayName 'GE_*' | Remove-HVGlobalEntitlement + Deletes global application/desktop entitlement(s), if displayName matches with 'GE_*' + + +.NOTES + Author : Praveen Mathamsetty. + Author email : pmathamsetty@vmware.com + Version : 1.1 + + ===Tested Against Environment==== + Horizon View Server Version : 7.0.2, 7.1.0 + PowerCLI Version : PowerCLI 6.5, PowerCLI 6.5.1 + PowerShell Version : 5.0 +#> + +[CmdletBinding( + SupportsShouldProcess = $true, + ConfirmImpact = 'High' + )] + param( + [Parameter(Mandatory = $true, ParameterSetName = 'Default')] + [ValidateNotNullOrEmpty()] + [String] + $DisplayName, + + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'pipeline')] + $GlobalEntitlement, + + [Parameter(Mandatory = $false)] + $HvServer = $null + ) + begin { + $services = Get-ViewAPIService -hvServer $hvServer + if ($null -eq $services) { + Write-Error "Could not retrieve ViewApi services from connection object" + break + } + } + process { + $info = $services.PodFederation.PodFederation_get() + if ("ENABLED" -ne $info.localPodStatus.status) { + Write-Host "Multi-DataCenter-View/CPA is not enabled" + return + } + $confirmFlag = Get-HVConfirmFlag -keys $PsBoundParameters.Keys + $GeList = @() + if ($DisplayName) { + try { + $GeList = Get-HVGlobalEntitlement -DisplayName $DisplayName -suppressInfo $true -hvServer $hvServer + } catch { + Write-Error "Make sure Get-HVGlobalEntitlement advanced function is loaded, $_" + break + } + } elseif ($PSCmdlet.MyInvocation.ExpectingInput -or $GlobalEntitlement) { + foreach ($item in $GlobalEntitlement) { + if (($item.GetType().name -ne 'GlobalEntitlementSummaryView') -and ($item.GetType().name -ne 'GlobalApplicationEntitlementInfo')) { + Write-Error "In pipeline did not get object of expected type GlobalApplicationEntitlementInfo/GlobalEntitlementSummaryView" + [System.gc]::collect() + return + } + $GeList += ,$item + } + } + foreach ($item in $GeList) { + Write-Host "Deleting global entitlement with DisplayName: " $item.base.displayName + if (!$confirmFlag -OR $pscmdlet.ShouldProcess($item.base.displayName)) { + if ($item.GetType().Name -eq 'GlobalEntitlementSummaryView') { + $services.GlobalEntitlement.GlobalEntitlement_Delete($item.id) + } else { + $services.GlobalApplicationEntitlement.GlobalApplicationEntitlement_Delete($item.id) + } + } + } + } + end { + [System.gc]::collect() + } + +} + +Export-ModuleMember Add-HVDesktop,Add-HVRDSServer,Connect-HVEvent,Disconnect-HVEvent,Get-HVPoolSpec,Get-HVInternalName, Get-HVEvent,Get-HVFarm,Get-HVFarmSummary,Get-HVPool,Get-HVPoolSummary,Get-HVMachine,Get-HVMachineSummary,Get-HVQueryResult,Get-HVQueryFilter,New-HVFarm,New-HVPool,Remove-HVFarm,Remove-HVPool,Set-HVFarm,Set-HVPool,Start-HVFarm,Start-HVPool,New-HVEntitlement,Get-HVEntitlement,Remove-HVEntitlement, Set-HVMachine, New-HVGlobalEntitlement, Remove-HVGlobalEntitlement, Get-HVGlobalEntitlement