The VMware Labs flings monthly for March 2019

We’re already into April that means it’s time for the flings update for March. There have been 3 updates and two new flings. I already have a blogpost about one of the updated flings: The Horizon Helpdesk Utility. The new flings are: Identity Manager Migration/Backup Tool and Physical Desktop as a Thin Client. The updated ones are: vSAN Hardware Compatibility List Checker, vSphere HTML5 Web Client and as said earlier the Horizon Helpdesk Utility.

New Releases

[sta_anchor id=”thinclient” /]

Physical Desktop as a Thin Client

Personally I don’t see the added value for this fling since there are already plenty of products that provide the functionality and you can even do it yourself with gpo’s. (and the logo is outdated as well)

A thin client is a stateless, fanless desktop terminal that has no hard drive. Thin clients provide businesses a cost-effective way to access virtual desktop infrastructures (VDI). To simplify the operation steps to access VDI, some features are embedded in thin clients.

For example:

  • Launch the RDP client default
  • Hide desktop/task bar
  • Disable system options to prevent user using other applications

And so on

This Fling will convert physical desktop as a thin client. It will restrict end-users’ behaviors when users log into physical desktops. After user logged in, Horizon view client will be launched automatically and other applications are forbidden to switch. Physical desktop will log off automatically once user exit Horizon view clients.

[sta_anchor id=”idmbackup” /]

Identity Manager Migration/Backup Tool

The Identity Manager Migration/Backup Tool helps you in migrating vIDM settings between environments.

Identity Manager Migration/Backup Tool automates the process of exporting or importing applications and entitlements from one Identity Manager instance to another. If entitlements exists, they will also be backed up to an XML file. This Fling uses Identity Manager API’s for Export, Import, Delete and applying entitlements.

Updated flings

[sta_anchor id=”vsanhcl” /]

vSAN Hardware Compatibility List Checker

With the vSAN Hardware Compatibility List Checker you can check easily if you’re hardware is supported for VSAN.

Changelog

Version 2.1

  • Fixed the bug that firmware version of some controllers can’t be fetched

Version 2.0

  • Add 3 new checks
  • Controller is VMware certified for ESXi release
  • Controller driver is VMware certified
  • Controller firmware is VMware certified
  • Update HTML report format
  • Bug fixes

[sta_anchor id=”html5″ /]

vSphere HTML5 Web Client

Nuf said about this one.

Changelog

Fling 4.1.0 – Build 12518617
New Features

  • Hiding VMs in Hosts and Clusters view – A very popular desktop client feature is brought into the vSphere HTML5 client where you can go to User’s menu, select My preferences and Inventory tab from where you can show/hide VMs in Hosts and Clusters view by selecting the checkbox.
  • User’s menu -> My preferences will have additional preference options like Language, Time Zone, Console and Inventory
  • Developer Center now has API Explorer tab listing all the REST APIs exposed by vSphere SDK.
  • New layout for the feedback tool and feedback tool can be invoked even when a dialog is open on the screen. This enables taking the screenshot of the client including the dialogs. Also, feedback tool now has the ability to add screenshots, this will help you compare the features between different clients and upload the screenshots.

Improvements

  • We added the support back to 6.0 vCenters to the fling. You can now point vSphere HTML5 client fling v4.1 to 6.0 or 6.5 or 6.7 version of vCenter servers.
  • License expiration notification now is increased from 60 to 90 days and includes all the licenses
  • Evaluation License is now shown in the licenses list
  • Sorting and Filtering by License Expiration date in the Licenses list

Known Issues

  • New layout of the feedback tool has issues in the Firefox browser, so you will see old feedback tool in that browser.
  • There are some areas where feedback tool might not capture the screenshot of the dialog, like VM edit settings.

[sta_anchor id=”horizonhelpdesk” /]

Horizon Helpdesk Utility

For a more complete overview of the Horizon Helpdesk Utility fling so the link I posted in the intro to my previous blogpost.

Changelog

Version 1.3.3.1

  • Removed machine listings from session view (overkill)
  • Improved Environment view to include metrics on all connected infrastructure:
    • vSphere
    • Hosts
    • Datastores
    • Remote Pods
    • Events
    • Problem Machines
  • Added repeated queries for logon breakdown if missed on first instance
  • Added event query support for logon breakdown
  • Added events view for Farm and Desktop pools
  • Added inbuilt find / search to users / machines in pool views
  • Added support for multiselect in pool / farm views
  • Added graph / chart views of machines / sessions and problem machines on the environment overview
  • Added a pod switcher to the environment overview
  • Added a global search to the environment overview
  • Added support for Pod Jumping.
    • the ability to jump to a pod on demand
    • the ability to jump to a pod a session belongs to
  • Added support for an architecture view of Desktop Pools
  • Added support for an architecture view of Farms
    • Enhanced view of servers load evaluator value
  • Added bulk user tasks via pool or farm views:
    • Bulk messaging
    • Bulk log off
    • Bulk disconnect
    • Bulk reset
    • Bulk restart
  • Added support for a local pod view (AKA environment view):
    • Connection servers
    • Farms
    • Desktop pools
  • Added documentation (finally)
  • Added MSI installation support
  • Added a start time column to user sessions (this will persist as a preference)

