VMware Cloud Community
ITJef
Enthusiast
Enthusiast

Horizon + PowerCLI

I am writing a script to automate the creation of a VDI and entitlement. The one issue i am having is how do i assign a VM to an existing pool? I can use add-poolentitlement to entitle the user to a pool and i can use update-userownership to add a user to the VM however i can't find the syntax necessary for adding a newly created VM to an existing pool.

12 Replies
LucD
Leadership
Leadership

Aren't Update-ManualPool and/or Update-ManualUnmangedPool doing that?

Btw, which Horizon version are we talking about?

And which PowerCLI version are you using?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ITJef
Enthusiast
Enthusiast

I am running Horizon 7.0.3 and i installed the version of view powercli that came with that install.

the update-manualpool commandlets do not allow you to add a VM to that pool. Based on the help screen it allows me to change settings about the pool.

0 Kudos
LucD
Leadership
Leadership

The PSSnapin that comes with Horizon 7.* is not the most recent one afaik.

In PowerCLI 6.5.* there is a new module and a HVHelper module, these give you access to the View API.

See Alan's GETTING STARTED WITH POWERCLI 6.5 AND HORIZON VIEW to start.

With access to the API you should be able to access all functionality.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

ITJef
Enthusiast
Enthusiast

ok thanks this helps. I  am taking a look at it now to see how to modify pools.

0 Kudos
LucD
Leadership
Leadership

Let me know if you get stuck.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ITJef
Enthusiast
Enthusiast

This helped tremendously. I am able to add a machine to the pool and entitle the user to the pool. with the commands below. The one last step is entitling the user to the machine in the pool.

THIS WORKS

add-hvdesktop -pool $vmviewpool -machines $vm -users $username  = add machine to pool

New-HVEntitlement -User $username -ResourceName $vmviewPool = add user to pool

THIS DOES NOT WORK

new-hventitlement -resourcetype 'Desktop' -ResourceName 'win7x64entpool' -resource 'vmNameHere'

New-HVEntitlement : Parameter set cannot be resolved using the specified named

parameters.

At line:1 char:1

+ new-hventitlement -resourcetype 'Desktop' -ResourceName

'win7x64entpool ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~~~

    + CategoryInfo          : InvalidArgument: (:) [New-HVEntitlement], Parame

   terBindingException

    + FullyQualifiedErrorId : AmbiguousParameterSet,New-HVEntitlement

what am i doing wrong here? When i look at the source of those powershell modules i have the syntax correct. THis is the last step for me. Any help you can provide would be appreciated.

thanks in advance

0 Kudos
LucD
Leadership
Leadership

You can't use Resource and ResourceName together.

They belong to two different parametersets.

entitlement.png


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ITJef
Enthusiast
Enthusiast

Seeing the issue below when i tweak it. I will work through these errors. Seems like specifying the VM name isn't good i need to query the VM another way. I tried get-hvmachine didnt work so i am looking into other methods. Making progress though

PowerCLI C:\Users\a-jaldrich\Desktop> new-hventitlement -User "username" -Resource 'VMName-01' -resourcetype 'Desktop'

new-hventitlement : In pipeline didn't received object(s) of expected type

DesktopSummaryView/DesktopInfo

At line:1 char:1

+ new-hventitlement -User "username" -Resource 'VMName-01'

-resourcetype  ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~~~

    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException

    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExceptio

   n,New-HVEntitlement

0 Kudos
estanev
Enthusiast
Enthusiast

Create a module with the following functions, for example you can name it addvmtopool.psm1:

<# .SYNOPSIS Get a View Pool object for a manual VC-managed pool. .DESCRIPTION Returns a manual Pool object or throws an exception, use for input validation .PARAMETER pool The pool's ID string to use, alternatively can accept an existing Pool object to validate it's a manual VC-managed type. #>

function Get-ManualPool

{

   param ($pool = $(Read-Host -prompt "Pool ID"))

   if ($pool.GetType().Name -eq "String") {

      # treat a string as a pool_id, get Pool object

      $pool = Get-Pool -pool_id $pool

      if ($pool -eq $null) {

         Throw "Pool not found"

      }

   }

   if ($pool.GetType().Name -ne "Pool") {

      Throw "Pool is of unknown type: " + $pool.GetType()

   }

   if ($pool.deliveryModel -ne "Manual") {

      Throw "Pool must be manual"

   }

   if ($pool.vcServerName -eq $null) {

      Throw "Pool must be VC managed"

   }

   return $pool

}

