Virtual Machine logging
I recently received an interesting question in my mailbox. Someone wanted to know if it was possible to enable/disable the logging for a Virtual Machine through PowerCLI. These Virtual Machine logs can be a handy resource when analysing problems.
This logging option is available through the vSphere client when you select Edit Settings and then Options-Advanced-General. In that form there is a checkbox that allows you to enable/disable the virtual machine logging.
Afaik, this feature is not yet available through a PowerCLI cmdlet. But it is easily accessible through the VirtualMachine object.
Enable/disable logging
#requires -version 2
#requires -pssnapin VMware.VimAutomation.Core -version 4.1
function Set-VMLogging{
<#
.SYNOPSIS
Activate or deactivate logging on a virtual machine
.DESCRIPTION
The function activates or deactivates logging on a
virtual machine. The function allows toggling of
the current setting through the
.NOTES
Author: Luc Dekens
.PARAMETER VM
The virtual machine
.PARAMETER Logging
A switch that indicates if logging should be activated or
deactivated
.PARAMETER Toggle
A switch that indicates if the current logging setting should
be toggled
.EXAMPLE
PS> Set-VMLogging -VM $vm -Logging:$true
.EXAMPLE
PS> Get-VM | Set-VMLogging -Logging:$false
.EXAMPLE
PS> Set-VMLogging -VM $vm -Toggle:$true
#>
[CmdletBinding(DefaultParametersetName="OnOff")]
param(
[parameter(Mandatory=$true,ValueFromPipeline=$true)]
[PSObject[]]$VM,
[Parameter(ParameterSetName="OnOff")]
[switch]$Logging,
[Parameter(ParameterSetName="Toggle")]
[switch]$Toggle
)
begin{
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.Flags = New-Object VMware.Vim.VirtualMachineFlagInfo
if($psCmdlet.ParameterSetName -eq "OnOff"){
$spec.Flags.enableLogging = $Logging
}
}
process{
foreach($obj in $VM){
if($obj.GetType().Name -eq "string"){
$obj = Get-VM -Name $obj
}
if($psCmdlet.ParameterSetName -eq "OnOff"){
$obj | where {$_.Extensiondata.Config.Flags.enableLogging -eq (!$Logging)} | %{
$_.Extensiondata.ReconfigVM($spec)
}
}
else{
$spec.Flags.enableLogging = !$VM.Extensiondata.Config.Flags.enableLogging
$obj.Extensiondata.ReconfigVM($spec)
}
}
}
}
Annotations
Line 34-37: To avoid that the Logging and Toggle switch be used together, I placed both of them in different parameter sets.
Line 41-45: The VirtualMachineConfigSpec object that we need to change the logging setting is constant for all calls. Except if the function is called with the Toggle parameter.
Line 33,49: The function defines the VM parameter as an array, that way the script can use a foreach loop. Even if the function is called with only 1 virtual machine, the $VM variable will still be an array, albeit with only 1 element.
Line 50-52: An simple emulation of the OBN (Object By Name) feature that the PowerCLI cmdlets offer. The virtual machines can be passed as string or as an object returned by the Get-VM cmdlet.
Line 53-61: The actual change of the logging flag is done with the ReconfigVM_Task. The function handles the Logging and the Toggle switch with the if-then-else construct.
While I was writing the above function I realised that it would also be handy to have a function to retreive these logs. With the help of the Copy-DatastoreItem it turns out that this is also a trivial task.
Retrieve the logs
#requires -version 2
#requires -pssnapin VMware.VimAutomation.Core -version 4.1
function Get-VMLog{
<#
.SYNOPSIS
Retrieve the virtual machine logs
.DESCRIPTION
The function retrieves the logs from one or more
virtual machines and stores them in a local folder
.NOTES
Author: Luc Dekens
.PARAMETER VM
The virtual machine(s) for which you want to retrieve
the logs.
.PARAMETER Path
The folderpath where the virtual machines logs will be
stored. The function creates a folder with the name of the
virtual machine in the specified path.
.EXAMPLE
PS> Get-VMLog -VM $vm -Path "C:\VMLogs"
.EXAMPLE
PS> Get-VM | Get-VMLog -Path "C:\VMLogs"
#>
param(
[parameter(Mandatory=$true,ValueFromPipeline=$true)]
[PSObject[]]$VM,
[parameter(Mandatory=$true)]
[string]$Path
)
process{
foreach($obj in $VM){
if($obj.GetType().Name -eq "string"){
$obj = Get-VM -Name $obj
}
}
$logPath = $obj.Extensiondata.Config.Files.LogDirectory
$dsName = $logPath.Split(']')[0].Trim('[')
$vmPath = $logPath.Split(']')[1].Trim(' ')
$ds = Get-Datastore -Name $dsName
$drvName = "MyDS" + (Get-Random)
New-PSDrive -Location $ds -Name $drvName -PSProvider VimDatastore -Root '\' | Out-Null
Copy-DatastoreItem -Item ($drvName + ":" + $vmPath + "*.log") -Destination ($Path + "\" + $obj.Name + "\") -Force:$true
Remove-PSDrive -Name $drvName -Confirm:$false
}
}
Annotations
Line 35-37: An simple emulation of the OBN (Object By Name) feature that the PowerCLI cmdlets offer. The virtual machines can be passed as string or as an object returned by the Get-VM cmdlet.
Line 43: The function creates a PSDrive to map the datastore where the virtual machine logs are located. To avoid/minimise collisions with existing PSDrives, the script adds a random number to the name.
Line 45: The actual copy of the log files is done with the Copy-DatastoreItem cmdlet. Note that the function always uses the Force parameter, this means that any existing files will be overwritten.
Sample runs
To activate logging for a virtual machine, you can call the function like this
Set-VMLogging -VM MyVM -Logging:$true
To deactivate logging for a series of virtual machines, you can do something like this
$vm = Get-VM -Name MyVM Set-VMLogging -VM $vm -Logging:$false
The function also provides a ‘toggle’ switch. This parameter will change the actual setting for logging.
Get-VM My* | Set-VMLogging -Toggle
To retrieve the logs for a virtual machine, you do
Get-VMLog -VM MyVM -Path "C:\VMLogs"

Note that the script assumes that the folder VMLogs already exists.
And you can do this for a number of virtual machines as well
Get-VM PC* | Get-VMLog -Path "C:\VMLogs"
You will find the virtual machine logs in the subfolders under C:\VMLogs



I seem to not be able to get this script working with cli v5 and vsphere 4.1. Has something changed in 5? There is no error generated, just nothing happens.
@David, both scripts have a line at the top that says
#requires -pssnapin VMware.VimAutomation.Core -version 4.1
Try removing that line.
The requirement will fail since you are using PowerCLI 5.