The Horizon Helpdesk Utility fling version 1.3.3.1 has been released

Last august I posted about a then new fling: the Horizon Helpdesk Utility While that release was great Andrew added a whole lot more of awesomeness.

Changelog

Version 1.3.3.1

  • Removed machine listings from session view (overkill)
  • Improved Environment view to include metrics on all connected infrastructure:
    • vSphere
    • Hosts
    • Datastores
    • Remote Pods
    • Events
    • Problem Machines
  • Added repeated queries for logon breakdown if missed on first instance
  • Added event query support for logon breakdown
  • Added events view for Farm and Desktop pools
  • Added inbuilt find / search to users / machines in pool views
  • Added support for multiselect in pool / farm views
  • Added graph / chart views of machines / sessions and problem machines on the environment overview
  • Added a pod switcher to the environment overview
  • Added a global search to the environment overview
  • Added support for Pod Jumping.
    • the ability to jump to a pod on demand
    • the ability to jump to a pod a session belongs to
  • Added support for an architecture view of Desktop Pools
  • Added support for an architecture view of Farms
    • Enhanced view of servers load evaluator value
  • Added bulk user tasks via pool or farm views:
    • Bulk messaging
    • Bulk log off
    • Bulk disconnect
    • Bulk reset
    • Bulk restart
  • Added support for a local pod view (AKA environment view):
    • Connection servers
    • Farms
    • Desktop pools
  • Added documentation (finally)
  • Added MSI installation support
  • Added a start time column to user sessions (this will persist as a preference)

Let’s take a look some of the new goodies, the first change is that you now get a proper connection alert:

The POD switcher

The show environment button will show you the environment as seen from the pod you are currently connected to. A lot of tabs with health information about those components and some counts on sessions, machines and problem machines.

The address behind Connected To will send you to the Horizon Admin Console, this might sound small but I like it!

When you open a pool this is what you see

All of the events for that pool and yes you can sort & filter them!

Some details for a users session

If there are multiple sessions (unlike in my lab) you can select them and mass send messages or do other actions against them.

The view for an RDS farm

So yes the best Horizon helpdesk tool ever just got improved by a 100%!

 

 

 

Applying Golden Images for VDI & RDS cloned pools using the Horizon View API’s

Recently I came up with the idea to create a script to apply new Golden Images against the various types of desktop pools and farms that we have in Horizon View. This was something that I thought was not available from the vmware.hv.helper module but after some research I did find that it it available from the module by using start-hvpool and start-hvfarm. No those are not the best names for the functions in my opinion. This wouldn’t stop me for creating this post though on how to apply the images using api’s only since the module uses mapentries and I still hate those. I will cover full clones and defining a new image without recomposing in a next post since that requires updating the pools.

Let’s take a look at the api explorer on what is needed to recompose or push an image.

 

The DesktopPushImageSpec for instant clones has a comparable setup with some nuance differences.

For RDS farms the linked clones spec is equal to the desktop spec but for instant clones there’s a rather big difference but I will cover that later on.

So the common steps for most types of applying the golden image are:

  • Selecting the Desktop Pool or RDS Farm
  • getting the id for the vcenter or datacenter where the parent VM lives
  • getting the id of the Parent VM
  • getting the id of the snapshot to use
  • getting the id’s of the machines in the desktop pool (Linked Clones only)
  • Select date & time for the recompose or imagepush (if required)
  • combine the above info into a spec to recompose or imagepush
  • Apply the recompose or ImagePush

Each step uses information from the step above it.

Selecting the Desktop Pool or RDS Farm

This can be done using queries. For desktops we user the desktopsummaryview definition and for farms farmsummaryview.

$poolname="pod02_LC"
$queryservice=New-Object VMware.Hv.QueryServiceService
$defn=new-object VMware.Hv.QueryDefinition
$defn.QueryEntityType='DesktopSummaryView'
$defn.Filter= New-Object VMware.Hv.QueryFilterEquals -property @{'MemberName'='desktopSummaryData.name'; 'value'=$poolname}
$desktoppool=($queryservice.QueryService_Create($services1, $defn)).results

And for a farm

$farmname="rds_IC"
$queryservice=New-Object VMware.Hv.QueryServiceService
$defn=new-object VMware.Hv.QueryDefinition
$defn.QueryEntityType='FarmSummaryView'
$defn.Filter= New-Object VMware.Hv.QueryFilterEquals -property @{'MemberName'='data.name'; 'value'=$farmname}
$farm=($queryservice.QueryService_Create($services1, $defn)).results

getting the id for the vcenter or datacenter where the parent VM lives

For desktops this is a property of the $desktoppool object we have now

$desktopppoolvcenterid=$desktoppool.desktopsummarydata.VirtualCenter

For automated farms we need a small extra step since it is not property for the summary data we we can get it by doing a farm_get with the id we received from the query

$farmvcenterid=($services1.Farm.Farm_Get($farm.id)).automatedfarmdata.VirtualCenter

getting the id of the Parent VM

Using the vcenterid as done below we are able to list all vm’s in the vCenter that might be a Golden Image using

