So the Ansible virt module doesn’t have a clone option and the creation of guests is a little limited. Because of this we have to use the shell or command modules and try to make them idempotent. This is a simple example and the dictionary can be expanded to a lot more customization. There is a way to use libvirt as a dynamic inventory and set group and host vars on guests, but I’ll cover that in a different post.

So we do a few checks to make sure the disk isn’t already in the directory and another check to make sure the VM isn’t already created. The dictionary is in the referenced vars_file:

playbook:

---
- name: create VMs
  hosts: kvm
  become: true
  vars_files:
    - vms.yml

  tasks:
    - name: get VM disks
      command: "ls {{ vm_location }}"
      register: disks
      changed_when: "disks.rc != 0"

    - name: create disk
      command: >
               virt-builder --format qcow2 centos-7.4
               -o {{ vm_location}}/{{ item.key }}.{{ item.value.file_type }}
               --root-password password:{{ root_pass }}               
      when: item.key not in disks.stdout
      with_dict: "{{ guests }}"

    - name: get list of VMs
      virt:
        command: "list_vms"
      register: vms

    - name: create vm
      command: >
                virt-install --import --name {{ item.key }}
                --memory {{ item.value.mem }} --vcpus {{ item.value.cpus }}
                --disk {{ vm_location }}/{{ item.key }}.{{ item.value.file_type }}
                --noautoconsole --os-variant {{ item.value.os_type }}                
      when: item.key not in vms.list_vms
      with_dict: "{{ guests }}"

    - name: start vm
      virt:
        name: "{{ item.key }}"
        state: running
      with_dict: "{{ guests }}"

vars file:

---
vm_location: "/data/VMs"
root_pass: "password"

guests:
  test:
    mem: 512
    cpus: 1
    os_type: rhel7
    file_type: qcow2
  test2:
    mem: 512
    cpus: 1
    os_type: rhel7
    file_type: qcow2

Obviously you wouldn’t put the password in plain text, you’d either use ansible-vault, a vars prompt, or a survey in tower.

And here’s our output. I had already created a system called test so it skips over to give us idempotence.

KVM