Create VMs on KVM with Ansible
2017-10-04
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_filevars_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 }}"
---- 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
---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.