Pulling Horizon View events with PowerCLI in a nicer way

Update: There is a new way to pull the event information without having to enter the sql password please see this post about it.

 

So in one of the first posts I did about Powercli 6.5 was a bit about pulling events from the Horizon View events database. This off course was not the crude way to pull the events. Another was was using the event dumper fling but that one is a bit to slow for my taste. I decided to create a script that leveraged and had the speed of PowerCli but actually gave some options and that dumped the results in a .csv file since reading them from the command line will be too much at some point.

What I ended up with is a 71 line script where 18 are informational, 8 blanks, 1 that pulls the information and the rest for the menus and error handling. I decided on not giving any real errors when things don’t work but just red text. A lot is done with try <> catch and a if elseif else.

There is no need to load any modules but the scripts assumes at least PowerCLI 6.5 with the vmware.hv.helper module loaded.

I have created a github repo for these smaller scripts over here.

#-------------------------------------------------
# Get the Horizon view event for the last x time and export to a csv
#
# Requires PowerCLI 6.5 or higher
# Requires vmware.hv.helper module
# Module can be found at https://github.com/vmware/PowerCLI-Example-Scripts
#
# Version 1.0
# 16-06-2017
# Created by: Wouter Kursten
#
#-------------------------------------------------

# Load the required VMware modules (for PowerShell only)

Write-Host "Loading VMware PowerCLI Modules" -ForegroundColor Green
try	{
	get-module -listavailable vm* | import-module -erroraction stop
	}
catch	{
	write-host "No Powercli 6.5 or higher found" -ForegroundColor Red
		}
$version=get-powercliversion -WarningAction silentlyContinue
if ($version.build -lt 4624819)	{
	write-host "Horizon View api's require Powercli 6.5 or higher to function, please upgrade PowerCLI" -ForegroundColor Red
	exit
	}
elseif (get-module vmware.hv.helper  ) {
	write-host "VMware.hv.helper found"
	}
else {
	write-host "Please download and install the VMware.hv.helper module from https://github.com/vmware/PowerCLI-Example-Scripts" -ForegroundColor Red
	exit
	}

#Ask for connection information

$hvservername=Read-host "Welke Connection broker?"
$domain=read-host "Please enter your active directory domain?"
$username=Read-host "Please enter your useraccount"
$password=Read-host -assecurestring "Please enter your password"

#Connect to View Connection broker
write-host "Connecting to the connection broker" -ForegroundColor Green
try {
$hvserver=connect-hvserver $hvservername -domain $domain -username $username -password $password -WarningAction silentlyContinue -erroraction stop
}
catch {
	Write-host "Can't connect to the Connection server please check the credentials." -ForegroundColor Red
	exit
	}

#connect to the Event Database

$dbpassword=Read-host -assecurestring "Please enter the password of the account configured in Horizon View to access the event database."
write-host "Connecting to the database" -ForegroundColor Green
try {
	$eventdb=connect-hvevent -dbpassword $dbpassword -erroraction stop
	}
catch {
	Write-host "Can't connect to the Database server please check the password." -ForegroundColor Red
	exit
	}

#Retreive information

write-host "Please provide the following information use % as wildcard." -ForegroundColor Green
$searchuser=Read-Host "Please enter the accountname you need information on?"
$module=Read-Host "What module do you want the logs for? (Agent,Broker,Client,Tunnel,Framework,Client)"
$sevfilter=Read-Host "What is the severity level you need information on?(Audit_fail, Audit_Success,Info,Warning,Error)"
$message=Read-host "Looking for any specific text in the message?"
$maxage=Read-Host "How far do you want to look back in event history? (Day,week,month,all)"
$filelocation=Read-host "Please provide filename and location for the exported csv file"

#Export to file

$lastevent=get-hvevent -hvdbserver $eventdb -timeperiod $maxage -SeverityFilter $sevfilter -userfilter $searchuser -modulefilter $module -messagefilter $message

try {
	$lastevent.events  | export-csv $filelocation -erroraction stop
	}
catch{
	write-host "Unable to create the file, please check name and location" -ForegroundColor Red
	exit
	}