<# .SYNOPSIS Get a View DesktopVM object for use in a manual VC-managed pool. .DESCRIPTION Return a DesktopVM instance for the specified VM .PARAMETER vm The VM's ID string to use, alternatively can accept an existing DesktopVM object to validate it's of the correct type. .PARAMETER vc_id The GUID representing the vCenter instance to filter by. .PARAMETER in_pool Whether the VM is expected to be in an existing pool or not. #>

function Get-ManualPoolVm

{

   param (          $vm      = $(Read-Host -prompt "VM name"),

          [String]  $vc_id   = $(Read-Host -prompt "VC guid"),

          [Boolean] $in_pool = $false)

   # need VC guid only

   if ($vc_id.GetType().Name -eq "ViewVC") {

      $vc_id = $vc_id.vc_id

   }

   # make sure we have a valid VM

   if ($vm.GetType().Name -eq "String") {

      # treat string as VM name, we can filter by VC matching $pool

      $vm = Get-DesktopVM -vc_id $vc_id -name $vm

      if ($vm -eq $null) {

         Throw "VM not found"

      }

   }

   if ($vm.GetType().Name -ne "DesktopVM") {

      Throw "VM is of unknown type: " + $vm.GetType()

   }

   if ($vm.isInPool -ne $in_pool) {

      Throw "VM has invalid isInPool value"

   }

   if ($vm.vc_id -ne $vc_id) {

      Throw "VM is not in the correct vCenter instance"

   }

   return $vm

}

<# .SYNOPSIS Get the associated ADSI object for VM/pool. .DESCRIPTION Return an ADSI object for the specified DN on localhost. .PARAMETER pool Either a Pool object or its ID. .PARAMETER vm Either a DesktopVM object or its ID. .PARAMETER dn The DN string. Alternatively, can pass in a Pool or DesktopVM object. #>

function Get-ViewAdsiObj

{

   param ([String]$dn = $null,

          $pool = $null,

          $vm = $null)

   # allow overloaded param as pool or vm

   if ($pool -ne $null) {

      if ($pool.GetType().Name -eq "Pool") {

         $pool = $pool.pool_id

      }

      $dn = ("cn=" + $pool + ",ou=server groups,dc=vdi,dc=vmware,dc=int")

   }

   if ($vm -ne $null) {

      if ($vm.GetType().Name -eq "DesktopVM") {

         $vm = $vm.machine_id

      }

      $dn = ("cn=" + $vm + ",ou=servers,dc=vdi,dc=vmware,dc=int")

   }

   if ($dn -eq $null) {

      Throw "Need to specify a DN"

   }

   # return ADSI object

   return [ADSI]("LDAP://localhost:389/" + $dn)

}

<# .SYNOPSIS Add a new VM to an existing manual pool .DESCRIPTION Adds the specified DesktopVM object and adds it to the existing manual pool. This is done by first creating a new temporary pool with the VM in, moving the VM to the existing pool, and finally deleting the temporary pool. .PARAMETER pool Either a Pool object or its ID. .PARAMETER vm Either an existing DesktopVM object or its ID. #>

function Add-ManualPoolVm

{

   param ($pool = $(Read-Host -prompt "Pool ID"),

          $vm = $(Read-Host -prompt "VM name"))

   $pool = Get-ManualPool $pool

   $vm = Get-ManualPoolVm -vm $vm -vc_id $pool.vc_id -in_pool $false

   # do the add

   $guid = "TMPPOOLADD-" + [Guid]::NewGuid()

   $tmppool = Add-ManualPool -pool_id $guid -vc_id $vm.vc_id -vm_id_list $vm.id

   try {

      # need an updated entry

      $vm = Get-ManualPoolVm -vm $vm.name -vc_id $vm.vc_id -in_pool $true

      $vm = Move-ManualPoolVm -vm $vm -pool $pool

   } finally {

      Remove-Pool -pool_id $guid -DeleteFromDisk $false

   }

   return $vm

}

<# .SYNOPSIS Move a VM from one manual pool to another .DESCRIPTION Removes the specified DesktopVM from its existing manual pool and adds it to the specified one. .PARAMETER pool Either a Pool object or its ID. .PARAMETER vm Either an existing DesktopVM object or its ID. #>

function Move-ManualPoolVm