$services1.BaseImageVm.BaseImageVm_List($desktopppoolvcenterid)

You might be able to see it but this gives a list of all VM’s in the vCenter, sadly there is no query for this yet even though that would be really useful. If you know the exact name you can select on that but if you look at the IncompatibleReasons property there’s info to filter (if you want to create a menu for example)

$baseimagevmlist=$services1.BaseImageVm.BaseImageVm_List($desktopppoolvcenterid)
$baseimagevmlist.IncompatibleReasons

InUseByDesktop is a usable one for instantclones. I don’t know why InUseByLinkedCloneDesktop doesn’t give any true values even though I have one pool with linked clones, viewcomposerreplica does work. I have filtered this on some of the more obvious ones and end up with both my golden images for Windows 7 & Server 2016

$baseimagevmlist |where {$_.IncompatibleReasons.InUseByDesktop -eq $false -and $_.IncompatibleReasons.InstantInternal -eq $false -and $_.IncompatibleReasons.ViewComposerReplica -eq $false}

I will do it easy and select on the name for now

$Desktopbaseimagevm=$baseimagevmlist | where {$_.name -eq "GI_H72"}
$farmbaseimagevm=$baseimagevmlist | where {$_.name -eq "rds_template"}

getting the id of the snapshot to use

With the baseimagevmid we can utilize the baseimagesnapshot method to get the id for the snapshot.

$desktopsnapshotlist=$services1.BaseImageSnapshot.BaseImageSnapshot_List($Desktopbaseimagevm.id)
$farmsnapshotlist=$services1.BaseImageSnapshot.BaseImageSnapshot_List($farmbaseimagevm.id)

In this there is also an IncompatibleReasons property but that doesn’t give a lot of information so we’ll need to filter on name.

$desktopLCsnapshot=$desktopsnapshotlist | where-object {$_.name -eq "gi_linked"}
$desktopICsnapshot=$desktopsnapshotlist | where-object {$_.name -eq "snap_gi"}
$farmsnapshot=$farmsnapshotlist | where-object {$_.name -eq "gi_rds_2016"}

getting the id’s of the machines in the desktop pool

As you’ll see later in the spec there’s a requirement to list the machine id’s for the pool if you want to do a recompose. These can be grabbed by doing a query

$queryService = New-Object VMware.Hv.QueryServiceService
$defn = New-Object VMware.Hv.QueryDefinition
$defn.queryEntityType = 'MachineSummaryView'
$defn.filter=New-Object VMware.Hv.QueryFilterEquals -property @{'memberName'='base.desktop'; 'value'=$desktoppool.id}
$QueryResults=$queryService.Queryservice_create($Services1, $defn)
$desktopmachinelist=$queryresults.results

For Linked Clone RDS farms you ned to use the QueryEntityType of RDSServerSummaryView but since I don’t have those in my lab I can only show the theory

$queryService = New-Object VMware.Hv.QueryServiceService
$defn = New-Object VMware.Hv.QueryDefinition
$defn.queryEntityType = 'RDSServerSummaryView'
$defn.filter=New-Object VMware.Hv.QueryFilterEquals -property @{'memberName'='base.desktop'; 'value'=$farm.id}
$QueryResults=$queryService.Queryservice_create($Services1, $defn)
$farmmachinelist=$queryresults.results

Settings date and time for the action

It’s not required to set a date and but is very usable if you want to schedule an action. Please be aware that this is based on us format for day and time so mm-dd-yyyy otherwise I would have scheduled it for august.

$datetime=[DateTime]"02-08-2019 10:00:00AM"

The [DateTime] converts the string that follows it to a variable of the type day and time

combine the above info into a spec to recompose or imagepush.

To build the spec we first need to declare a new object with new-object vmware.hv.DesktopRecomposeSpec please be aware that for this name you need to look at the data object in the API explorer and not the class.

$desktoprecomposespec=new-object vmware.hv.DesktopRecomposeSpec
$desktoprecomposespec.ParentVm=$desktopbaseimagevm.id
$desktoprecomposespec.Snapshot=$desktopLCsnapshot.id
$desktoprecomposespec.StartTime=$datetime
$desktoprecomposespec.LogoffSetting="WAIT_FOR_LOGOFF"
$desktoprecomposespec.StopOnFirstError=$true
$desktoprecomposespec.Machines=$desktopmachinelist.id

For the instant clone image push there’s an extra layer required for the settings

$desktopimagepushspec=new-object VMware.Hv.DesktopPushImageSpec
$desktopimagepushspec.settings=new-object vmware.hv.DesktopPushImageSettings
$desktopimagepushspec.ParentVm=$desktopbaseimagevm.id
$desktopimagepushspec.snapshot=$desktopICsnapshot.id
$desktopimagepushspec.settings.StartTime=$datetime
$desktopimagepushspec.settings.LogoffSetting="WAIT_FOR_LOGOFF"
$desktopimagepushspec.settings.StopOnFirstError=$true

The recompose for a linked clone rds farm is similar to the desktop linked clone.

