In a previous post I explained how to deploy a batch of Virtual Machines from a template :

In this blog post, we will explore an Ansible playbook that creates multiple virtual machines (VMs) in a vCenter environment. We will also host in another file common parameters to keep the main playbook "clean". This playbook uses sequential naming for the VMs and allows you to specify various parameters such as the number of VMs to create, VM names, templates, and more.

Playbook Overview
The playbook is divided into several sections:
- Play definition: The play targets localhost, gathers no facts, and includes variables from an external YAML file called
vars_multiple.yml
. - Create a folder for VMs in vCenter: This task uses the
community.vmware.vcenter_folder
module to create a new folder under the specified datacenter in vCenter, where the VMs will be created. - List all VMs in the vCenter: This task retrieves information about all existing VMs in the vCenter environment using the
community.vmware.vmware_vm_info
module. - Filter VMs based on prefix and determine the maximum number: Using a set_fact task, this section extracts the maximum number from the names of any existing VMs that match the specified prefix, in order to create new VM names with sequential numbering.
- Create VMs starting from the next available number: This section creates multiple VMs with custom specifications using the
community.vmware.vmware_guest
module and sequential naming based on thestart_number
.
Prerequisites
Before running this playbook, ensure that you have:
- Ansible installed and configured on your system.
- Access to a vCenter server with valid credentials.
- A proper inventory file or configuration for connecting to the vCenter server via an Ansible module.
To install Ansible you can read the instructions here :

Playbook Walkthrough
Let's walk through each section of this playbook:
1. Play definition
- name: Create multiple VMs with sequential naming
hosts: localhost
gather_facts: false
vars_files:
- vars_multiple.yml
This play is defined to run locally, does not gather facts about the system, and includes a vars_files
directive that references a file called vars_multiple.yml
. This YAML file contains variables required for creating VMs in vCenter.
2. Create a folder for VMs in vCenter
- name: Create a folder for VMs in vCenter
community.vmware.vcenter_folder:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ vcenter_validate_certs }}"
datacenter: "{{ vcenter_datacenter }}"
folder_name: "{{ vcenter_destination_folder }}"
folder_type: vm
state: present
This task uses the community.vmware.vcenter_folder
module to create a new folder under the specified datacenter in vCenter, where the VMs will be created. Replace variables like vcenter_hostname
, vcenter_username
, etc., with valid values according to your environment.
3. List all VMs in the vCenter
- name: List all VMs in the vCenter
community.vmware.vmware_vm_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ vcenter_validate_certs }}"
register: all_vms_info
This task retrieves information about all existing VMs in the vCenter environment using the community.vmware.vmware_vm_info
module and registers the output as a variable called all_vms_info
.
4. Filter VMs based on prefix and determine the maximum number
- name: Filter VMs based on prefix and determine the maximum number
set_fact:
max_existing_vm_number: "{{ (all_vms_info.virtual_machines | selectattr('guest_name', 'match', vm_name_prefix ~ '\\d+$') | map(attribute='guest_name') | map('regex_search', '\\d+$') | map('int') | list + [0]) | max }}"
Using a set_fact
task, this section extracts the maximum number from the names of any existing VMs that match the specified prefix. This allows for sequential naming when creating new VMs.
5. Create VMs starting from the next available number
- name: Create VMs starting from the next available number
community.vmware.vmware_guest:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ vcenter_validate_certs }}"
name: "{{ vm_name }}_{{ item + start_number }}"
datacenter: "{{ vcenter_datacenter }}"
folder: "/{{ vcenter_destination_folder }}"
template: "{{ templates }}"
resource_pool: "{{ resource_pool }}"
# Additional parameters for VM configuration
loop: "{{ range(num_vms) }}"
This section creates multiple VMs with custom specifications using the community.vmware.vmware_guest
module and sequential naming based on the start_number
. Replace variables like templates
, resource_pool
, etc., with valid values according to your environment.
Running the Playbook
To run this playbook, save it as a YAML file (e.g., create-vms.yml
) and execute the following command:
ansible-playbook create-vms.yml
Here is the full playbook :
---
- name: Create multiple VMs with sequential naming
hosts: localhost
gather_facts: false
vars_files:
- vars_multiple.yml
tasks:
- name: Create a folder for VMs in vCenter
community.vmware.vcenter_folder:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ vcenter_validate_certs }}"
datacenter: "{{ vcenter_datacenter }}"
folder_name: "{{ vcenter_destination_folder }}"
folder_type: vm
state: present
- name: List all VMs in the vCenter
community.vmware.vmware_vm_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ vcenter_validate_certs }}"
register: all_vms_info
- name: Filter VMs based on prefix and determine the maximum number
set_fact:
max_existing_vm_number: "{{ (all_vms_info.virtual_machines | selectattr('guest_name', 'match', vm_name_prefix ~ '\\d+$') | map(attribute='guest_name') | map('regex_search', '\\d+$') | map('int') | list + [0]) | max }}"
- name: Increment max_existing_vm_number safely
set_fact:
start_number: "{{ (max_existing_vm_number | int) + 1 }}"
- name: Create VMs starting from the next available number
community.vmware.vmware_guest:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ vcenter_validate_certs }}"
datacenter: "{{ vcenter_datacenter }}"
folder: "{{ vcenter_destination_folder }}"
template: "{{ vm_template }}"
name: "{{ vm_name_prefix }}{{ '%d' | format(item + start_number | int) }}"
state: "{{ vm_state }}"
guest_id: "{{ vm_guest_id }}"
cluster: "{{ vcenter_cluster }}"
customization:
hostname: "{{ vm_name_prefix }}{{ '%d' | format(item + start_number | int) }}"
hardware:
memory_mb: "{{ vm_hw_ram_mb }}"
num_cpus: "{{ vm_hw_cpu_n }}"
scsi: "{{ vm_hw_scsi }}"
hotadd_cpu: "{{ hot_add_cpu | default('True') }}"
hotadd_memory: "{{ hot_add_memory | default('True') }}"
networks:
- name: "{{ vm_net_name }}"
device_type: "{{ vm_net_type }}"
type: dhcp
loop: "{{ range(0, vms_count) | list }}"
loop_control:
index_var: item
Content of the file vars_multiple.yml :
---
vcenter_hostname: <your vCenter hostname or IP address>
vcenter_username: <your vCenter username>
vcenter_password: <your vCenter password>
vcenter_validate_certs: True # Set to False if you don't have SSL certificates
vcenter_datacenter: <your datacenter name>
vm_template: "Template VM" # Replace with the actual template VM name
vms_count: 5 # Number of VMs to create
vm_name_prefix: "VM-" # Prefix for VM names
vm_net_name: "VM Network" # Name of the network to attach the VMs to
vm_hw_ram_mb: 2048 # Memory size in MB for new VMs
vm_hw_cpu_n: 2 # Number of CPUs for new VMs
vcenter_destination_folder: "VMs" # Folder where the created VMs will be placed in vCenter
vm_state: present # Initial state of the created VMs (absent or present)
vm_guest_id: <your Guest ID> # Replace with the actual Guest ID for new VMs
vcenter_cluster: "Cluster" # Cluster where the created VMs will be placed in vCenter
hot_add_cpu: True # Whether to add CPU during VM creation if not specified in hardware configuration
hot_add_memory: False # Whether to add memory during VM creation if not specified in hardware configuration
Note: Make sure to replace the placeholder values with actual values from your environment before running the Ansible playbook.
As with any automation, testing in a non-production environment is crucial before rolling out to production, ensuring that the playbook performs as expected in your specific environment.