saltext-vcf-cloud
A native Salt Cloud driver for VMware vSphere, backed by
saltext.vcf.
Salt 3008 no longer ships the old community VMware cloud driver. This extension
restores the vmware provider without replacing Salt Cloud's lifecycle. Native
Salt Cloud still generates and pre-accepts minion keys, renders the deployment
script, bootstraps the minion, and removes its key during destruction. The
extension handles the vSphere operations through saltext.vcf and pyVmomi.
What works
- Clone a VM or template, or create a blank VM.
- Select folders, datastores, clusters, resource pools, and hosts by name or MoID.
- Configure CPU, memory, advanced settings, hot-add options, NICs, and disks.
- Attach existing vCenter tags to newly created VMs and templates.
- Apply a named vCenter customization spec or generate a Linux customization spec.
- Wait for an address reported by VMware Tools, run the native Salt bootstrap, and return the new minion's complete grains dictionary.
- List, inspect, start, stop, reboot, and destroy VMs.
- Use normal Salt Cloud providers, profiles, maps, events, cache, and key lifecycle.
The driver has been integration-tested with Salt 3008.2, saltext.vcf 1.0.0,
pyVmomi 9.1.0.0, and vCenter 8.0.3. Salt 3008.x is the supported Salt line.
Install
Install this extension on the machine that runs salt-cloud, normally the Salt
master. Salt 3008 packages use an isolated onedir Python, so use salt-pip, not
the system pip.
sudo salt-pip install saltext.vcf-cloud
The wheel installs the compatible saltext.vcf[vcenter] and pyVmomi dependencies.
To pin the first release:
sudo salt-pip install "saltext.vcf-cloud==0.1.0"
For a source checkout, use:
git clone https://github.com/Arderos/saltext-vcf-cloud.git
cd saltext-vcf-cloud
sudo salt-pip install .
Verify that Salt can discover the extension:
salt-pip show saltext.vcf-cloud saltext.vcf pyvmomi
salt-cloud --list-providers
salt-cloud is a new process on every invocation, so a restart is not required
for the CLI. Restart salt-master if runners or another long-lived master process
will load the extension.
To upgrade or remove it:
sudo salt-pip install --upgrade saltext.vcf-cloud
sudo salt-pip uninstall saltext.vcf-cloud
Configure a provider
Create /etc/salt/cloud.providers.d/vcenter.conf:
lab-vcenter:
driver: vmware
url: vcenter.example.com
user: svc-salt-cloud@vsphere.local
password: replace-with-a-secret
verify_ssl: true
task_timeout: 900
create_missing_tags: false
Do not commit the real password. Protect the provider file with restrictive
permissions or use a Salt-supported secret/SDB backend. Set verify_ssl: false
only for a vCenter whose certificate cannot yet be verified.
Provider options:
| Option | Required | Default | Meaning |
|---|---|---|---|
url |
yes | — | vCenter hostname or HTTPS URL |
user |
yes | — | vCenter account |
password |
yes | — | vCenter password |
verify_ssl |
no | true |
Verify the vCenter TLS certificate |
protocol |
no | https |
Only HTTPS is supported |
port |
no | 443 |
vCenter HTTPS port |
vcf_timeout |
no | 30 |
Connection timeout in seconds |
task_timeout |
no | 900 |
Default vSphere task timeout in seconds |
create_missing_tags |
no | false |
Create missing tag categories and tags |
default_tag_category_cardinality |
no | SINGLE |
Cardinality for new categories without an override |
tag_category_cardinalities |
no | {} |
New-category cardinality overrides keyed by exact category name |
Check connectivity without creating anything:
salt-cloud -f get_vcenter_version lab-vcenter
salt-cloud -f avail_images lab-vcenter
salt-cloud -f avail_tags lab-vcenter
Configure a profile
Create /etc/salt/cloud.profiles.d/ubuntu.conf:
ubuntu-2404:
provider: lab-vcenter
clonefrom: template-ubuntu-2404
cluster: compute-cluster
folder: salt-managed
datastore: datastore-01
num_cpus: 2
memory: 4GB
cores_per_socket: 1
annotation: Managed by Salt Cloud
tags:
- category: Environment
name: Production
- category: Operating System
name: Ubuntu
devices:
network:
Network adapter 1:
name: server-vlan
switch_type: distributed
adapter_type: vmxnet3
start_connected: true
disk:
Hard disk 2:
size: 50
thin_provision: true
customization: true
domain: example.com
time_zone: UTC
dns_servers:
- 192.0.2.53
ssh_username: ubuntu
private_key: /root/.ssh/salt-cloud
script: bootstrap-salt
script_args: stable 3008
The keys under devices.network and devices.disk are device labels. When a
label already exists on the cloned template, the driver updates its network
backing and start_connected state or resizes the disk. vSphere cannot safely
change the type or MAC address of an existing NIC through this operation, so a
different adapter_type or mac produces a clear error instead of being
silently ignored. A missing NIC label creates a NIC; a missing disk label creates
a disk. Disk sizes must be positive whole numbers of GB. Disks can grow but
cannot shrink.
Use object MoIDs instead of names when vCenter contains duplicate names. For a
blank VM without clonefrom, folder and datastore are required, together
with enough placement information (cluster, resourcepool, or host) for
vCenter to select compute resources. Cloning from a vCenter template requires
cluster or resourcepool/resource_pool; host alone does not populate the
required resource pool in the clone placement specification.
vCenter tags
Set tags to a list of category/name mappings. Both names are matched exactly;
the category is mandatory because vCenter tag names are only meaningful within
their category. Internal vCenter IDs are resolved by the driver and never need
to appear in a profile or map.
List the available category and tag names through the same Salt Cloud provider:
salt-cloud -f avail_tags lab-vcenter
Inspect the tags attached to one VM:
salt-cloud -a show_tags web-01.example.com
By default, both the category and tag must already exist. Set
create_missing_tags: true on the provider to create missing objects. A missing
tag is created inside the existing category. A missing category is created for
VirtualMachine objects with default_tag_category_cardinality, which defaults
to SINGLE. Categories that must allow several tags per VM can override that
default by exact category name:
create_missing_tags: true
default_tag_category_cardinality: SINGLE
tag_category_cardinalities:
Capabilities: MULTIPLE
Overrides are consulted only when a category is absent. Existing categories always retain their vCenter configuration and do not need to be repeated in the provider.
Tags are attached after VM configuration and guest customization, but before
power-on and Salt bootstrap. Duplicate category/name entries are attached only
once. If lookup, creation, or assignment fails, create returns an error and
does not continue to power-on or bootstrap the VM.
Static guest networking
Put addressing data on each NIC to generate a Linux customization spec:
devices:
network:
Network adapter 1:
name: server-vlan
switch_type: distributed
ip: 192.0.2.25
subnet_mask: 255.255.255.0
gateway:
- 192.0.2.1
dns_servers:
- 192.0.2.53
Without ip, that NIC uses DHCP in the generated customization spec. Network
mapping order must match the template's guest NIC order. Alternatively, set
customization_spec to the name of an existing vCenter customization spec:
customization_spec: linux-default
Guest customization and address discovery require a compatible guest and VMware Tools/open-vm-tools running in the template.
Guest customization is not applied when template: true, because vCenter does
not support CustomizeVM_Task against a template object.
Profile options
| Option | Default | Meaning |
|---|---|---|
clonefrom |
none | Source VM/template name or MoID |
folder |
source folder | Destination folder name or MoID |
datastore |
source datastore | Destination datastore name or MoID |
cluster |
none | Cluster name or MoID |
resourcepool / resource_pool |
none | Resource pool name or MoID |
host |
none | ESXi host name or MoID |
image |
otherGuest64 |
vSphere guest ID for a blank VM |
num_cpus |
source value | Virtual CPU count |
memory |
source value | Memory in MB, M, MB, G, or GB |
cores_per_socket |
unchanged | Cores per virtual socket |
annotation |
unchanged | VM annotation |
tags |
none | List of exact vCenter category/name mappings to attach |
extra_config |
{} |
vSphere advanced settings mapping |
cpu_hot_add |
unchanged | Enable CPU hot-add |
cpu_hot_remove |
unchanged | Enable CPU hot-remove |
mem_hot_add |
unchanged | Enable memory hot-add |
nested_hv |
unchanged | Expose hardware virtualization |
vpmc |
unchanged | Enable virtual CPU performance counters |
template |
false |
Create a template instead of a runnable VM |
power_on |
true |
Power on after configuration |
deploy |
true |
Run Salt's native bootstrap after address discovery |
customization |
true |
Apply guest customization when it can be built |
customization_spec |
none | Existing vCenter customization spec name |
wait_for_ip_timeout |
1200 |
Seconds to wait for a guest IPv4 address |
wait_for_minion_timeout |
120 |
Seconds to wait for grains.items before returning instance data with a warning |
task_timeout |
provider value | Per-profile vSphere task timeout |
Standard Salt Cloud deployment options such as ssh_username, ssh_password,
private_key/key_filename, script, script_args, minion, and master
are passed to Salt's native bootstrap implementation.
Use a map
Create /etc/salt/cloud.maps.d/vmware.map:
ubuntu-2404:
- web-01.example.com:
num_cpus: 4
memory: 8GB
- web-02.example.com:
num_cpus: 4
memory: 8GB
Create the VMs in parallel:
salt-cloud -m /etc/salt/cloud.maps.d/vmware.map -P
Or create one VM directly from a profile:
salt-cloud -p ubuntu-2404 web-01.example.com
Inspect and operate VMs:
salt-cloud -Q
salt-cloud -F
salt-cloud -a start web-01.example.com
salt-cloud -a stop web-01.example.com
salt-cloud -a reboot web-01.example.com
salt-cloud -a show_tags web-01.example.com
salt-cloud -d web-01.example.com
Minion keys and bootstrap
There is no custom key-generation protocol in this driver. Salt Cloud's core performs its normal sequence:
- Generate the minion keypair before calling the provider's
create(). - Pre-accept the public key on the master.
- Render the selected deployment script and minion configuration.
- Pass the generated keys and configuration through the native
cloud.bootstraputility after the VM has an address. - Wait for the configured minion ID to return
grains.items. When available, create output is the complete guest grains dictionary. If the wait times out or a local master client is unavailable, deployment remains successful and create returns instance data with aWarninginstead. - Remove the accepted key when Salt Cloud destroys the VM.
Creates that skip bootstrap because deploy: false, power_on: false, or
template: true is set return normal instance data rather than guest grains.
This is the same lifecycle used by native Salt Cloud providers. Options that change Salt's key handling continue to belong to Salt Cloud itself.
Troubleshooting
Run with debug logging when a vSphere or bootstrap step fails:
salt-cloud -l debug -p ubuntu-2404 test-01.example.com
Common causes:
vmwaredoes not appear in--list-providers: the extension was installed with systempipinstead ofsalt-pip, or a required dependency cannot load.- Certificate verification fails: install the issuing CA for the Salt host;
use
verify_ssl: falseonly as a temporary exception. - An object name is ambiguous: use the vSphere MoID.
- The VM is created but bootstrap does not run: check VMware Tools, guest IP
reporting, DNS fallback, SSH reachability, username/key, and
wait_for_ip_timeout. The create result contains anErrorand emits adeploy_failedevent when no IPv4 address is found or bootstrap reports a failure. - Bootstrap completes but the minion does not return grains: create returns
instance data with a
Warningand still emits thecreatedevent with the computedminion_id. Check the effectiveminion.id,append_domain, master address, accepted key, andwait_for_minion_timeout. - Guest customization fails: confirm the template OS supports vSphere guest customization and that NIC order matches the profile.
Salt Cloud 3008 pre-accepts the minion key before it calls a provider's
create() function, but does not tell the provider whether the key was accepted
on the local or a remote master. After a failed deployment, verify the target
master and remove an unused accepted key with salt-key -d <minion-id> when
appropriate.
The password is not included in Salt Cloud event payloads or returned instance data. Debug logs from dependencies can still contain environmental details; review logs before sharing them publicly.
Development
git clone https://github.com/Arderos/saltext-vcf-cloud.git
cd saltext-vcf-cloud
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e ".[tests]" build
pytest
python -m build
Unit tests do not require a vCenter. Live integration testing requires an explicitly configured disposable VM/template and is intentionally not run by public CI.
Security
Please report vulnerabilities through GitHub's private vulnerability reporting for this repository. See SECURITY.md.
License
Metadata
Release files for saltext.vcf-cloud 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| saltext_vcf_cloud-0.1.1.tar.gz | 77.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| saltext_vcf_cloud-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 101.2 kB
Release files / saltext_vcf_cloud-0.1.1.tar.gz
| Download URL | saltext_vcf_cloud-0.1.1.tar.gz |
|---|---|
| Size | 77.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cbc5007b8b33de7f0e0b8d84d02087a759b9f41c4d0808eb39cbcc315110b279
|
|
BLAKE2b-256 checksum How to use checksums |
313c2cf2d667679786eb0ef8137a72eb052ddd42adcd2b87b9f1aec98c04d10a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.
Transparency logRelease files / saltext_vcf_cloud-0.1.1-py3-none-any.whl
| Download URL | saltext_vcf_cloud-0.1.1-py3-none-any.whl |
|---|---|
| Size | 23.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
767870ea703e431a0051a613029e7e2f06f5ee2fdb1e16b24bb52d91ec7c0f8c
|
|
BLAKE2b-256 checksum How to use checksums |
c5e5268e3d914a0176b387192dfa321eb28e2b72d3c404f76e22d06c155a0198
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.
Transparency log