$farmrecomposespec=new-object vmware.hv.farmRecomposeSpec
$farmrecomposespec.ParentVm=$farmbaseimagevm.id
$farmrecomposespec.Snapshot=$farmLCsnapshot.id
$farmrecomposespec.StartTime=$datetime
$farmrecomposespec.LogoffSetting="WAIT_FOR_LOGOFF"
$farmrecomposespec.StopOnFirstError=$true
$farmrecomposespec.Machines=$farmmachinelist.id

For RDS instant clone farms the pushing of a new image is part of the maintenance schedule that can be done immediate or recurring. I will do the recurring option for now since rds hosts needs to be refreshed every once in a while anyway. There’s some options inside the settings that are explained in the api explorer.

$farmmaintenancespec=new-object vmware.hv.FarmMaintenanceSpec
$farmmaintenancespec.recurringMaintenanceSettings=new-object vmware.hv.FarmRecurringMaintenanceSettings
$farmmaintenancespec.imageMaintenanceSettings=new-object vmware.hv.FarmImageMaintenanceSettings
$farmmaintenancespec.maintenanceMode="RECURRING"
$farmmaintenancespec.scheduledTime=$datetime
$farmmaintenancespec.logoffsetting="WAIT_FOR_LOGOFF"
$farmmaintenancespec.stopOnFirstError=$true
$farmmaintenancespec.recurringMaintenanceSettings.startTime="23:00"
$farmmaintenancespec.recurringMaintenanceSettings.maintenancePeriod="WEEKLY"
$farmmaintenancespec.recurringMaintenanceSettings.startInt=1
$farmmaintenancespec.ImageMaintenanceSettings.parentVm=$farmbaseimagevm.id
$farmmaintenancespec.ImageMaintenanceSettings.snapshot=$farmsnapshot.id

Apply the recompose or ImagePush

This is the easiest part of the spec’s have been build properly.

Please note that the variables for the pools I use are a bit different to show the linked and instant clone pools

$services1.Desktop.Desktop_Recompose($linkedclonepool.id,  $desktoprecomposespec)
$services1.Desktop.Desktop_SchedulePushImage($instantclonepool.id, $desktopimagepushspec)
$services1.farm.Farm_ScheduleMaintenance($farm.id, $farmmaintenancespec)

No visible feedback but it’s visible from the admin console (sadly not all tasks can be gotten from the api’s yet 🙁 )

That’s it for now but expect future posts about full clones, setting a default image for linked clones without recompose and maybe a complete script that does it all for you.

The VMware Labs flings monthly for January 2019

One month down, eleven to go for 2019! I am very busy planning the first Nutanix User Group meet and hopefully I will be selected again as vExpert. You can also still apply for vExpert at http://vexpert.vmware.com/. Back to the flings, this month there has been one new release:  Policy Enforcer and four updates: ESXi Embedded Host Client,
vSphere HTML5 Web Client, vSAN Hardware Compatibility List Checker and vSphere PKS Plugin.

New Releases

[sta_anchor id=”policyenforcer” /]

Policy Enforcer

Policy Enforcer is used to check and remediate restriction policies on a Workspace ONE Managed Windows 10 machine. If a user were to try to override configured Policy CSP settings by attempting to edit the Windows Registry, Policy Enforcer will compare the current value with the MDM configured value and reset the registry if the values differ.

Policy Enforcer can be implemented by uploading the MSI installer to the WS1 UEM console and deploying as an internal app via Apps & Books.

Updated

[sta_anchor id=”vsancompatchecker” /]

vSAN Hardware Compatibility List Checker

With the vSAN Hardware Compatibility List Checker you are able to test your hardware against the vSAN Hardware Compatibility list.

The vSAN Hardware Compatibility List Checker is a tool that verifies all installed storage adapters against the vSAN supported storage controller list. The tool will verify if the model, driver and firmware version of the storage adapter are supported.

Using a supported storage controller and firmware is important in a vSAN deployment to ensure normal operations, optimal performance, and to reduce the chances of hardware/firmware issues. This tool can be useful to ensure that a storage device and its firmware went through certification testing supported by VMware and its partners.

Some scenarios where the tool can be useful:

  • Verify if new server and storage adapter are supported for a vSAN deployment
  • Verify if re-purposed server, storage adapter are supported for a vSAN deployment

For a full vSAN system check, please check vSAN health UI through vSphere web client after a vSAN deployment.

Changelog

Version 2.0

  • Add 3 new checks
  • Controller is VMware certified for ESXi release
  • Controller driver is VMware certified
  • Controller firmware is VMware certified
  • Update HTML report format
  • Bug fixes

[sta_anchor id=”vspherepksplugin” unsan=”vSpherePKSPlugin” /]

vSphere PKS Plugin

The vSphere PKS plugin gives the administrator a graphical interface within the vSphere HTML5 console.

Changelog

Version 1.0.1 – Build 168317

  • A PKS instance can be added to the plugin by providing the Ops Manager credentials
  • Support an alternate IP address (such as an NSX floating IP) to be used as the registration server and plugin server IP. It is assumed that the IP will be mapped to the appliance’s NIC via other means
  • Minor bug fixes

[sta_anchor id=”esxihostclient” /]

ESXi Embedded Host Client

The latest and greatest version of the ESXi embedded host client as found in production since ESXi6.0

