Skip to main content

vCenter - Linux Templates

To deploy multiple VMs with different hostnames and IP addresses while utilizing the customization capabilities provided by the vmware_guest module in Ansible, you can use VMware's customization specifications. This approach allows for more advanced customization options, such as setting the domain, hostname, and network settings directly within the playbook. Below is an example of how to modify the playbook to use VMware's customization feature for deploying 3 VMs with distinct configurations:

Step

Inventory

1:

To Updatecreate a separate inventory file with all the Playbookvariables withused Customizationin Specificationsthe

You'provided playbook, you'll need to defineorganize these variables in a customizationstructured specway. forAnsible eachinventory VM, whichfiles can be includedin directlyINI or YAML format, but for complex configurations like this, YAML is more suitable due to its support for hierarchical data.

Below is an example of how to create an Ansible inventory file in theYAML loop.format Here's(inventory.yml) howthat defines all the updatedvariables playbookrequired couldby look:your playbook. This example demonstrates setting up variables for deploying three VMs, but you can adjust the quantities and details as needed:

all:
  vars:
    vcenter_hostname: vcenter.example.com
    vcenter_username: admin@vsphere.local
    vcenter_password: securepassword
    vcenter_datacenter: DC1
    vcenter_folder: /DC1/vm/ansible_managed_vms
    vcenter_cluster: Cluster1
    vm_template: CentOS_Template
    vm_network: VM_Network
    vm_netmask: 255.255.255.0
    vm_gateway: 192.168.1.1
    dns01: 8.8.8.8
    dns02: 8.8.4.4
    nios_provider:
      host: infoblox.example.com
      username: infoblox_user
      password: infoblox_password

  hosts:
    vm01:
      vm_name: vm01
      vm_ip: 192.168.1.101
      vm_ram: 2048
      vm_cores: 2
      vm_sockets: 1
      vm_notes: "VM01 Notes"
      vm_agency: "Agency1"
      vm_application: "Application1"
      vm_role: "Role1"
      vm_env: "Development"
      vm_buildcode: "Build01"
      vm_lifecycle: "Lifecycle1"
      vm_contact: "Contact1"

    vm02:
      vm_name: vm02
      vm_ip: 192.168.1.102
      vm_ram: 4096
      vm_cores: 4
      vm_sockets: 2
      vm_notes: "VM02 Notes"
      vm_agency: "Agency2"
      vm_application: "Application2"
      vm_role: "Role2"
      vm_env: "Testing"
      vm_buildcode: "Build02"
      vm_lifecycle: "Lifecycle2"
      vm_contact: "Contact2"

    vm03:
      vm_name: vm03
      vm_ip: 192.168.1.103
      vm_ram: 8192
      vm_cores: 4
      vm_sockets: 2
      vm_notes: "VM03 Notes"
      vm_agency: "Agency3"
      vm_application: "Application3"
      vm_role: "Role3"
      vm_env: "Production"
      vm_buildcode: "Build03"
      vm_lifecycle: "Lifecycle3"
      vm_contact: "Contact3"

Adjusting the Inventory

  • Hosts and Variables: The example above assumes you are deploying three VMs (vm01, vm02, and vm03). Each VM has its set of variables defined under hosts. You can add more VMs or adjust the existing definitions as needed.

  • Global Variables: Variables that are common across all VMs are defined under all: vars. This includes vCenter connection details, network configuration, and Infoblox provider details. These can be overridden at the host level if necessary.

  • Customization: Tailor the inventory to match your environment's specifics, including vCenter details, template names, network settings, and VM specifications.

This approach allows you to manage your infrastructure as code, making deployments repeatable and reducing the likelihood of human error.

Playbook: deploy_vms.yml

