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.