Changelog

Version 1.33.1 build 12086396 (Fling 23) – January 31, 2019
OVF issues 

  • Various fixes for ovf import issues
  • ISO files are now imported from OVAs

General 

  • Fixed an issue with special characters in datastore names in some versions of ESXi
  • Fix swapped labels for transmit and receive in network chart
  • Network adapters are added to the vm in the correct order
  • Fixed issue with firewall notifications displaying incorrect information
  • provide notifications for expiring licenses
  • Support for Swedish input locale in the vm console
  • Display Fibre channel wwn and wwp as 64bit addresses

[sta_anchor id=”html5client” /]

 vSphere HTML5 Web Client

This is the newest release of the HTML5 Web Client for vSphere. The downloadable version is 4.0.1 while the changelog is 4.0 so we’ll have to assume that 4.0.1 is a small bug fix. Starting from this version the fling ONLY supports vSphere 6.5 and newer!

Changelog

Fling 4.0 – Build 11785236

  • New Features
    • Support for VC 6.7
    • ESX Agent Manager UI
    • MxN Convergence in System Configuration
    • Import Certificate and Generate CSR
    • Code Capture: the record button can be toggled between hidden and shown.
    • Ability to remove Script Bundles in Autodeploy for 6.7 VC
    • Ability to remove Discovered hosts in Autodeploy for 6.7 VC
    • Export licensing data in CSV for all licensing views
    • Add and Assign license with single operation
    • Authentication Proxy configuration for VC 6.5+ (VC > Configure  > Settings > Authentication Proxy)
  • Improvements
    • Improved performance for Files browser for VC 6.7
  • Bug Fixes
    • Fixed an issue where starting a Code Capture recording would lead to dialogs loading slowly or not at all.
  • Known Issues
    • To open the Fling UI, you need to use https://<Fling IP>/ui
    • The VMware vSphere Update Manager (VUM) plugin will not be loaded when the Fling 4.0 is connected to vSphere 65
  • Release Notes
    • The upgrade from Fling 3.x to Fling 4.0 will require to establish new connection to the vSphere by providing the vSphere credentials.
    • The Fling 4.0 is based on the vSphere 6.7 client and does not support vSphere versions prior to vSphere 6.5

Added Checks to the vCheck for Horizon View

Starting this year I decided to really restart working on the vCheck for Horizon. I had several requests for RDS checks & Active directory plus I really wanted to get rid of everything related to the vmware.hv.helper module to make using it a little easier.

Just like the pools I pull the farms in the connection plugin so these can be used from other plugins.

# --- Get Desktop pools
$poolqueryservice=new-object vmware.hv.queryserviceservice
$pooldefn = New-Object VMware.Hv.QueryDefinition
$pooldefn.queryentitytype='DesktopSummaryView'
$poolqueryResults = $poolqueryService.QueryService_Create($Services1, $pooldefn)
$pools = foreach ($poolresult in $poolqueryResults.results){$services1.desktop.desktop_get($poolresult.id)}

# --- Get RDS Farms

$Farmqueryservice=new-object vmware.hv.queryserviceservice
$Farmdefn = New-Object VMware.Hv.QueryDefinition
$Farmdefn.queryentitytype='FarmSummaryView'
$FarmqueryResults = $FarmqueryService.QueryService_Create($Services1, $Farmdefn)
$farms = foreach ($farmresult in $farmqueryResults.results){$services1.farm.farm_get($farmresult.id)}

# ---- Remove queries
$services1.QueryService.QueryService_DeleteAll()

The deleteall() for the queries needs to be added to clean things up, otherwise you will run out of queries pdq. The RDS plugins I created are visible down below.

Also an AD check was added

The vCenter api call was split into three checks for vCenter itself, ESXi and datastores.

Besides these I have also added a saml check (tested by Aresh Sarkari, thank you!) and truesso checks (don’t have it in my lab so can’t test).

If you want an example of the vCheck that can be found HERE.

Setting maintenance mode for Linked Clones using API’s

If you have used the VMware.hv.helper the title of this blog post might sound strange since the set-hvmachine already has a way to set maintenance mode. When Ryan Butler asked me the question this week though I didn’t think of that and dived into the api’s immediately. The machines.Machine_EnterMaintenanceMode method looked good to me and than I though of the vmware.hv.helper and noticed that with

Set-HVMachine -Maintenance ENTER_MAINTENANCE_MODE

it was also possible so set maintenance mode. The usage though made me think immediately that this was not actually using a proper api call but the update function. A quick look at the function itself confirmed this. It sets that status of the virtual machine by directly setting the status.

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
      }
    }
(this is just a snippet of the complete function)

If you are below version 7.5 of Horizon view it’s probably of no use to continue with the rest of this blog post. The api explorer only mentions the relevant functions since 7.5! They have been tried against 7.0.3 and 6.2 and there they don’t work.

So back to the drawing board it was and I needed to look at the API explorer, there are 4 relevant methods for maintenance mode.

As usual there are methods for multiple machines that use an array of id’s (with machines in the name) and methods for single machines id’s (without the machines in the name).

Since I usually use instant clones these days I created a small pool with three linked clones. With get-hvmachine I can show you their names and state.

