Centos VM Creation on Nutanix Using AnsibleINTRODUCTION
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.
.fusion-syntax-highlighter-33 > .CodeMirror, .fusion-syntax-highlighter-33 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-33 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-33 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }Copy to ClipboardSyntax Highlighter- 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.
.fusion-syntax-highlighter-34 > .CodeMirror, .fusion-syntax-highlighter-34 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-34 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-34 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }Copy to ClipboardSyntax Highlighter- 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.
.fusion-syntax-highlighter-35 > .CodeMirror, .fusion-syntax-highlighter-35 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-35 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-35 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }Copy to ClipboardSyntax Highlighter- 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.
.fusion-syntax-highlighter-36 > .CodeMirror, .fusion-syntax-highlighter-36 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-36 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-36 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }Copy to ClipboardSyntax Highlighter- 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.
.fusion-syntax-highlighter-37 > .CodeMirror, .fusion-syntax-highlighter-37 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-37 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-37 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }Copy to ClipboardSyntax Highlighter- 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).
.fusion-syntax-highlighter-38 > .CodeMirror, .fusion-syntax-highlighter-38 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-38 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-38 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }Copy to ClipboardSyntax Highlighter- 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: vmname: 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: Truename: 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.
.fusion-syntax-highlighter-39 > .CodeMirror, .fusion-syntax-highlighter-39 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-39 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-39 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }Copy to ClipboardSyntax Highlighterclusters: "{{ 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 SCloud 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.
Nutanix- * On Linked-In