{

   param ($pool = $(Read-Host -prompt "Pool ID"),

          $vm = $(Read-Host -prompt "VM name"))

   $pool = Get-ManualPool $pool

   $vm = Get-ManualPoolVm -vm $vm -vc_id $pool.vc_id -in_pool $true

   $oldPool = Get-ManualPool $vm.pool_id

   $vmAdam = Get-ViewAdsiObj -vm $vm

  $oldPoolAdam = Get-ViewAdsiObj -pool $oldPool

  $newPoolAdam = Get-ViewAdsiObj -pool $pool

   $vmDn = [String]($vmAdam.distinguishedName)

   # remove VM from the old pool

   $oldPoolAdam."pae-MemberDn".Remove($vmDn)

   $oldPoolAdam.SetInfo()

   # add VM to the new pool

   $newPoolAdam."pae-MemberDn".Add($vmDn)

   $newPoolAdam.SetInfo()

   $vm.pool_id = $pool.pool_id

   return $vm

}

<# .SYNOPSIS Removes a DesktopVM from a manual pool .DESCRIPTION Removes the DesktopVM from the specified pool, by removing its entry from ADAM and then clearing its View configuration information from the machine.id field. The pool parameter is used as a safety check. .PARAMETER pool Either a Pool object or its ID. .PARAMETER vm Either an existing DesktopVM object or its ID. .PARAMETER clearMid Clean the machine.id field for the VM, this is needed if you are not planning to delete it, but does require the vSphere PowerCLI cmdlets to be loaded. #>

function Remove-ManualPoolVm

{

   param ($pool = $(Read-Host -prompt "Pool ID"),

          $vm = $(Read-Host -prompt "VM name"),

          [Boolean]$clearMid = $true)

   $pool = Get-ManualPool $pool

   $vm = Get-ManualPoolVm -vm $vm -vc_id $pool.vc_id -in_pool $true

   if ($pool.pool_id -ne $vm.pool_id) {

      Throw "VM is not in the correct pool"

   }

   # remove from ADAM

   $serverOu = Get-ViewAdsiObj -dn "ou=servers,dc=vdi,dc=vmware,dc=int"

   $serverOu.Delete("pae-VM", "cn=" + $vm.machine_id)

   $serverOu.SetInfo()

   # set machine.id field

   if ($clearMid -eq $true) {

      Clear-ViewMachineIdConfig -vm $vm.name

   }

}

Then use to add a VM to existing pool:

$user = Get-Credential

$session = New-PSSession -ComputerName MyViewHost -Credential $user
$vmname = 'vm01'
Invoke-Command -Command {Import-Module C:\addvmtopool.psm1} -Session $session

Invoke-Command -ScriptBlock {Add-ManualPoolVm -pool "MyExistingPool" -vm "$using:vmname"} -Session $session

estanev
Enthusiast
Enthusiast

forgot to mention that i'm running Horizon 6.2.0

ITJef
Enthusiast
Enthusiast

Thanks i will look how to adapt this for horizon 7.

0 Kudos
jkollbach
Contributor
Contributor

Here is the solution:

https://www.retouw.nl/powercli/adding-manual-desktops-in-horizon-view-and-assigning-them-using-power...

get-hvmachine -machinename $yourcomputer | set-hvmachine -key base.user -Value $userObjId

$userObjId has to be of a specific VMware type - see link above or check the module VMware.Hv.Helper

you could do something like this:

function Get-HVMyUserObject

{

     param(

          $HvServer,

          [string]$username # in form of just the basename without domain

     )

     $hvqdef = New-Object VMware.Hv.QueryDefinition

     $hvqdef.QueryEntityType = 'ADUserOrGroupSummaryView'

     [VMware.Hv.QueryFilter[]]$filters = $null

     $userNameFilter = New-Object VMware.Hv.QueryFilterEquals -Property @{'memberName' = 'base.name'; 'value' = $username }

     $hvqdef.Filter = $userNameFilter

     $queryservice_helper = New-Object VMware.Hv.QueryServiceService

     $result =$queryservice_helper.QueryService_Query($hvserver.ExtensionData,$hvqdef)

     return $result.Results

}

$myUserObj = Get-HVMyUserObject -hvserver $myHvServer -username $myBaseUserName

get-hvmachine -machinename $yourComputerName | set-hvmachine -key base.user -Value $myUserObj.Id

0 Kudos