Using PowerCLI for Advanced Syslog Configuration Tasks

PowerCLI has shiped with cmdlets for managing the Syslog configuration of ESXi hosts for some time, Get-VMHostSysLogServer and Set-VMHostSysLogServer. Unfortunately, neither of these (yet) support the configurations mentioned in the below two posts for multiple Syslog servers or different protocols, such as SSL.

http://www.boche.net/blog/index.php/2011/07/23/configure-a-vcenter-5-0-integrated-syslog-server/

http://blogs.vmware.com/vsphere/2012/04/configuring-multiple-syslog-servers-for-esxi-5.html

So for the time being I have put together two functions, Get-VMHostSyslogConfig and Set-VMHostSyslogConfig, to supplement what you can currently do with the following additional options:

  • Include the ability to set protocol specific paths, e.g. ssl://syslog01.domain.local
  • Include the ability to add multiple Syslog servers
  • Open the necessary firewall ports in ESXi 5.0 or later. If they are already open then it will skip this task. (This is possible in PowerCLI via the firewall cmdlets, but I have bundled them into this set function since I always want to combine the two things)
  • Make the configuration active straightaway via an esxcli reload task. (This doesn’t appear to happen via Set-VMHostSysLogServer)
  • Optionally just run the reload task where circumstances require a restart of the syslog service on ESXi hosts

A few examples of how they can be run:

1) Report on the configuration where multiple Syslog servers or alternative protocols have been specified:


Get-VMHost | Sort-Object Name | Get-VMHostSyslogConfig | Format-Table VMHost,SyslogServer -AutoSize

2) Set both servers “syslog01.domain.local”,“splunk.domain.local” to use SSL and port 1514


Set-VMHostSyslogConfig -SyslogServer "syslog01.domain.local","splunk.domain.local" -Protocol SSL -SyslogServerPort 1514 -VMHost ESXi01

3) Set a mixture of servers, protocols and ports. Note in this case you can’t use the Protocol or SyslogServerPort parameters because they would set all servers to use the same configuration, like Example 2, so they must each be manually specified.


Set-VMHostSyslogConfig -SyslogServer "syslog01.domain.local","ssl://splunk.domain.local:1514" -VMHost ESXi01

4) Reload the Syslog configuration on all hosts. For instance if you are running the vCenter supplied Syslog server after a vCenter reboot the hosts don’t seem to automatically start sending their logs through again. An esxcli reload kicks them back into life


Get-VMHost | Set-VMHostSyslogConfig -Reload -Verbose

One thing to watch out for when configuring the hosts is making sure that a DNS name supplied Syslog server must be resolvable by the ESXi host, not just for functionality, but even to configure it. The ESXi Advanced Setting Syslog.global.logHost appears to validate via a DNS query whether each host name is resolvable or not and will fail to configure the setting if not resolvable.

The functions are available here:


function Get-VMHostSyslogConfig { <# .SYNOPSIS Function to get the Syslog config of a VMHost. .DESCRIPTION Function to get the Syslog config of a VMHost. Added extra functionality that Get-VMHostSysLogServer is missing Get-VMHostSysLogServer does not (currently) include the ability to query an ESXi host if it is configured with multiple Syslogservers .PARAMETER VMHost VMHost to configure Syslog settings for. .INPUTS String. System.Management.Automation.PSObject. .OUTPUTS System.Management.Automation.PSObject. .EXAMPLE PS> Get-VMHostSyslogConfig -VMHost ESXi01

.EXAMPLE PS> Get-VMHost ESXi01,ESXi02 | Get-VMHostSyslogConfig #> \[CmdletBinding()\]\[OutputType('System.Management.Automation.PSObject')\]

Param (

\[parameter(Mandatory=$true,ValueFromPipeline=$true)\] \[ValidateNotNullOrEmpty()\] \[PSObject\[\]\]$VMHost )

begin {

$SyslogServerObject = @() }

process {

foreach ($ESXiHost in $VMHost){

try {

if ($ESXiHost.GetType().Name -eq "string"){

try { $ESXiHost = Get-VMHost $ESXiHost -ErrorAction Stop } catch \[Exception\]{ Write-Warning "VMHost $ESXiHost does not exist" } }

elseif ($ESXiHost -isnot \[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl\]){ Write-Warning "You did not pass a string or a VMHost object" Return }

\# --- Get Advanced Configuration value Syslog.global.logHost

$SyslogGlobalLoghost = Get-AdvancedSetting -Entity $ESXiHost -Name 'Syslog.global.logHost'

$hash = @{

VMHost = $ESXiHost SyslogServer = $SyslogGlobalLoghost.Value } $Object = New-Object PSObject -Property $hash $SyslogServerObject += $Object

} catch \[Exception\]{

throw "Unable to get Syslog config" } } } end {

Write-Output $SyslogServerObject } }