---
- name: Deploy multiple LinuxMultiple VMs from a template with customization on vCenter
  hosts: localhostall
  gather_facts: nofalse

  tasks:
    - name: Setting Facts
      set_fact:
        vm_guest_name: "{{ vm_name | upper }}"
        vm_hostname: "{{ vm_name | lower }}"

    - name: Deploy or Clone VMsLinux fromVM
      template with customization
      community.vmware.vmware_guest:
        hostname: '"{{ vcenter_hostname }}'"
        username: '"{{ vcenter_uservcenter_username }}'"
        password: '"{{ vcenter_passvcenter_password }}'"
        validate_certs: no
        datacenter: '"{{ datacenter_namevcenter_datacenter }}'"
        folder: '"{{ vm_foldervcenter_folder }}'"
        name: "{{ item.vm_namevm_guest_name }}"
        cluster: "{{ vcenter_cluster }}"
        state: poweredon
        template: '"{{ vm_template }}'"
        state:annotation: poweredon
        disk:
          - size_gb: '"{{ item.disk_size_gb | default(disk_size_gb)vm_notes }}'
            type: thin
            datastore: '{{ datastore_name }}'"
        hardware:
          memory_mb: '"{{ item.vm_memory_mb | default(vm_memory_mb)vm_ram }}'"
          num_cpus: '"{{ item.vm_cpus | default(vm_cpus)vm_cores }}'"
          num_cpu_cores_per_socket: "{{ vm_sockets }}"
        networks:
          - name: '"{{ network_namevm_network }}'"
            device_type:ip: vmxnet3"{{ vm_ip }}"
            netmask: "{{ vm_netmask }}"
            gateway: "{{ vm_gateway }}"
        wait_for_ip_address: yes
        wait_for_customization: yes
        cdrom:
          type: none
        customization:
          hostname: "{{ item.vm_namevm_hostname }}"
          domain: '{{"example.com"
          vm_domaintimezone: }}'"America/New_York"
          ipsettings:dns_servers:
            ip:- "{{ item.vm_ipdns01 }}"
            subnet_mask: '{{ vm_netmask }}'
            gateway: '{{ vm_gateway }}'
            dns_servers:- "{{ item.vm_dns_servers | default(vm_dns_servers)dns02 }}"
      wait_for_customization: yes
      delegate_to: localhost
      loop:register: vmcreate


    - name: Add Custom Attributes to the VM
      vmware_guest_custom_attributes:
        hostname: "{{ vmsvcenter_hostname }}"
        vars:username: vcenter_hostname:"{{ 'vcenter.example.com'vcenter_username vcenter_user:}}"
        'your-username'password: vcenter_pass:"{{ 'your-password'vcenter_password datacenter_name:}}"
        'your-datacenter'validate_certs: vm_folder:no
        '/your-vm-folder'name: vm_template:"{{ 'your-linux-template'vm_guest_name disk_size_gb:}}"
        20 # Default disk size
    datastore_name: 'your-datastore'
    vm_memory_mb: 2048 # Default memory
    vm_cpus: 2 # Default CPU count
    network_name: 'VM Network'
    vm_domain: 'example.com'
    vm_netmask: '255.255.255.0'
    vm_gateway: '192.168.1.1'
    vm_dns_servers:attributes:
          - name: Department
            value: "{{ vm_agency | default('8.8.8.8'') }}"
          - name: Application
            value: "{{ vm_application | default('8.8.4.4'') vms:}}"
          - vm_name:name: Role
            value: "{{ vm_role | default('linux-vm-01'') vm_ip: '192.168.1.101'}}"
          - vm_name:name: Environment
            value: "{{ vm_env | default('linux-vm-02'') vm_ip: '192.168.1.102'}}"
          - vm_name:name: Automation
            value: "Baseline"
          - name: buildcode
            value: "{{ vm_buildcode | default('linux-vm-03'') vm_ip:}}"
          - name: lifecycle
            value: "{{ vm_lifecycle | default('192.168.1.103'') }}"
          - name: Contact
            value: "{{ vm_contact | default('') }}"

Explanation of Each Task

  1. InSetting thisFacts: playbook, each VM's customization is defined withinConverts the VM name to uppercase and lowercase versions for different uses, such as the display name in vCenter (customizationvm_guest_name) parameterand the internal hostname of the VM (vm_hostname).

  2. Deploy or Clone Linux VM: Uses the vmware_guest module.module to either deploy a new VM or clone an existing one from a template specified in the inventory. This task includes settingsconfiguring forthe hostname,VM's domain,hardware IP,specifications, subnetnetwork mask,settings, gateway,and customization specifications like the hostname and DNS servers.settings. TheIt waits for the IP address to be assigned and customization to complete before proceeding.

  3. Update VM IP in Infoblox: If using Infoblox for IP address management, this optional task updates Infoblox with the new VM's IP address. This task only runs if the wait_for_customization: yesnios_provider optionvariable ensuresis defined, indicating that Infoblox integration is desired.

  4. Include VM Storage Configuration: Includes an additional Ansible waitstask untilfile, VMware'svmstorage.yml, customizationwhich processcan completescontain beforetasks movingfor on.configuring VM storage. This step is conditional on the definition of vm_storage, allowing for optional storage configuration.

  5. Add Custom Attributes to the VM: Adds custom attributes to the newly created VM in vCenter. These attributes can include metadata such as the agency, application, role, and environment the VM is associated with. This helps in organizing and managing VMs based on these metadata.

Step 2: Running the Playbook

To run the updatedthis playbook, use the samefollowing commandcommand, asensuring before:you specify the inventory file:

ansible-playbook -i hosts.iniinventory.yml deploy_vm.deploy_vms.yml

This command deploystells 3Ansible VMs,to deploy VMs as configured in inventory.yml, applying the settings and customizations specified for each with its customized hostname and network configuration as defined in the vms list.VM.

Notes:

  • Template Requirements: The template you use must be prepared for customization. For Linux VMs, ensure VMware Tools is installed, and the Perl scripting language is available for the customization scripts to run.
  • Customization Script: VMware's customization mechanism uses a script that runs on the first boot. If the customization does not apply, troubleshooting may involve checking that VMware Tools is correctly installed and that the template is properly prepared for cloning and customization.
  • Ansible and VMware Versions: Ensure you are using recent versions of Ansible and the VMware modules, as improvements and bug fixes are regularly added.

This method leverages VMware's powerful customization engine, allowing for a wide range of customization options beyond what was demonstrated here.