Centos VM Creation on Nutanix Using Ansible
INTRODUCTION
Nutanix Prism is an end-to-end consumer-grade management solution for virtualized datacenter environments. Prism manages the entire stack from the storage and compute infrastructure all the way up to virtual machines (VMs).
Here, we'll discuss how to create a CentOS VM on Nutanix using Ansible playbook. Ansible is a high-level automation engine that automates cloud provisioning, configuration management, application deployment.
PREREQUISITES
- Nutanix Prism login credentials
- Nutanix cluster URL, cluster name, subnet name and disk image name
ANSIBLE ON NUTANIX VM CREATION
Ansible roles are sets of Ansible defaults, files, tasks, templates, variables, and other Ansible components that work together. 'nutanix_vm_provisioner' is a basic Ansible role to provision VMs on a Nutanix AHV using APIv3.
Required variables
- api_version: # add API version, it's best to use v3, if available
- cluster_url: # IP address where you would normally log into PRISM
- prism_user: # An account with permissions to provision on the cluster
- prism_password: # The password to your account
- cluster_name: # Name of the cluster to provision against
- subnet_name: # Name of the Subnet to add VMs to
- image_name: # Name of the disk image or ISO to use
- vm_defs: # The list of dicts that define the VMs to be created
A single role 'nutanix_vm' is required for the VM creation.
'nutanix_vm' role deals with the creation of a VM with the provided subnet, cluster and the OS image by authenticating with a session cookie for logging into the prism. The required variables are to be placed in 'defaults' folder. 'tasks' for the role is shown step-by-step in the next page.
STEP 1
*(nutanix_vm): *shows how the authentication to the prism is done by creating a session cookie.
- name: Auth to the cluster
uri:
url: "{{ api_url_v3 }}/clusters/list"
body:
kind: cluster
sort_order: ASCENDING
offset: 0
length: 10
sort_attribute: ''
method: POST
validate_certs: no
force_basic_auth: yes
body_format: json
user: "{{ prism_user }}"
password: "{{ prism_password }}"
status_code: 200
return_content: yes
register: login
ignore_errors: yes
- name: Debug | Print Auth Cookie
debug:
var: login.set_cookie
when: global_debug
- name: Set fact for session cookie
set_fact:
session_cookie: "{{ login.set_cookie}}"
register: cookie
- debug: var=cookie.failed
STEP 2
*(nutanix_vm): *shows how to get the cluster lists and uuids to use.
- name: Get clusters list
uri:
url: "{{ api_url_v3 }}/clusters/list"
body:
kind: cluster
sort_order: ASCENDING
offset: 0
length: 10
sort_attribute: ''
method: POST
validate_certs: no
body_format: json
status_code: 200
headers:
Cookie: "{{ session_cookie }}"
register: json_cluster_result
ignore_errors: yes
- name: Stash the Cluster UUIDs
set_fact:
cluster_uuids: "{{ cluster_uuids|default([]) + [{'name': item.spec.name, 'uuid': item.metada.uuid} ] }}"
with_items: "{{ json_clusters_result.json.entities }}"
no_log: True
- name: Debug|Printcluster name/UUIDs
debug:
var: cluster_uuids
when: global_debug
STEP 3
*(nutanix_vm): *shows how to get the subnet lists and uuids to use.
- name: Get Subnet List
uri:
url: "{{ api_url_v3}}/subnets/list"
body:
length: 100
offset: 0
filter: ""
method: POST
validate_certs: no
body_format: json
status_code: 200
headers:
Cookie: "{{ session_cookie }}"
register: json_images_result
ignore_errors: yes
- debug: var=json_images_result.json.entities.0.status
- debug: var=json_images_result.json.entities.1.status
- debug: var=json_images_result.json.entities.2.status
- name: Stash the subnet UUIDs
set_fact:
subnet_uuids: "{{ subnet_uuids|default([]) + [ {'name': item.spec.name, 'uuid': item.metadata.uuid } ] }}"
with_items: "{{ json_images_result.json.entities }}"
no_log: True
- name: Debug | Print Subnet name/UUIDs
debug:
var: subnet_uuids
when: global_debug
STEP 4
*(nutanix_vm): *shows how to get the images list and the uuids to use.
- name: Get Images list
uri:
url: "{{ api_url_v3 }}/images/list"
body:
length: 100
offset: 0
filter: ""
method: POST
validate_certs: no
body_format: json
status_code: 200
headers:
Cookie: "{{ session_cookie }}"
register: json_images_result
ignore_errors: yes
- name: Stash the image UUIDs
set_fact:
image_uuids: "{{ image_uuids | default([]) + [ {'name': item.spec.name, 'uuid': item.metadata.uuid } ] }}"
with_items: "{{ json_images_result.json.entities }}"
no_log: True
- name: Debug | Print image name/UUIDs
debug:
var: image_uuids
when: global_debug
STEP 5
*(nutanix_vm): *shows how to define and use the uuids for the VM creation.
- name: Define Cluster UUID to use from name
set_fact:
cluster_uuid: "{{ item['uuid'] }}"
when: "item['name'] == cluster_name"
loop: "{{ cluster_uuids }}"
register: cluster_uuid
- debug: var=cluster_uuid
- name: Define Image UUID to use from name
set_fact:
image_uuid: "{{ item['uuid'] }}"
when: "item['name'] == image_name"
loop: "{{ image_uuids }}"
register: image_uuid
- debug: var= image_uuid
- name: Define Subnet UUID to use from name
set_fact:
subnet_uuid: "{{ item['uuid'] }}"
when: "item['name'] == subnet_name"
loop: "{{ subnet_uuids }}"
register: subnet_uuid
- debug: var= subnet_uuid
STEP 6
*(nutanix_vm): *shows how to provision a new VM (uses CentOS image here).
- name: Copy python with owner and permissions
template:
src: nutanix.py.j2
dest: /tmp/nutanix.py
owner: root
group: root
mode: u=rwx,g=rx,o=r
- name: Copy yaml with owner and permissions
template:
src: nutanix.yml.j2
dest: /tmp/nutanix.yml
owner: root
group: root
mode: u=rwx,g=rx,o=r
- name: run python script
shell: /tmp/nutanix.py --host {{ vm_name }}
register: output
- debug: var=output.stdout
- name: Debug | Print VM definitions
debug:
var: vm_defs
when: global_debug
- name: Create fact with VM template contents
set_fact:
vm_body: "{{ lookup('template', 'vm-body.yml.j2') | from_yaml }}"
loop: "{{ vm_defs }}"
register: templates
loop_control:
loop_var: vm
- name: Debug | Print Template lookup result
debug:
msg: "{{ item.ansible_facts.vm_body }}"
when: global_debug
with_items: "{{ templates.results }}"
- name: Create a VM from a template
uri:
url: "{{ api_url_v3 }}/vms"
body:
"{{ template.ansible_facts.vm_body }}"
method: POST
validate_certs: no
body_format: json
headers:
Cookie: "{{ session_cookie }}"
status_code: 202
register: json_create_result
with_items: "{{ templates.results }}"
loop_control:
loop_var: template
when: 'output.stdout_lines == [
"{}"
]'
- name: Debug | Print VM creation result
debug: msg="{{json_create_result}}"
- name: Debug | Display VM creation response
debug:
msg: "{{ item.json.metadata.uuid }}"
when: 'output.stdout_lines == [
"{}"
]'
with_items: "{{ json_create_result.results }}"
- name: Register the created vm uuid's for future use
set_fact:
_uuids: "{{ item.json.metadata.uuid }}"
with_items: "{{ json_create_result.results }}"
register: vm_uuids
when: 'output.stdout_lines == [
"{}"
]'
no_log: True
- name: Debug | Print VM uuids
debug:
var: vm_uuids
when: 'output.stdout_lines == [
"{}"
]'
'nutanix.py' is a Python script which generates an inventory that Ansible can understand by making API requests to one or more Nutanix clusters. This is placed in the templates folder. You can get a clear idea on this by referring h**ttps://github.com/mattkeeler/ansible-nutanix-inventory
STEP 7
*(nutanix_vm): *template *'nutanix.yml.j2' *is given below.
clusters:
"{{ cluster_name }}":
address: "{{ cluster_url }}"
port: "{{ cluster_port }}"
username: "{{ prism_user }}"
password: "{{ prism_password }}"
verify_ssl: False
caching:
cache_max_age: 300
cache_path: '/tmp/'
cache_base_name: 'ansible-nutanix.cache'
CONCLUSION
Ansible is a simple and efficient tool for automating infrastructure (IaC – Infrastructure as Code). In this tutorial, I used Ansible role *'**nutanix_vm_provisioner' *for the creation of CentOS VM on Nutanix. Ansible can also help in tasks like app deployments, configuration management and wokflow orchestration.
REFERENCES
- https:// galaxy.ansible.com/mbach04/nutanix_vm_provisioner
- https://github.com/mattkeeler/ansible-nutanix-inventory
About The Author

Sreedevi J S
Cloud Dev-Ops Engineer | Cloud Control
Cloud DevOps Engineer with more than three years of experience in supporting, automating, and optimizing deployments to hybrid cloud platforms using DevOps processes, tools, CI/CD, containers and Kubernetes in both Production and Development environments.