``` ```

function Set-VMHostSyslogConfig { <# .SYNOPSIS Function to set the Syslog config of a VMHost. .DESCRIPTION Function to set the Syslog config of a VMHost. Added extra functionality that Set-VMHostSysLogServer is missing Set-VMHostSysLogServer does not (currently) include the ability to set protocol specific paths, e.g. ssl://syslog01.domain.local Set-VMHostSysLogServer does not (currently) include the ability to add multiple Syslogservers Set-VMHostSysLogServer also does not open the necessary firewall ports in ESXi 5.0 or make the configuration active straightaway .PARAMETER VMHost VMHost to configure Syslog settings for. .PARAMETER SyslogServer SyslogServer to use .PARAMETER SyslogServerPort SyslogServerPort to use .PARAMETER Protocol Protocol to use for Syslog server .PARAMETER Reload Reload the config after a change or vCenter restart .INPUTS String. System.Management.Automation.PSObject. .OUTPUTS None. .EXAMPLE PS> Set-VMHostSyslogConfig -SyslogServer "syslog01.domain.local" -VMHost ESXi01

.EXAMPLE Set both servers "syslog01.domain.local","splunk.domain.local" to use SSL and port 1514

PS> Set-VMHostSyslogConfig -SyslogServer "syslog01.domain.local","splunk.domain.local" -Protocol SSL -SyslogServerPort 1514 -VMHost ESXi01

.EXAMPLE Set a mixture of servers, protocols and ports

PS> Set-VMHostSyslogConfig -SyslogServer "syslog01.domain.local","ssl://splunk.domain.local:1514" -VMHost ESXi01

.EXAMPLE PS> Get-VMHost ESXi01 | Set-VMHostSyslogConfig -SyslogServer "syslog01.domain.local" #> \[CmdletBinding(DefaultParametersetName="Configure")\]

Param (

\[parameter(Mandatory=$true,ValueFromPipeline=$true)\] \[ValidateNotNullOrEmpty()\] \[PSObject\[\]\]$VMHost,

\[parameter(Mandatory=$true,ValueFromPipeline=$false,ParameterSetName="Configure")\] \[ValidateNotNullOrEmpty()\] \[String\[\]\]$SyslogServer,

\[parameter(Mandatory=$false,ValueFromPipeline=$false,ParameterSetName="Configure")\] \[ValidateNotNullOrEmpty()\] \[int\]$SyslogServerPort,

\[parameter(Mandatory=$false,ValueFromPipeline=$false,ParameterSetName="Configure")\] \[ValidateSet("UDP","TCP","SSL")\] \[String\]$Protocol,

\[parameter(Mandatory=$false,ValueFromPipeline=$false,ParameterSetName="Reload")\] \[Switch\]$Reload )

begin {

\# --- Create the value to enter into Syslog.global.logHost $SyslogGlobalLoghostObject = @() foreach ($SyslogDestination in $SyslogServer){

$SyslogGlobalLoghost = $SyslogDestination

if ($PSBoundParameters.ContainsKey('Protocol')){

$SyslogGlobalLoghost = $Protocol.ToLower() + "://" + $SyslogGlobalLoghost }

if ($PSBoundParameters.ContainsKey('SyslogServerPort')){

$SyslogGlobalLoghost = $SyslogGlobalLoghost + ":" + $SyslogServerPort }

$SyslogGlobalLoghostObject += $SyslogGlobalLoghost }

if (($SyslogGlobalLoghostObject | Measure-Object).Count -gt 1){

$SyslogGlobalLoghostAdvancedSetting = $SyslogGlobalLoghostObject -join ", " } else {

$SyslogGlobalLoghostAdvancedSetting = $SyslogGlobalLoghostObject\[0\] } }

