Tag Archives: PowerCLI

veducate header

Safely Clean Up Orphaned First Class Disks (FCDs) in VMware vSphere with PowerCLI

vSphere Orphaned First Class Disk (FCD) Cleanup Script

Orphaned First Class Disks (FCDs) in VMware vSphere environments are a surprisingly common and frustrating issue. These are virtual disks that exist on datastores but are no longer associated with any virtual machine or Kubernetes persistent volume (via CNS). They typically occur due to:

  • Unexpected VM deletions without proper disk clean-up
  • Kubernetes CSI driver misfires, especially during crash loops or failed PVC deletes
  • vCenter restarts or failovers during CNS volume provisioning or deletion
  • Manual admin operations gone slightly sideways!

Left unchecked, orphaned FCDs can consume significant storage space, cause inventory clutter, and confuse both admins and automation pipelines that expect everything to be nice and tidy.

🛠️ What does this script do?

Inspired by William Lam’s original blog post on FCD cleanup, this script takes the concept further with modern PowerCLI best practices.

You can download and use the latest version of the script from my GitHub repo:
👉 https://github.com/saintdle/PowerCLI/blob/saintdle-patch-1/Cleanup%20standalone%20FCD

Here’s what it does:

  1. Checks if you’re already connected to vCenter; if not, prompts you to connect
  2. Retrieves all existing First Class Disks (FCDs) using Get-VDisk
  3. Retrieves all Kubernetes-managed volumes using Get-CnsVolume
  4. Excludes any FCDs still managed by Kubernetes (CNS)
  5. For each remaining “orphaned” FCD, checks if it is mounted to any VM (even if Kubernetes doesn’t know about it)
  6. Generates a report (CSV + logs) of any true orphaned FCDs (not in CNS + not attached to any VM)
  7. If dry-run mode is OFF, safely removes the orphaned FCDs from the datastore

The script is intentionally designed for safety first, with dry-run mode ON by default. You must explicitly allow deletions with -DryRun:$false and optionally -AutoDelete.

❗ Known limitations and gotchas

Despite our best efforts, there is one notorious problem child: the dreaded locked or “current state” error.

You may still see errors like:

The operation is not allowed in the current state.

This happens when vSphere believes something (an ESXi host, a failed task, or the VASA provider) has an active reference to the FCD. These “ghost locks” can only be diagnosed and resolved by:

  • Using ESXi shell commands like vmkfstools -D to trace lock owners
  • Rebooting an ESXi host holding the lock
  • Engaging VMware GSS to clear internal stale references (sometimes the only safe option)

This script does not attempt to forcibly unlock or clean these disks for obvious reasons. You really don’t want a script going full cowboy on locked production disks. 😅

So while the script works great for true orphaned disks, ghost FCDs are a special case and remain an exercise for the reader (or your VMware TAM and GSS support team!).

⚠️ Before you copy/paste this blindly…

Let me be brutally honest: this script is just some random code stitched together by me, a PowerCLI enthusiast with far too much time on my hands, and enhanced by ChatGPT. It’s never been properly tested in a production environment.

 

Regards


Bluesky Icon
Follow me on Bluesky

Dean Lewis

PowerCLI

PowerCLI – Import-VApp Name or service not known

I kept running into the error whilst running PowerCLI on Ubuntu. After wracking my brains, I realised that the issue is DNS, my Ubuntu box couldn’t resolve the FQDN for the ESXi host, which is a mandatory parameter for the Import-vApp command.

Import-VApp             Name or service not known

Import-VApp Name or service not known

Dean

PowerCLI

PowerCLI with a GUI – Clone a machine, add DHCP Reservations, alter CPUID

In this blog post, I am going to break down a PowerShell code I have created (with help from some colleagues). The functions of this PowerShell code are;

  • Present a GUI form to the end user
    • Connect to a vCenter
    • Select the virtual machine to be cloned
    • Select the datastore the new VM is to be stored on (display DS free space)
    • Select the host for this VM to be created against (display free memory on the host)
    • Set the new VM name
    • Create an IP reservation in both the Production and DR DHCP Scopes

Below are some functional screenshots of the code’s GUI and also a rough flowchart of what I needed to achieve.

You can skip to the end to find the full code or my github.

PowerCLI with a GUI - Clone a machine, add DHCP Reservations, alter CPUID

clone script connection window veducate

clone script full GUI options when connected vEducate

clone vm script flowchart

TAM Lab Recording

Since posting this blog, I also covered this in a VMware TAM Lab recording which you can watch below.

A little more background on the script

So my customer had a dedicated environment for hosting their custom application, however these applications were built and running inside an old unsupported OS which expected to be running on a particular era of CPU’s to run correctly, for example todays Intel Skylake would cause the OS to panic and not run. As you can also imagine with this type of older OS, there are no VM Tools support either.

Here is the architecture diagram;

clone vm architecture diagram

Providing DR around this environment was interesting, we could protect the VM using SRM and storage array LUN replication. But this also presented some issues, when the VM boots in DR. “what happens with networking?” hence we setup a DHCP reservation on both Production and DR. Meaning we know the VMs IP regardless of where its booted.

Continue reading PowerCLI with a GUI – Clone a machine, add DHCP Reservations, alter CPUID

PowerCLI

PowerCLI – Setup Host networking and storage ready for ISCSI LUNs

So I am no scripting master, my PowerShell knowledge is still something I want to expand. During an install last week I had a number of hosts to setup from scratch, so I decided to do this via PowerCLI, as a lot of the tasks were repetitive. Setting up the vSwitch networking and iSCSI configuration for each host

For those of you new to scripting, I’ve included screenshots to accompany the commands so you can see whats going on in the GUI.

Note: the full code without the breaks is at the end of this post

#Setup which host to target 
$VMhost = 'hostname'

Continue reading PowerCLI – Setup Host networking and storage ready for ISCSI LUNs

vmwarevss

Using PowerCLI to create Virtual Machine Port Groups

So basically I had a host failure where all of the configure was lost, if I was more savvy with Powershell/PowerCLI, I would have been able to rebuild it all via scripts, but that clones the settings from a working host.

But nevermind that is for a different day of learning.

So I configured the host to the point of Networking, so the vSwitches had the correct NICs, but I needed to do all the port groups, which in the GUI if you have a few to do is time consuming.

So in PowereCLI, pull all of your information, port-group names and VLAN IDs.

Get-Vmhost -name <FQDN of host> | Get-VirtualSwitch -name  | Get-VirtualPortGroup

2014-11-12_00-07-01

To create a port-group

Get-Vmhost -name <FQDN of host> | Get-VirtualSwitch -Name  | New-VirtualPortgroup -Name "Name of PG" -VlanID
2014-11-13_10-58-47

Obviously this is a very short crude method of achieving what I need, but here you can see the basic building blocks needed to create Port Group in PowerCLI.
Regards

Dean