Write-host "Events have been successfully exported." -ForegroundColor Green

And how does this look in the end??

Updated flings for Horizon View

The last couple of weeks some of the flings applicable for Horizon View and that I had in my VMUG presentation have been updated. The Horizon Toolbox 2 has been updated so it now supports console access for vCenter 6.0u2 and 6.5 + it now supports horizon 7.1. The Horizon OS Optimization Tool got several bugfixes.

Recent change for the Horizon Toolbox 2:

2017-Mar-17 Horizon Toolbox 2.1.3

New Features

  • Support new Horizon version(7.1)
  • Support new VCenter version(VC6.5 and 6.0u2a) in Console Access feature

 

Recent changelog for the OSOT:

April 27, 2017 b1090b

  • Issue Fix: “the node to be removed is not a child of this node” when opitimize windows 10 template
  • Issue Fix: System.NullReferenceException occurs if the network can’t reach any of the public template repository.
  • Template Update (Windows 7/8/8.1): Correct the Menu Show Delay type to REG_SZ in item “Reduce Menu Show Delay”

April 18, 2017

Issue fixed

    • Some optimization items are skipped mistakenly. For example, Remote Apps in Windows 10 template. This is caused by a recent change in Conditional Check feature.

April 17, 2017 b1088

Feature

      • Conditional Check: you can specify on what condition an optimization should be run. For example, when a specific registry key match certain value.

Template

      • “Change Explorer Default View” has been changed to unselected by default, because of conflict to UEM. Details: it causes the locations in “user files” (desktop, downloads, favorites, music, videos , Documents, Pictures) folder is to the local drive c:\Users\Username, its Should be \\server\folder_redirection\%username% when use UEM folder redirection.

Enhancements

      • Public Templates tab: click template on the list is very slow, which should not be
      • Default public template repository URL updated
      • Loading public template repository takes too long

Issue Fix

    • Field validation: prevent user from creating template with blank name

Using PowerCLI to get Horizon view status & events

Update: There is a new way to pull the event information without having to enter the sql password please see this post about it.

So two weeks ago I had a nice little post about talking to Horizon View using PowerCLI. I also promised to be digging a bit more into PowerCLI by grabbing the script posted on the VMware blog and editing it a little to my taste. It’s a very useful script they have on there but still I prefer to know what might have caused the issues. I decided I needed to know who the last user was that used the desktop and the last entry into the eventlog and the time of that log. So actually most code used talks to the eventlog database, something already available pre PowerCLI 6.5 but what I hardly ever used.

The basics for connecting I won’t post but we do need an extra connection and that is to the event database:

$eventdb=connect-hvevent -dbpassword $hvedbpassword

As with the Horizon View connection it’s best to put this into a variable so it can be used later on. The $hvedbpassword should be the password for the user that View uses to connect to the database server in plain text! Earlier in the script I read the password from hashed contents in a text file.The request has been dropped to be able to pass encrypted credentials and/or creta a credentialstore for this.

Next up is grabbing the events for a certain Desktop

$lastevent=get-hvevent -hvdbserver $eventdb -timeperiod 'day' -messagefilter $problemvm.base.name

This could use some rework since I would prefer the time period to be a variable based on the current date but if the event is older then a day it will be hard to find anything on it anyway.

if ($lastevent.events){
$lasteventtime=$lastevent.events | select -expandproperty eventtime -first 1
$lasteventmessage=$lastevent.events | select -expandproperty message -first 1 
$lasteventusername=$lastevent.events | select -expandproperty Username -first 1 
}

This grabs the latest event, the time it happened and the user it happened to. This can be anything including a logoff. It might be able to help you why a lot of desktops are ending up in a rotten state.

The rest of the script is basic building of arrays, filling them, mailing it etc etc. So still not a lot of complicated code that some people build but it’s a bit of the basics in talking to the View Api and the event database.

This is the output you will get (this is from an html file and heavily edited to anonimize it)

The complete script, please do use and abuse it to your own taste as I have done with the original:

