Skip to main content

saltext-vcf-cloud

CI CodeQL License

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:

  1. Generate the minion keypair before calling the provider's create().
  2. Pre-accept the public key on the master.
  3. Render the selected deployment script and minion configuration.
  4. Pass the generated keys and configuration through the native cloud.bootstrap utility after the VM has an address.
  5. 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 a Warning instead.
  6. 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:

  • vmware does not appear in --list-providers: the extension was installed with system pip instead of salt-pip, or a required dependency cannot load.
  • Certificate verification fails: install the issuing CA for the Salt host; use verify_ssl: false only 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 an Error and emits a deploy_failed event 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 Warning and still emits the created event with the computed minion_id. Check the effective minion.id, append_domain, master address, accepted key, and wait_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

Apache License 2.0. See LICENSE and NOTICE.

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)

Source distribution for saltext.vcf-cloud 0.1.1
File Size Uploaded
saltext_vcf_cloud-0.1.1.tar.gz 77.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for saltext.vcf-cloud 0.1.1
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page