POSTS
Ansible Hyper-V Deployment
- 4 minutes read - 784 wordsIntroduction
Ansible is one of the most popular configuration management tools. I’ve written about Ansible Testing previously. Ansible consists of a number of modules that provide atomic operations such as installing a package or creating an AWS EC2 virtual machine. These modules are basically Python programs that adhere to an Ansible protocol. On Windows, modules are instead written in PowerShell. The presence of the PowerShell interpreter is one prerequisite for Ansible provisioning on Windows machines. In this article, we examine how a Windows module is created and provide some modules we can use to work with Hyper-V.
Background
Hyper-V is a Microsoft hypervisor built into some versions of Windows. You may be more familiar with VirtualBox and VMWare Fusion which are consumer-friendly hypervisors. A hypervisor allows a host to share its resources with guest virtual machines. To enable high availability, Failover Clustering manages failover from one Hyper-V host to another. I wanted to be able to create Hyper-V-hosted VMs, configure failover, and create checkpoints using Ansible.
Investigation
I initially wanted to use Terraform for my automation but encountered problems using with an existing provider 1. Instead, I started with an existing Ansible-based solution. This project has existing modules to create a guest VM and configure networking, but that was only part of what I needed.
Failover
An Ansible Windows module consists of two files. First, we need some Python file containing some metadata about the module.
# win_failoverclusters_vm.py
DOCUMENTATION = '''
---
module: win_failoverclusters_vm
description:
- Adds a VM to Failover Clusters manager
options:
name:
description:
- Name of VM
required: true
# MORE OPTIONS TRUNCATED
'''
ANSIBLE_METADATA = {
'status': ['preview'],
'supported_by': 'community',
'metadata_version': '1.1'
}
We also need a PowerShell file that applies the module. It is
common practice to respond to a state
parameter passed to the
module, but you could have a simple module that only creates
and does not delete, for example. That’s what’s presented below.
For the full module, see
GitHub.
# win_failoverclusters_vm.ps1
#Requires -Module Ansible.ModuleUtils.Legacy
$params = Parse-Args $args;
$name = Get-Attr -obj $params -name name -failifempty $true
Add-ClusterVirtualMachineRole -VirtualMachine '$name' -Name '$name'
This script imports a library PowerShell module, parses arguments passed from the caller, and executes Add-ClusterVirtualMachineRole which adds a VM to Failover Cluster Manager. Some assumptions are made here including that the Hyper-V host has already been added to a Failover Cluster Group, and that Ansible is running against the target VM’s Hyper-V host.
Usage
Once we have created the module, we can use it by adding it to
the library
folder of either an Ansible role or in the
playbooks directory. I created a role that uses the
win_hyperv_guest
and win_failoverclusters_vm
modules to
both create a new VM and add enable failover for that VM. You
can see an example of usage in
tsailiming/ansible-hyperv
and find the modules I added in my fork
jamiely/ansible-hyperv,
which include modules to:
- modify Hyper-V guest network adapters
- get information about VMs added to a failover cluster
- create and delete Hyper-V guest VM checkpoints
Example Role
With these components, one of the interesting things we can do is take checkpoints of a set of VMs without prior knowledge about their host. This is useful if we do not have a dynamic inventory script or plugin.
Here’s an example role that will create checkpoints for a group defined in inventory.
# defaults/main.yml
---
# a list of VMs
# for example:
# hyperv_checkpoint_vms: "{{ groups['my_vms'] }}"
hyperv_checkpoint_vms: []
# The failover cluster name/fqdn
hyperv_checkpoint_cluster: ""
# tasks/main.yml
---
# First query the failover cluster to get facts about
# all of the VMs we're interested in.
- name: |
Figure out which Hyper-V host the VM is on
by querying Failover Cluster Manager
win_failoverclusters_vm_facts:
name: "{{ hyperv_checkpoint_vms }}"
cluster: "{{ hyperv_checkpoint_cluster }}"
register: vm_facts
when: hyperv_checkpoint_vms | length > 0
# Now create a checkpoint for each VM.
- name: Create a checkpoint for each VM
win_hyperv_checkpoint:
name: "{{ hyperv_checkpoint_name }}"
state: present
vm_name: "{{ item['Name'] }}"
hostserver: "{{ item['owner_node_name'] }}"
loop: "{{ vm_facts['vms'] | default([]) }}"
Conclusion
Creating a custom Ansible Windows module is very straightforward, consisting of a Python definition and PowerShell implementation. Ansible is a great way to unify configuration management across both Linux and Windows. Hyper-V and Failover Clustering have PowerShell modules that we can use via Ansible to automate configuration. We can combine these modules to create powerful and reusable Ansible roles. If you are in need of automating Hyper-V, check out the Ansible Windows modules I’ve created at jamiely/ansible-hyperv.
Notes
-
When I looked into how Terraform communicates with the Hyper-V host, it seemed to use masterzen/winrm, which does not support Windows Domain users, and instead requires local users, which I wanted to avoid. ↩︎