#########################################################################################
#																						#
# Get List of Desktops that are not available or connected		 						#
# This is based on the script posted here:												#
# https://blogs.vmware.com/euc/2017/01/vmware-horizon-7-powercli-6-5.html				#
# Required:																				#
# Powercli 6.5 Release 1																#
# The VMware.Hv.Helper Module from https://github.com/vmware/PowerCLI-Example-Scripts	#
#																						#
#########################################################################################

#region variables
#########################################################################################
#								Variables												#
#	Password files need to be filled firs using:										#
#	Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File 'filename.txt'		#
#	Enter password and press enter														#
#	vCenter things have been marked out but I left them in here 						#
#	because they might be usefull for when someone else uses this script				#
#########################################################################################
$cs = "connectionbroker"														# Horizon Connection Server
$hvcsUser= "Service_Account"													# User account to connect to Connection Server
$hvcsPassword = get-content .\hvcs_Credentials.txt | convertto-securestring		# Password for user to connect to Connection Server
$csDomain = "domain"															# Domain for user to connect to Connection Server
$hvedbpassword=get-content .\hvedb_Credentials.txt | convertto-securestring   	# password to access event database
$mailto="user@domain.com"														# Address to send the status mail to
$mailfrom="connectionbroker@domain.com"											# Address to send the mail from
$mailsubject="Overview bad VDI desktops"										# Mail subject
$smtpserver="mailserver.domain.com"												# Mail server			
#$vcuser="vcuser"																# User account to access the vCenter server
#$vcpassword=get-content .\vCenter_Credentials.txt | convertto-securestring		# password to access the vCenter server
#vc = "Enter vCenter name"														# vCenter Server



$baseStates = @('PROVISIONING_ERROR',
                'ERROR',
                'MAINTENANCE',
                'DISCONNECTED',
                'AGENT_UNREACHABLE',
                'AGENT_ERR_STARTUP_IN_PROGRESS',
                'AGENT_ERR_DISABLED',
                'AGENT_ERR_INVALID_IP',
                'AGENT_ERR_NEED_REBOOT',
                'AGENT_ERR_PROTOCOL_FAILURE',
                'AGENT_ERR_DOMAIN_FAILURE',
                'AGENT_CONFIG_ERROR',
                'UNKNOWN')
				

#endregion variables

#region initialize
###################################################################
#                    Initialize                                  #
###################################################################
# --- Import the PowerCLI Modules required ---
Import-Module VMware.VimAutomation.HorizonView
Import-Module VMware.VimAutomation.Core

# --- Connect to Horizon Connection Server API Service ---
$hvServer1 = Connect-HVServer -Server $cs -User $hvcsUser -Password $hvcsPassword -Domain $csDomain

# --- Get Services for interacting with the View API Service ---
$Services1= $hvServer1.ExtensionData

# --- Connect to the vCenter Server ---
#Connect-VIServer -Server $vc -User $vcUser -Password $vcPassword

# --- Connect to the view events database ---
$eventdb=connect-hvevent -dbpassword $hvedbpassword

#endregion initialize

#region html
###################################################################
#                    HTML                                         #
###################################################################

$style = "<style>BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + "</style>"

#endregion

