Welcome back to our series on Automating vSphere Configuration Profile (VCP). In Part 1, we broke down the core VCP APIs and how they maintain the “desired state” of vSphere clusters. Now, it’s time to get hands-on with the code.
This blog post explains how to consume these APIs using the tools most familiar to VI admins and developers: PowerCLI and Python.
Consuming VCP APIs Using PowerCLI SDK
If you are already living in a PowerShell world, the PowerCLI SDK is your best friend. It provides direct, low-level access to the VMware Cloud Foundation (VCF) and vSphere Automation APIs, making it a natural fit for existing automation pipelines.
Pro Tip: If you’re new to the latest SDK architecture, check out my recent blog post, Demystifying VCF PowerCLI 9.0 SDK, to understand how the new bindings work.
Getting Started
To begin, ensure you have VCF PowerCLI 9.0 (or later) installed. The magic of this SDK lies in its discoverability; you don’t have to guess the command names if you already know the REST URI.
Finding Your Command
The Get-vSphereOperation cmdlet is the “Rosetta Stone” for mapping REST APIs to PowerCLI. Let’s look at a common VCP task: checking a cluster’s enablement status.
|
1 |
GET https://{api_host}/api/esx/settings/clusters/{cluster}/enablement/configuration |
The Discovery Command:
PowerShell
|
1 |
Get-vSphereOperation -Method GET -Path "/api/esx/settings/clusters/{cluster}/enablement/configuration" |
Running this will return a CommandInfo object. Once you have that, you can invoke the corresponding operation.
The below PowerCLI code sample demonstrates the process of enabling vSphere Configuration Profiles (VCP) on a vSphere Cluster. Furthermore, it illustrates how to manage, update, and configure the desired state using the VCP draft APIs.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
#vSphere Configuration Profile API, PowerShell Sample #Author: Jatin Purohit #Title: Product Marketing Engineer, Broadcom #API Blog Post: #https://blogs.vmware.com/cloud-foundation/2026/01/22/vsphere-configuration-profile/ $vc = "vc-fqdn-or-ip" $cred = Get-Credential -Message "Enter vCenter Credentials" Connect-VIServer -Server $vc -Credential $cred $cluster = Get-Cluster -Name "cluster-name" ######################################################################################### #Transition a cluster to be managed by vSphere Configuration Profile ######################################################################################### #Check if Cluster is managed by vSphere Configuration API $IsVCPEnabled = Invoke-GetClusterEnablementConfiguration -Cluster $cluster.ExtensionData.Moref.Value Write-Host "vSphere Configuration Profile Enabled:" $IsVCPEnabled.Enabled #Invoke Cluster Eligibility Check for Configuration Transition if not already enabled if (-not $IsVCPEnabled.Enabled) { Invoke-CheckEligibilityClusterConfigurationTransitionAsync -Cluster $cluster.ExtensionData.Moref.Value -Confirm:$false } #Import Configuration Profile from a reference host $referenceHost = Get-VMHost -Name "esx-fqdn-or-ip" $body = $referenceHost.ExtensionData.Moref.Value Invoke-ImportFromHostClusterConfigurationTransitionAsync -Body $body -Cluster $cluster.ExtensionData.MoRef.Value -Confirm:$false #Validate cluster configuration Invoke-ValidateConfigClusterConfigurationTransitionAsync -Cluster $cluster.ExtensionData.Moref.Value -Confirm:$false #Enable vSphere Configuration Profile on the cluster Invoke-EnableClusterConfigurationTransitionAsync -Cluster $cluster.ExtensionData.Moref.Value -Confirm:$false Start-Sleep -Seconds 60 #Check if the vSphere Configuration Profile is enabled $IsVCPEnabled = Invoke-GetClusterEnablementConfiguration -Cluster $cluster.ExtensionData.Moref.Value Write-Host "vSphere Configuration Profile Enabled:" $IsVCPEnabled.Enabled ######################################################################################### #Manage Desired State Configuration on the Cluster using vSphere Configuration Profile ######################################################################################### #Create a New Configuration Draft $draftId = Invoke-CreateNewDraftClusterConfiguration -Cluster $cluster.ExtensionData.Moref.Value Write-Host "Initialized Configuration Draft ID:" $draftId #Export Cluster Configuration from Configuration Draft $configuration = Invoke-GetClusterDraftConfiguration -Cluster $cluster.ExtensionData.Moref.Value -Draft $draftId $configuration |Out-File ClusterConfig.json #Modify the Cluster Configuration JSON as needed #For example, changing NTP settings, adding/removing tags, etc. #Load your JSON file into a PowerShell Object $configObj = Get-Content ./ClusterConfig.json -Raw | ConvertFrom-Json #Convert that object into a JSON String # CRITICAL: We use -Depth 10 to ensure the nested ESX/NSX settings aren't lost $configJsonString = $configObj | ConvertTo-Json -Depth 10 #Initialize the UpdateSpec using the JSON STRING $updatedSpec = Initialize-SettingsClustersConfigurationDraftsUpdateSpec -Config $configJsonString #Invoke the update to the Cluster Draft Invoke-UpdateClusterDraft -Cluster $cluster.ExtensionData.MoRef.Value -Draft $draftId -EsxSettingsClustersConfigurationDraftsUpdateSpec $updatedSpec #Validate the Cluster Draft Configuration Changes $configChanges = Invoke-GetClusterDraft0 -Cluster $cluster.ExtensionData.MoRef.Value -Draft $draftId $configChanges |ConvertTo-Json -Depth 10 #Run Prechecks on the Draft Configuration Invoke-PrecheckClusterDraftAsync -Cluster $cluster.ExtensionData.MoRef.Value -Draft $draftId -Confirm:$false Start-Sleep -Seconds 30 #Apply Config Profile Draft to the Cluster Invoke-ApplyClusterDraft -Cluster $cluster.ExtensionData.MoRef.Value -Draft $draftId -Confirm:$false #Monitor the Job #Check Cluster Compliance Status Invoke-CheckComplianceClusterConfigurationAsync -Cluster $cluster.ExtensionData.MoRef.Value -Confirm:$false $complianceResult = Invoke-GetClusterConfigurationReportsLastComplianceResult -Cluster $cluster.ExtensionData.MoRef.Value Write-Host "Cluster Compliance Status:" $complianceResult.ClusterStatus Write-Host "Cluster Compliance Summary:" $complianceResult.Summary.DefaultMessage Write-Host "Compliant Hosts:" $complianceResult.CompliantHosts |
Consuming VCP APIs Using Unified VCF SDK for Python
The Unified VCF SDK 9.0 for Python, introduced in VCF 9.0, represents a significant evolution in automating VMware environments. This new SDK simplifies the consumption of VCF APIs by unifying what were previously separate libraries such as pyvmomi for SOAP, the vSphere Automation SDK for REST, and a dedicated vSAN SDK for vSAN into a single package.
Developers can now use this single SDK to access all VCF APIs. Refer to the blog post Introducing a Unified VCF SDK 9.0 for Python and Java to learn more about the API coverage.
Core Enhancements in VCF SDK 9.0
- Consolidated Packaging: You can now install the entire suite via a single command: pip install vcf-sdk.
- Unified Authentication: The biggest pain point in previous versions was managing different sessions for SOAP (/vim25) and REST (/api) endpoints. Now, you can log in once and share the session ID across both.
- Expanded Coverage: Includes bindings for the new VCF Installer, SDDC Manager, and the latest vSphere Configuration Profile (VCP) APIs.
How are VCP APIs Structured in VCF SDK?
To automate vSphere Configuration Profiles (VCP), you will primarily work within the com.vmware.esx.settings.clusters.* namespace.
In Python, the SDK is organized into Modules (which contain the client logic) and Service Classes (which contain the methods like get, list, or enable_task). To perform an action, you must import the specific client module and then instantiate its service class.
Example: Transitioning a Cluster to VCP
One of the most common VCP tasks is moving a cluster from Host Profiles to VCP.
|
1 |
POST https://{api_host}/api/esx/settings/clusters/{cluster}/enablement/configuration/transition?action=enable |
The Python Implementation: To invoke this, you use the Transition service class found within the enablement.configuration_client module.
1. Import the Service Class
First, import the Transition class from the appropriate client module:
Python
|
1 |
from com.vmware.esx.settings.clusters.enablement.configuration_client import Transition |
2. Initialize the Service Endpoint
Once imported, you create a service endpoint by passing your authenticated vsphere_client stub configuration to the class constructor. This “connects” the class to your active session.
Python
|
1 2 3 4 5 6 7 8 |
# Create the service endpoint transition_service = Transition(vsphere_client._stub_config) # Execute the 'enable' action as a vCenter Task # Replace "domain-c10" with your specific Cluster MORef enable_task = transition_service.enable_task(cluster="domain-c10") print(f"VCP Enablement Task ID: {enable_task}") |
Key Takeaway
While the REST API path gives you the “address” of the operation, the Python SDK maps these paths into a nested hierarchy. Always look for the _client suffix in the module name to find the classes that contain the actual execution methods (the “verbs”) for your automation.
Check out the complete python sample code to enable VCP on a vSphere Cluster.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
""" vSphere Configuration Profile API, Python Sample Author: Jatin Purohit Title: Product Marketing Engineer, Broadcom API Blog Post: https://blogs.vmware.com/cloud-foundation/2026/01/22/vsphere-configuration-profile/ """ import requests import urllib3 import json from vmware.vapi.vsphere.client import create_vsphere_client from com.vmware.esx.settings.clusters.enablement_client import Configuration from com.vmware.esx.settings.clusters_client import Configuration from com.vmware.esx.settings.clusters.enablement.configuration_client import Transition from com.vmware.esx.settings.clusters.configuration.reports_client import LastComplianceResult from com.vmware.esx.settings.clusters.configuration_client import Drafts import time session = requests.session() session.verify = False urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # Create vSphere Client Session vsphere_client = create_vsphere_client( server='vc_fqdn_or_ip', username='vc_username', password='vc_password', session=session ) print(f"\033[92mConnected to vCenter Server, Session ID: \033[0m {vsphere_client.session_id}") ######################################################################################### #Transition a cluster to be managed by vSphere Configuration Profile ######################################################################################### #Check VCP Enablement Status on Cluster print("\033[92m1. Checking VCP Configuration for cluster: domain-c8 \033[0m") print("GET /esx/settings/clusters/:cluster/enablement/configuration") vcp_service = Configuration(vsphere_client._stub_config) result = vcp_service.get(cluster="domain-c10") print(f"\033[92mvSphere Configuration Profile Enablement Status on cluster domain-c10: \033[0m {result.enabled} ") #Invoke Cluster Eligibility Check for VCP Transition print("\n\033[92m2. Invoking Cluster Eligibility Check for Configuration Transition...\033[0m") print("POST /esx/settings/clusters/:cluster/enablement/configuration/transition?action=checkEligibility&vmw-task=true") transition_service = Transition(vsphere_client._stub_config) check_eligibility_task = transition_service.check_eligibility_task(cluster="domain-c10") print(f"\033[92mCluster Eligibility check initiated successfully. VMware Task ID: \033[0m {check_eligibility_task.task_id}") time.sleep(120) #Import Configuration Profile from a reference Host for VCP Transition print("\n\033[92m3. Importing Configuration Profile from reference Host for VCP Transition...\033[0m") print("POST /esx/settings/clusters/:cluster/enablement/configuration/transition?action=importFromHost&vmw-task=true") import_task = transition_service.import_from_host_task(cluster="domain-c10", host="host-13") print(f"\033[92mConfiguration Profile import initiated successfully. VMware Task ID: \033[0m {import_task.task_id}") time.sleep(120) #Validate Imported Cluster Configuration Profile for VCP Transition print("\n\033[92m4. Validating Imported Cluster Configuration Profile for VCP Transition...\033[0m") print("POST /esx/settings/clusters/:cluster/enablement/configuration/transition?action=validateConfig&vmw-task=true") validate_task = transition_service.validate_config_task(cluster="domain-c10") print(f"\033[92mConfiguration Profile validation initiated successfully. VMware Task ID: \033[0m {validate_task.task_id}") time.sleep(120) #Enable VCP on Cluster using Imported Configuration Profile print("\n\033[92m5. Enabling VCP on Cluster using Imported Configuration Profile...\033[0m") print("POST /esx/settings/clusters/:cluster/enablement/configuration/transition?action=enable&vmw-task=true") enable_task = transition_service.enable_task(cluster="domain-c10") print(f"\033[92mVCP Enablement initiated successfully. VMware Task ID: \033[0m {enable_task.task_id}") time.sleep(120) #Check VCP Enablement Status on Cluster after Transition print("\n\033[92m6. Checking VCP Configuration for cluster: domain-c10 \033[0m") print("GET /esx/settings/clusters/:cluster/enablement/configuration") vcp_service = Configuration(vsphere_client._stub_config) result = vcp_service.get(cluster="domain-c10") print(f"\033[92mvSphere Configuration Profile Enablement Status on cluster domain-c10: \033[0m {result.enabled} ") ######################################################################################## #Manage Desired State Configuration on the Cluster using vSphere Configuration Profile ######################################################################################## #Check Cluster Compliance Status with Desired State Configuration print("\n\033[92m7. Checking Cluster Compliance Status with Desired State Configuration...\033[0m") print("GET /esx/settings/clusters/:cluster/configuration?action=checkCompliance&vmw-task=true") compliance_service = Configuration(vsphere_client._stub_config) result = compliance_service.check_compliance_task(cluster="domain-c10") print(f"\033[92mCluster Compliance Status: \033[0m {result.get_task_id()} ") #Validate Cluster Desired State Configuration Compliance Results print("\n\033[92m8. Validating Cluster Desired State Configuration Compliance Results...\033[0m") print("GET /esx/settings/clusters/:cluster/configuration/reports/last-compliance-result") report_service = LastComplianceResult(vsphere_client._stub_config) compliance_report = report_service.get(cluster="domain-c10") print(f"\033[92mCompliance Result Status: \033[0m {compliance_report.cluster_status} ") #Create Configuration Draft for Cluster print("\n\033[92m9. Creating Configuration Draft for Cluster...\033[0m") print("POST /esx/settings/clusters/:cluster/configuration/drafts") draft_service = Drafts(vsphere_client._stub_config) draft_id = draft_service.create(cluster="domain-c10") print(f"\033[92mConfiguration Draft created successfully, Draft ID: \033[0m {draft_id}") #Export Cluster Configuration from Draft print("\n\033[92m10. Exporting Cluster Configuration from Draft...\033[0m") print(f"POST /esx/settings/clusters/:cluster/configuration/drafts/{{draft}}?action=exportConfig ") draft_config = draft_service.export_config(cluster="domain-c10", draft=draft_id) print(draft_config) data = vars(draft_config).copy() # parse 'Config' data to dictionary if isinstance(data.get("config"), str): try: data["config"] = json.loads(data["config"]) except Exception: pass # Leave as is if not valid JSON with open("config_new.json", "w") as f: json.dump(data, f, indent=2) # Load the JSON file into a Python object with open("config.json", "r") as f: config_obj = json.load(f) # Convert the Python object back into a JSON string # config_json_string = json.dumps(config_obj["config"], indent=2) #Update the Configuration Draft with new configurations print("\n\033[92m11. Updating the Configuration Draft with new configurations ...\033[0m") print(f"POST /esx/settings/clusters/:cluster/configuration/drafts/{{draft}}?action=update ") draft_spec = draft_service.UpdateSpec(expected_revision=None, config=config_json_string) updated_draft = draft_service.update(cluster="domain-c10", draft=draft_id, spec=draft_spec) #Run Draft Precheck print("\n\033[92m12. Running Draft Precheck ...\033[0m") precheck_task = draft_service.precheck_task(cluster="domain-c10", draft=draft_id) print(f"POST /esx/settings/clusters/:cluster/configuration/drafts/{{draft}}?action=precheck&vmw-task=true") print(f"\033[92mDraft Precheck initiated successfully. VMware Task ID: \033[0m {precheck_task.task_id}") #Apply the Configuration Draft time.sleep(120) print("\n\033[92m13. Applying the Configuration Draft ...\033[0m") print(f"POST /esx/settings/clusters/:cluster/configuration/drafts/{{draft}}?action=apply") apply_task = draft_service.apply(cluster="domain-c10", draft=draft_id) print(f"\033[92mConfiguration Draft applied successfully. VMware Task ID: \033[0m {apply_task}") |
The vSphere Configuration Profile (VCP) APIs in the Unified VCF SDK and PowerCLI 9.0 provide a direct, programmatic way to manage cluster configurations. By using these unified tools, you can automate setup tasks and ensure consistency across your environment. Whether you use PowerCLI for quick scripts or the Python SDK for larger applications, managing VCP is now more integrated and accessible.
Resources
You can find the complete Python sample for the VCP enablement and configuration workflow here:
- GitHub Repository: VCP Automation Samples
Next Steps
In the next post, we will move beyond manual scripts to explore GitOps workflows. You’ll learn how to manage these cluster profiles as code, using Git to trigger automated updates.
Discover more from VMware Cloud Foundation (VCF) Blog
Subscribe to get the latest posts sent to your email.