(get-hvmachine -pool pod2_linked).base | select-object name,basicstate

Since I know that get-hvmachine will already give you the id of a machine it’s easy to do a one liner to set one system in maintenance mode.

 $services1.Machine.Machine_EnterMaintenanceMode((get-hvmachine -machinename p2lc001).id)

and exit maintenance mode.

 $services1.Machine.Machine_ExitMaintenanceMode((get-hvmachine -machinename p2lc001).id)

And the entire pool?

$services1.Machine.Machine_EnterMaintenanceModemachines((get-hvmachine -pool pod2_linked).id)

And exit maintenance mode for the entire pool.

$services1.Machine.Machine_ExitMaintenanceModemachines((get-hvmachine -pool pod2_linked).id)

Okay so we now know how this works but I don’t want to use to vmware.hv.helper module for this at all because I want to be able to use a list of machines or based on part of the name. That can be done using a query. The query entitytype to use is MachineSummaryView and if you use queryfiltercontains it’s also possible to use only a part of the name for a kind of wildcard selection. Combine several of these in with queryfilteror and it gives the opportunity to select them from a list.

$connectionserver="servername"
$hvserver1=connect-hvserver $connectionserver 
$Services1= $hvServer1.ExtensionData
$machines=get-content machines.txt
$queryService = New-Object VMware.Hv.QueryServiceService
$defn = New-Object VMware.Hv.QueryDefinition
$defn.queryentitytype='MachineSummaryView'
$filterset=@()
foreach ($machine in $machines) {
    $queryfiltercontains=New-Object VMware.Hv.QueryFiltercontains -Property @{ 'memberName' = 'base.name'; 'value' = $machine }    
    $filterset+=$queryfiltercontains
    }
$orFilter = New-Object VMware.Hv.QueryFilterOr
$orFilter.filters = $filterSet
$defn.filter=$orFilter
$ids=($queryService.QueryService_Create($Services1, $defn)).results
$services1.Machine.Machine_EnterMaintenanceModeMachines($ids.id)
p2lc001
p2lc003

Now I replaced the names in the txt file with only p2lc00

$connectionserver="servername"
$hvserver1=connect-hvserver $connectionserver 
$Services1= $hvServer1.ExtensionData
$machines=get-content machines.txt
$queryService = New-Object VMware.Hv.QueryServiceService
$defn = New-Object VMware.Hv.QueryDefinition
$defn.queryentitytype='MachineSummaryView'
$filterset=@()
foreach ($machine in $machines) {
    $queryfiltercontains=New-Object VMware.Hv.QueryFiltercontains -Property @{ 'memberName' = 'base.name'; 'value' = $machine }    
    $filterset+=$queryfiltercontains
    }
$orFilter = New-Object VMware.Hv.QueryFilterOr
$orFilter.filters = $filterSet
$defn.filter=$orFilter
$ids=($queryService.QueryService_Create($Services1, $defn)).results
$services1.Machine.Machine_ExitMaintenanceModeMachines($ids.id)

And back into maintenance mode

So this is a nice way to manage the machines and their maintenance state. Please remember that these scripts only work against horizon 7.5 and higher.

Horizon View Api’s: back to basics part 3: Methods

Like I said in part two I wanted to do that first before going to method’s since for some methods you actually need the output from a query. I posted an example of that in the meanwhile with my post about sending messages to users. The get-hvglobalsession and get-hvlocalsession are based on queries that are used for the Session_SendMessages method of the session service.

The obvious way of finding available methods is by looking into the API Explorer.

It’s a complete list but it’s hard to find all the methods that belong to a service. It’s easier to do a get-method on a service.

$services1.connectionserverhealth | gm

So, in here we have two methods: ConnectionServerHealth_Get and ConnectionServerHealth_List. Even my wide PowerShell window is not big enough to show what’s needed to with the ConnectionServerHealth_Get method. For that we can use service.method without any brackets.

$services1.ConnectionServerHealth.ConnectionServerHealth_Get

and

$services1.ConnectionServerHealth.ConnectionServerHealth_List

The required input for the method’s is visible between the brackets. The _Get method requires an id of the type vmware.hv.connectionserverid and the list doesn’t even need an input. I will keep the first one to use for later while I run the latter one.

$services1.ConnectionServerHealth.ConnectionServerHealth_List()

A lot of these lists have information that is available on a deeper level, with a get-method everything is shown.

$services1.ConnectionServerHealth.ConnectionServerHealth_List() | gm

The ones where you see a property that has a definition that starts with vmware.hv…. has more content hidden. It is possible to access these by putting the entire line between brackets followed by .membername for example

($services1.ConnectionServerHealth.ConnectionServerHealth_List()).certificatehealth

Please be aware that this can go multiple levels deep for some methods. To avoid unneeded api calls it’s wise to declare a variable from the method and use that to access the data.

$connectionserverhealth=$services1.ConnectionServerHealth.ConnectionServerHealth_List()
$connectionserverhealth.certificatehealth

Now to show the use of the _get method I could use the id that I received from the _list method but that would be cheating. What I will do is put a list of all connectionservers into an array (even though I only have 1) and do a foreach with the _get method.