#region main
###################################################################
#                    Main                                        #
###################################################################
$Problemarray=@()
#Write-Output ""
if ($Services1) 
	{
     foreach ($baseState in $baseStates) 
		{
           # --- Get a list of VMs in this state ---
           $ProblemVMs = Get-HVMachineSummary -State $baseState

           foreach ($ProblemVM in $ProblemVMs) 
		   {
		   			$lastevent=get-hvevent -hvdbserver $eventdb -timeperiod 'day' -messagefilter $problemvm.base.name
			
				if ($lastevent.events){
					$lasteventtime=$lastevent.events | select -expandproperty eventtime -first 1
					$lasteventmessage=$lastevent.events | select -expandproperty message -first 1 
					$lasteventusername=$lastevent.events | select -expandproperty Username -first 1 
					}
				else{
				$lasteventtime="Last event is longer then 1 day ago"
				$lasteventmessage="Not Available"
				}
			$lastmaintenancedate=(Get-HVMachine -machinename $problemvm.base.name)
		   	$item = New-Object PSObject
			$item | Add-Member -type NoteProperty -Name Name -Value $problemvm.base.name 
			$item | Add-Member -type NoteProperty -Name State -Value $problemvm.base.basicstate 
			$item | Add-Member -type NoteProperty -Name Pool -Value $problemvm.namesdata.desktopname
			$item | Add-Member -type NoteProperty -Name Last_event_time -Value $lasteventtime
			$item | Add-Member -type NoteProperty -Name Last_event_user -Value $lasteventusername
			$item | Add-Member -type NoteProperty -Name Last_event_message -Value $lasteventmessage
			$Problemarray+= $item
           }
		}
	
		if ($problemarray)	
			{
			$mailbody=$Problemarray | sort state,name | convertto-html -head $style -property  name,state,Pool,Last_event_time,Last_event_user,Last_event_message | out-string
			send-mailmessage -smtpserver $smtpserver -to $mailto -from $mailfrom -subject $mailsubject -body $mailbody -bodyashtml 
			}
		else
			{
			send-mailmessage -smtpserver $smtpserver -to $mailto -from $mailfrom -subject $mailsubject -body "No problems found in the Horizon View Environment" 
			}

     Write-Output "Disconnect from Connection Server."
     Disconnect-HVServer -Server $cs -confirm:$false
		} 

else 
	{
     Write-Output "Failed to login in to Connection Server."
     
     }
# --- Disconnect from the vCenter Server ---
#Write-Output "Disconnect from vCenter Server."
#Disconnect-VIServer -Server $vc
#endregion main

 

 

Talking PowerCLI against Horizon view (basics)

You know that VMware product that really lacked on the PowerCLI front called Horizon View? Well from PowerCLI 6.5 R1 it finally (try to imagine saying this like The Rock : Finally Powercli has come to Horizon View!) has its own module that you can use to talk to Horizon View and the View API’s.

Offcourse i am not the first to write about it and lots can already be found at the above link to the VMware blog by Graeme Gordon but I did want to share a couple of easy commands with you. I will not bore you with how to set it up because that’s already perfectly explained in Graeme’s post.

First we need to connect, looks like the connect-viserver right?:

connect-hvserver SERVERNAME

you will get a popup box for credentials, I haven’t found an option yet to do something like new-vicredentialstoreitem yet but you can use a hashed password in a text file.

Now for example to retrieve all disconnected desktops

Get-HVMachineSummary -State DISCONNECTED

This can be changed to whatever states are available for desktops.

One of the things Horizon View always lacked was proper reporting for desktop counts i.e. how many desktops are in what state. Lots of people had to use things like scripts that counted them from the adam database (sloooooow) or used tools like the VMware Horizon toolbox 2. To get a count is now really easy with powercli, just repeat the above command and do a count on it.

(Get-HVMachineSummary -State DISCONNECTED).count

For me this was a matter of a second with over 900 desktops available.

Want some information about a single desktop?

get-hvmachinesummary -machinename "machinename" | fl

In short you can find anything you want with the command or by using the View API’s. Since I am not an APi expert myself I would recommend heading over to the API browser and see what you want to use.  In my next post I will dig into the command a bit more by grabbing the script from the VMware blog post and editing it more to my taste.

Can you smellllllll what The Rock is cooking?

New VMware fling: View Client Resizer

I must have missed i during the holiday season but VMware has released a new fling: the View Client Resizer. It’s a simple fling that let’s you easily select any resolution you want to check your VMware Horizon View environment on to see how it behaves. The steps below I have done on a 2-screen setup.

  1. First you go to https://labs.vmware.com/flings/view-client-resizer and download the zip file
  2. Next unpack the zip file
  3. Start the executable
  4. Start the Horizon View client and open a VDI session
  5. Push refresh in the tool and it wil show the active sessions in the pulldown menu
  6.  
  7. Click resize and the session wil go to the top left corner of the Primary monitor in that resolution.

You can pick any of the default resolutions or make one up (smartphone resolutions for example ) as long as the x is between the digits with a minimum right now it seems of 800*600