Category Archives: PowerCLI - Page 2

PowerCLI A Syslog Server To All ESXi Hosts In vCenter

I was recently tasked with configuring all ESXi hosts within a number of vCenter environments to use a Syslog Server.  Each of these environments contained numerous clusters and ESXi hosts.  Too many to manually want to configure a Syslog Server by hand.  Using our lab environment I played around with a few different ways of quickly pushing out some Syslog settings via PowerCLI.

I came across two different PowerCLI cmdlets that would do the job.  The  first was Set-AdvancedSetting and the second was Set-VMHostAdvancedConfiguration.  The latter being a deprecated cmdlet.  Both cmlets do the job equally well.  Ideally you would want to be using the newer Set-AdvancedSetting cmdlet rather than the deprecate one.

Where I didn’t like the newer Set-AdvancedSetting was that it would ask for confirmation before making a change.   I didn’t fully realise how annoying this would be till after I had wrote my script.   Once a connection to a vCenter is made in PowerCLI the script I created prompts for a Syslog Server then gets all ESXi hosts in the vCenter, applies the Syslog Server value, reloads syslog, and finally opens the syslog ports.  All simple and basic except that you will be prompted to apply the syslog value to each host.  Fine if you’re very cautious or if you want to omit specific hosts.

Perform operation?
Modifying advanced setting ‘Syslog.global.logHost’.
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is “Y”):y

I then decided to test out Set-VMHostAdvancedConfiguration and found I preferred this cmdlet over Set-AdvancedSetting.  Each time it set a syslog value on a host it would flash up a friendly yellow little warning and go ahead with the change.  Much more convenient for large changes.  At some point in a future PowerCLI version I assume this cmdlet won’t work but until then it works a treat.

WARNING: Set-VMHostAdvancedConfiguration cmdlet is deprecated. Use
Set-AdvancedSetting cmdlet instead.

The below code block uses the newer Set-AdvancedSetting cmdlet.

# This script will set a Syslog Server all all ESXi hosts within a vCenter once connected.
# Uses the newer Get / Set-AdvancedSetting cmdlet.
# This cmdlet will require confirmation for each host being modified.
# Created by Mark Ukotic
# 04/04/2015

Write-Host "This script will change the Syslog Server on all hosts within a vCenter, restart Syslog, and open any required ports."

Write-Host

$mySyslog = Read-Host "Enter new Syslog Server. e.g. udp://10.0.0.1:514"

Write-Host

foreach ($myHost in get-VMHost)
{
#Display the ESXi Host being modified
Write-Host '$myHost = ' $myHost

#Set the Syslog Server
$myHost | Get-AdvancedSetting -Name Syslog.global.logHost | Set-AdvancedSetting -Value $mySyslog

#Restart the syslog service
$esxcli = Get-EsxCli -VMHost $myHost
$esxcli.system.syslog.reload()

#Open firewall ports
Get-VMHostFirewallException -Name "syslog" -VMHost $myHost | set-VMHostFirewallException -Enabled:$true
}

This second code block uses the deprecated Set-VMHostAdvancedConfiguration, which I prefer.

# This script will set a Syslog Server all all ESXi hosts within a vCenter once connected.
# The deprecated Set-VMHostAdvancedConfiguration cmdlet is used.
# Seems to run a little more cleaner with this cmdlet and doesn't ask for confirmation
# Created by Mark Ukotic
# 04/04/2015

Write-Host "This script will change the Syslog Server on all hosts within a vCenter, restart Syslog, and open any required ports."

Write-Host

$mySyslog = Read-Host "Enter new Syslog Server. e.g. udp://10.0.0.1:514"

Write-Host

foreach ($myHost in get-VMHost)
{
#Display the ESXi Host being modified
Write-Host '$myHost = ' $myHost

#Set the Syslog Server
Set-VMHostAdvancedConfiguration -Name Syslog.global.logHost -Value $mySyslog -VMHost $myHost

#Restart the syslog service
$esxcli = Get-EsxCli -VMHost $myHost
$esxcli.system.syslog.reload()

#Open firewall ports
Get-VMHostFirewallException -Name "syslog" -VMHost $myHost | set-VMHostFirewallException -Enabled:$true
}

Modifying Services via PowerCLI

If your vSphere environment is anything like the ones I manage over time you can be left with various ESXi hosts with Services left Running when they should be Stopped. It’s so common to turn on SSH or the ESXi Shell to troubleshoot an issue and then forget to Stop the service when you’re done.

If you’re managing 10s, if not, 100s of ESXi hosts you don’t want to be clicking on each host and checking the Security Profile setting.

