Resetting VMware’s Changed Block Tracking (CBT) File with PowerCLI

Changed Block Tracking (CBT) is a handy feature in which the hypervisor is tasked with keeping track of all changed data blocks for each virtual disk attached to a virtual machine. When it’s enabled, the idea is that software leveraging the vSphere APIs for Data Protection (VADP) can reduce the amount of data ingested by only requesting the changed blocks. Every software solution handles the actual data ingest process a little differently, but the overarching principle remains the same.

VMware KB 2136854, entitled Backing up a Changed Block Tracking enabled virtual machine in ESXi 6.0.x returns incorrect changed sectors, showcases an issue in which the CBT file may contain erroneous data in some situations. With data protection, any chance of corruption should be treated seriously and all data should be handled as suspect. As such, it’s important that those affected apply the patch ESXi600-201511401-BG. I’ve done so using the VMware vSphere Update Manager (VUM) for my various lab environments.

I take no responsibility if this happens to you.
I take no responsibility if this happens to you.

Once that’s done, it’s also a good idea to purge the CBT file for any running (powered on) virtual machines. I went looking for a programmatic method for doing this on the web, and only found some rather hackish-looking scripts and blog posts with snipets of code. I wanted something a bit more robust and formatted as a proper cmdlet with an embedded function, so I’ve written my own and published it on the Wahl Network PowerShell Scripts GitHub repository under the Apache 2.0 open source license. Meaning – use it at your own risk without any other permission from me. I’ve run the cmdlet against all of my virtual machines in the home lab and at my work lab, which are both running vSphere 6.

Download Reset-CBT.ps1

The cmdlet is fairly simple. For each VM specified, it will do the following:

  1. Sets the CBT option to False, thus disabling CBT for that VM.
  2. Checks to see if the VM has previous snapshots (you’ll need to consolidate them) or is powered off (no need to flush the CBT file).
  3. If Step 2 looks good, creates and deletes a snapshot to flush the CBT file. This avoids the need to power off your virtual machines.
  4. Reports any skipped VMs from Step 2 at the end for further remediation.

If you notice any issues, feel free to drop a comment or submit a pull request. Enjoy!

Deeper Dive into the Code

I’ve included a handful of examples with the cmdlet. You can view these with the following command:

Get-Help Reset-CBT -Examples

Example 1

Reset-CBT -VM 'WAHLNETWORK' -vCenter VCENTER.DOMAIN.LOCAL

Disables CBT for a VM named WAHLNETWORK, then creates and consolidates (remove) a snapshot to flush the CBT file. The assumption here is that your backup software will then re-enable CBT during the next backup job.

Example 2

Reset-CBT -VM 'WAHLNETWORK' -vCenter VCENTER.DOMAIN.LOCAL -NoSnapshots

Disables CBT for a VM named WAHLNETWORK but will not use a snapshot to flush the CBT file. This is useful for environments where you simply want to disable CBT and do not have backup software that will go back and re-enable CBT.

Example 3

Reset-CBT -VM $VMlist -vCenter VCENTER.DOMAIN.LOCAL

Disables CBT for all VMs in the list $VMlist, which can be useful for more targeted lists of virtual machines that don’t easily match a regular expression.┬áHere are some methods to build $VMlist:

$VMlist = Get-VM -Location (Get-Folder 'Test Servers')
$VMlist = Get-VM -Location (Get-DataCenter 'Austin')

Example 4

Get-VM -Location (Get-Folder 'Test Servers') | Reset-CBT -vCenter VCENTER.DOMAIN.LOCAL

Similar to the previous example, except that it uses a pipeline for the list of virtual machines.

Example 5

Reset-CBT -VM 'WAHLNETWORK' -vCenter VCENTER.DOMAIN.LOCAL -EnableCBT

Enables CBT for a VM named WAHLNETWORK. No other activities are performed. This is useful for when you want to enable CBT for one or more virtual machines.