$connectionservers=$services1.ConnectionServer.ConnectionServer_List()
foreach ($connectionserver in $connectionservers){$services1.ConnectionServerHealth.ConnectionServerHealth_get($connectionserver.id)}

This is the basic usage for method’s. For some method’s a spec is required for input please take a look at this post about adding an instantclone administrator for an example. I will show some more details about that one in here. Let’s take a look at what the method requires as input.

$services1.InstantCloneEngineDomainAdministrator.InstantCloneEngineDomainAdministrator_Create

You can see that a spec is required of the type VMware.Hv.InstantCloneEngineDomainAdministratorSpec. The API Explorer will show that this actually is a bit weird one since it one contains a base.

If you click on the base you’ll see whats required in there.

These levels actually show that we need to declare multiple objects to build the actual spec. You can create the basic object with new-object objecttype

$InstantCloneEngineDomainAdministratorSpec=new-object vmware.hv.InstantCloneEngineDomainAdministratorSpec
$InstantCloneEngineDomainAdministratorSpec
$InstantCloneEngineDomainAdministratorSpec.base

As you see the base is empty and doesn’t know what data it can contain. This shows that we need to declare the object for every level where we need to enter some information.

First I tried this using the class that’s shown in the API explorer, this obviously didn’t work so I use the data object name.

$InstantCloneEngineDomainAdministratorSpec.base=new-object vmware.hv.InstantCloneEngineDomainAdministratorBase
$InstantCloneEngineDomainAdministratorSpec.base

In the link I posted above you should be able to find what’s required to create an actual instantcloneadministrator. With this I have covered most of the method’s and how they work. Please don’t assume that _list nevers needs an id or that _get always needs one because that’s not true. Sometimes it will also say ids like with my previous post about sending messages that means it needs an array of id’s most possibly generated by a query or an _list method.

 

 

Sending messages to users with the Horizon API’s

I got the question today from Fabian Lenz if it is possible to send messages to end users using the Horizon API. I knew I had seen it somewhere already and here’s a quick explanation.

There are two method’s to do this, one for a single session and the other for a group of sessions. Both fall under the session service.

$services1.session | gm

You can see both the methods called session_sendmessage and session_sendmessages if we look at what’s required for both we see that the difference is a single sessionid or an array of session id’s.

Let’s see what the API explorer says what’s needed.

So the msgtype is a string that can have three values and the message is just a string, let’s test this.

I am lazy and will use get-hvlocalsession for the sessionid.

$session=get-HVlocalsession | select -first 1

I do the -first 1 so it isn’t an array but a single session.

Now let’s send a message.

 $services1.session.Session_SendMessage($session.id,"INFO","This is a test message for retouw.nl at 30-10-2018 19:13h")

And the result:

Now let’s do the same for multiple sessions.

$sessions=get-HVlocalsession
$services1.session.Session_SendMessages($sessions.id,"ERROR","This is a test message with multiple recipients for retouw.nl at 30-10-2018 19:25h")

And to show that this also works for global sessions (both where connected to pod2cbr1)

$sessions=get-HVglobalsession 
$services2.session.Session_SendMessages($globalsessions.id,"WARNING","This is a test message with multiple global recipients for retouw.nl at 30-10-2018 19:30h")

If you want to filter the sessions on user or machine name you can filter the $globalsessions on $globalsessions.namesdata.basenames

 $globalsessions.namesdata.basenames | select-object username,machineorrdsservername,clientname

With the localsessions it’s located in $sessions.namesdata

$sessions.namesdata | select-object username,machineorrdsservername,clientname

It’s also possible to filter this with the query service, take a look on my previous post on how to handle queries.

So now you know how to send messages to users. Not that they always read these messages but at least you can try warning them a bit faster now!

Horizon View Api’s: back to basics part 2: Queries

So this is the second post in this series about the Horizon View API basics. While functions logically would be part 2 I have decided on doing queries first since you might need the result for a query before you can use some of the functions. Some if it will seem double from my recent post about pulling event information but not everyone might be looking into that. This post will not have as much gifs as the first post but that’s because only the end results count for this one.

Looking at the API Explorer these are the services that we can actually query:

There are some examples in the API explorer but will show you some different examples with the aduserorgroupsummaryview since that one has a lot of documented filters and I can easily add some extra accounts to show different queries.

The first thing that we always need to do with queries is to declare the queryservice object

$queryservice=new-object vmware.hv.queryserviceservice

If you do a get-method on this object it will show several possible methods to use.

The next thing to do is to create a definition object in which we will declare the things the query looks for.

$defn = New-Object VMware.Hv.QueryDefinition

When getting this object and its get-method it shows the definitions we can set, as you can see all method’s are already visible from just viewing the object so we don’t need to use the get-method anymore.

Now we need to set a QueryEntityType these can be found in the API explorer under the Queryable Entity Types. They have to be used between quotation marks.

$defn.queryentitytype='ADUserOrGroupSummaryView'

Now we’re already set to create some results by putting the query into an object.

$queryResults = $queryService.QueryService_Create($hvServices1, $defn)

As you can see below this will create an object where the results property contains all the data. This Results property has 2 other properties of it’s own that actually contain all the data.