This can be checked really easily and modified via PowerCLI. Below I slowly build a basic script that will check and modify a service of all hosts connected to a vCenter.

Open PowerCLI and make a connection to vCenter.

Connect-VIServer myvcenter.domain.local

Once connected we can run the following cmdlet to list all hosts in vCenter.

Get-VMHost

Next we can narrow it down by selecting an individual host then displaying all Services on that host to help identify the Service we want to modify.

Get-VMHost –Name esxi01.domain.local | Get-VMHostService

powercli_service01

This will display all services on the host, their policy state, and whether they are running.

Now we can take it one step further and enumerate all hosts looking for a specific service using its service name from the Key column above. In this case I want to list the settings for the ESXi Shell, which is defined by the Key value “TSM”

Get-VMHost | Get-VMHostService | Where {$_.Key –eq “TSM”}

powercli_service02

Next I want to now change the policy from On to Off for all hosts which we would do as follows.

Get-VMHost | Get-VMHostService | Where {$_.Key –eq “TSM-SSH”} | Set-VMHostService –Policy “On”

Finally, I want to also change the ESXi Shell on all hosts from Running to Stopped.

Get-VMHost | Get-VMHostService | Where {$_.Key –eq “TSM-SSH”} | Stop-VMHostService

powercli_service03

This will display a prompt asking you to acknowledge the operation on each or all hosts.

The scripts above are very crude but get the job done very quickly. They can obviously be narrowed down and enumerated much better. For example Get-Cluster can be used in front of Get-VMHost to target a specific cluster. Also the host’s name can be enumerated to better see which hosts you’re modifying on an individual basis. Call that your study lesson 😉

Using PowerCLI to speed up Question time

It seems like all my posts start of the same way, “I recently had an issue…”, but it’s true 🙂   I recently had an issue with snapshots consuming all of the space in a datastore.  The culprit was CommVault preforming end of month full backups of VMs.  During the backup process it takes a snapshot of the VM prior to that full VMDK backup.

It was first identified with a VM having a pending question in the vCenter Client.

get-vmquestion01

It was also quickly identified as having a snapshot by the xxx-000001.vmdk virtual disk name.  A check of the working snapshots of the VM showed that it was created by CommVault.  A check of the VMs datastores the VM used showed that one of them was full.  It was also a good bet that any other VMs on this datastore with snapshots or thin provisioned disks would be having issues too.

The snapshots couldn’t be deleted as there was no free space on the datastore to commit the transactions from the snapshot VMDK.  I could have grown the size of the datastore but that would have involved Change Requests with changes at the SAN and vSphere level.  Without panicking too much I identified a rather small working VM and migrated it’s storage to another datastore.  The goal here is to free up space on the datastore in preperation to answer the pending questions and get the VM running ASAP.

While the VM was being migrated to a different datastore it gave me a few minutes to identify which VMs had a pending question and would have been in a paused state.  Now there’s probably 17 different ways to approach this but I just went with a direct method.

Using PowerCLI and connecting up the vCenter Server.  I then ran Get-VMQuestion.

Connect-VIServer my_vcenter_server.domain.local

Get-VMQuestion

This will by default return all VMs in the vCenter instance that have pending questions.  If you have a large vCenter with 1000+ VMs this will most likely take a while and you might want to target the command to specific datastores or ESXi servers.  In my situation I wanted to make sure I identified all pending questions and didn’t miss anything.

get-vmquestion02

By this point my VM migration just completed so I could now answer all the pending questions and resume the VMs in the paused state.  This can be done by using the Set-VMQuestion.

Get-VMQuestion | Set-VMQuestion –Option “Retry” -Confirm:$false

It doesn’t really get simpler then the above command.  Identify pending questions with Get-VMQuestion.  Pipe it to Set-VMQuestion, answer all with ‘Retry’, and use the parameter ‘Confirm’ so not to get prompted to confirm action.  Again probably smarter ways to go about this.  You could use the Get-Datastore cmdlet to identify datastores with zero free space.  Then target those datastores with Get-VMQuestion.

Get-Datastore my_datastore | Get-VM | Get-VMQuestion

The Get-VMQuestion / Set-VMQuestion is a great PowerCLI way of working smarter not harder.  Whether answering 1 or 100 questions it’s all the same via PowerCLI.  I don’t really know if there’s an easy way to identify and answer pending questions through the vCenter Web or C# client???

On a side note.  Set-VMQuestion isn’t overly intuitive as a cmdlet name for answering a question.  So there is an alias to it called Answer-VMQuestion.  I guess it sticks with PowerShell tradition with the Get / Set verbs.