process {

foreach ($ESXiHost in $VMHost){

try {

if ($ESXiHost.GetType().Name -eq "string"){

try { $ESXiHost = Get-VMHost $ESXiHost -ErrorAction Stop } catch \[Exception\]{ Write-Warning "VMHost $ESXiHost does not exist" } }

elseif ($ESXiHost -isnot \[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl\]){ Write-Warning "You did not pass a string or a VMHost object" Return }

switch ($PsCmdlet.ParameterSetName) { "Configure" {

Write-Verbose "Configuring the Syslog service for $ESXiHost"

\# --- Open firewall ports for Syslog if ESXi 5 or later

if ($ESXiHost.Version -ge 5){

Write-Verbose "Opening firewall ports for Syslog on $ESXiHost" $SyslogFirewall = Get-VMHostFirewallException -VMHost $ESXiHost -Name Syslog

if (!($SyslogFirewall.Enabled)){

try {

$SyslogFirewall | Set-VMHostFirewallException -Enabled $true | Out-Null Write-Verbose "Successfully opened firewall ports for Syslog on $ESXiHost" } catch \[Exception\]{

Write-Verbose "Failed to open firewall ports for Syslog on $ESXiHost" } } else {

Write-Verbose "Firewall ports for Syslog on $ESXiHost are already open" }

} else {

Write-Verbose "ESXi version is less than 5 so no need to open firewall ports" }

\# --- Set Advanced Configuration value Syslog.global.logHost

Write-Verbose "Setting $SyslogGlobalLoghostAdvancedSetting as Syslog.global.logHost on $ESXiHost"

try {

Get-AdvancedSetting -Entity $ESXiHost -Name 'Syslog.global.logHost' | Set-AdvancedSetting -Value $SyslogGlobalLoghostAdvancedSetting -Confirm:$false | Out-Null Write-Verbose "Successfully set $SyslogGlobalLoghostAdvancedSetting as Syslog.global.logHost on $ESXiHost" } catch \[Exception\]{

Write-Verbose "Unable to set $SyslogGlobalLoghostAdvancedSetting as Syslog.global.logHost on $ESXiHost" }

\# --- Restart the Syslog service via ESXCli Write-Verbose "Restarting the Syslog service for $ESXiHost" $ESXCli = Get-EsxCli -VMHost $ESXiHost $Refresh = $ESXCli.System.Syslog.Reload()

if ($Refresh -eq "true"){

Write-Verbose "Syslog service for $ESXiHost was successfully restarted" } else {

Write-Verbose "There was an issue restarting the Syslog service for $ESXiHost" }

break }

"Reload" {

\# --- Restart the Syslog service via ESXCli Write-Verbose "Restarting the Syslog service for $ESXiHost" $ESXCli = Get-EsxCli -VMHost $ESXiHost $Refresh = $ESXCli.System.Syslog.Reload()

if ($Refresh -eq "true"){

Write-Verbose "Syslog service for $ESXiHost was successfully restarted" } else {

Write-Verbose "There was an issue restarting the Syslog service for $ESXiHost" }

break } } } catch \[Exception\]{

throw "Unable to set Syslog config" } } } end {

} }