And if we expand the base property it gives us one of the build-in Active Directory groups.

$queryresults.results | select-object -first 1 | select -expandproperty Base

Since this can go several layers deep it is smarter to use the round brackets to get this information. (Select -expandproperty following select – expandproperty is just ugly and takes too long)

($queryresults.results | select-object -first 1).base

This way it’s also easy to count the amount of returned objects. This is very useful if you have a bigger environment and want to take counts of sessions with their status (i.e. Connected, disconnected, error etc)

($queryresults.results).count

Next up is adding a filter, so we only get user accounts but we need to do some maintenance first. If you do too many queries it is possible that you will get some errors about too many filters or something (of course I am not getting them while writing this post) so, it might be needed to remove the old stored queries is possible with the queryservice_deleteall method.

$queryservice.QueryService_DeleteAll($hvservices1)

This does not give any feedback on the results so let’s continue with the old query and put a filter on it. First you need to know what kind of filter you need and the options are listed in the API explorer.

The first one I will use is queryfilterequals since I use that the most. I start by defining a filter object consisting of a property with a value.

$filter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.group'; 'value' = $false }

Then I will add it to the querydefinition

 $defn.filter=$filter

Now I will show you the results + the fact that you don’t necessarily need to define an object for the results. I have selected the first result to show you that it contains the domain administrator account

($queryService.QueryService_Create($hvServices1, $defn)).results.base | select -first 1

It is also possible to combine several filters into one query, while the ad service might not be the most useful for this it can still be used as an example. The thing to do is to first create a couple of filters.

Please be aware that these membernames are case sensitive!

$notgroupfilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.group'; 'value' = $false }
$usernamefilter = New-Object VMware.Hv.QueryFilterEquals -Property @{ 'memberName' = 'base.loginName'; 'value' = "m_wouter" }

These need to be combined into one array

$filterarray=@()
$filterarray+=$notgroupfilter
$filterarray+=$usernamefilter

To filter on multiple things we need to have a filterand object

$filterAnd = New-Object VMware.Hv.QueryFilterAnd

And then we can add the $filterarray to this object

$filterAnd.Filters = $filterarray

and finally we put this object into the querydefinition object

$defn.Filter = $filterAnd

Now let’s run the query

($queryService.QueryService_Create($hvServices1, $defn)).results.base

That’s it for the basics of doing queries using the Horizon View API’s. There are some more things that we can do with these like sorting them, but I think you can find that on your own in the API explorer examples.

[Update 15-10] VMware PowerCLI 11.0.0 release with new Horizon (7.6!) API calls

UPDATE 12-10: The new API explorer page also has been published, it just needs to be added to the main page. Check this link: https://code.vmware.com/apis/445

Update 15-10: I have received an overview from VMware about the other changes:

New API Endpoints:
ConnectionServer_GetTags
GlobalSettings_GetEnvironmentSettings
QueryService_DeleteByIds
Datastore_GetDatastoreRequirements
Datastore_ListDatastoresByDesktopOrFarm
RemoteApplication_EndApplication

There also have been some changes to some objects (MachineBase,AccessGroup etc) to include more properties

Original Article:

Today the latest version of PowerCLI was released with version 11.0.0. When you look at the release notes it’s obvious that some extra things have been added for the Horizon VIew API’s.

PowerCLI has been moving at quite the rapid pace over the last 2 years. In 2018, we’ve been releasing roughly every other month to make sure we get the latest features, performance improvements, and updates available as quickly as possible. Well, it’s been two months and we’re not going to break this trend. Today, we are releasing PowerCLI 11.0.0!

PowerCLI 11.0.0 comes with the following updates:

  • Added a new Security module
  • Added new cmdlets for Host Profiles
  • Added a new cmdlet to interact with NSX-T in VMware Cloud on AWS
  • Support for vSphere 6.7 Update 1
  • Support for NSX-T 2.3
  • Support for Horizon View 7.6
  • Support for vCloud Director 9.5
  • Multiplatform support for the Cloud module
  • Updated the Get-ErrorReport cmdlet
  • Removed the PCloud module
  • Removed the HA module

Even though Jake Robinson already gave me a heads up that this version was coming it’s always the question what has been added for Horizon View. According to the API explorer page no new querydefinitions have been added. Like last time I decided to compare the services against the old list and there are two new additions:

  • CategoryFolder
  • ResourceSettings

I have tried both against a Horizon 7.5 setup and they failed so these are only exposed from Horizon View 7.6 and up.

The first one called Categoryfolder is linked to the possibility to put rdsh applications into folders.

It currently has only one function:

I have also investigated if there was a way to change things using the helper function but sadly it has no .update api call so that’s a no-go. I currently have no rdsh on my lab so I can do the list but it doesn’t show anything.

The other new service is the .ResourceSettings just like categoryfolder it also only has one function:

For this one I can actually show what it’s used for:

It shows the general settings for forced logoffs.

Sadly this service also doesn’t show a way to change things.

Sadly I have no found no way yet to see what queryservice entity’s have been added so hopefully we will have a new API explorer soon (maybe with release notes this time, pretty please VMware?) that shows us all the new goods.