This post details how to carry out a NetApp ONTAP Automated non-disruptive upgrade (ANDU) using Ansible.
Intro
If your organization has a high number of ONTAP clusters, keeping these up-to-date and compliant can turn out to be a considerable task. Using automation and Ansible in particular can help reduce costs associated with managing such infrastructure.
ONTAP upgrade using Ansible
The following playbook can be invoked by Jenkins thus negating the need for storage administrators to carry out the ONTAP upgrade process manually. The playbook leverages the ansible module na_ontap_software_update from the netapp.ontap collection.
Tasks
The playbook below has three tasks. Two of these display the ONTAP version pre- and post- upgrade and the final one carries out the actual software upgrade.
ONTAP gather version
The gather tasks use na_ontap_rest_info to retrieve the ontap version:
  - name: run ONTAP gather version pre-update
    na_ontap_rest_info:
      hostname: "{{ lookup('env', 'ClusterName') }}"
      username: "{{ lookup('env', 'ontap_admin_usr') }}"
      password: "{{ lookup('env', 'ontap_admin_pwd') }}"
      use_rest: always
      https: true
      validate_certs: false
      gather_subset:
        - cluster_node_info
      fields:
        - 'version'
    register: cluster_node_info
  - debug:
      var: >- 
        cluster_node_info.ontap_info['cluster/nodes'].records
          | map(attribute='version.full') | listexample output from this task
TASK [debug] *******************************************************************
task path: /var/lib/jenkins/workspace/Infra-NetApp_ONTAP_Upgrade/ONTAP_software_update.yml:20
ok: [localhost] => {
    "cluster_node_info.ontap_info['cluster/nodes'].records\n  | map(attribute='version.full') | list": [
        "NetApp Release 9.12.1P4: Tue Jun 06 20:41:34 UTC 2023",
        "NetApp Release 9.12.1P4: Tue Jun 06 20:41:34 UTC 2023"
    ]
}ONTAP software update
This is the task that carries out the actual NDU where
- package_url is defined in Jenkins and has the following syntax: https://httpserver.domain.com/ontap/9131_q_image.tgz
- package_version is also defined in Jenkins and for this release has the value of 9.13.1
- download_only – allows downloading images to nodes without actually updating the software. The default value will be “false” if the parameter is not specified:
- Select “true” to copy the software image to the nodes only
- Select “false” to carry out the upgrade of both nodes
 
- timeout is 30min if not specified therefore the ansible task will fail/timeout in 30min while a NDU takes less than an hour even though the estimate is nearly 2 hours
  - name: "ONTAP software update on {{ lookup('env', 'ClusterName') }}"
    netapp.ontap.na_ontap_software_update:
      state: present
      package_url: "{{ lookup('env', 'ontap_package_url') }}"
      package_version: "{{ lookup('env', 'ontap_package_version') }}"
      ignore_validation_warning: true
      download_only: "{{ lookup('env', 'ontap_package_download_only') }}"
      hostname: "{{ lookup('env', 'ClusterName') }}"
      username: "{{ lookup('env', 'ontap_admin_usr') }}"
      password: "{{ lookup('env', 'ontap_admin_pwd') }}"
      stabilize_minutes: 10
      https: true
      validate_certs: false
      timeout: 7200Full Playbook code
---
- hosts: localhost
  collections:
    - netapp.ontap
  tasks:
  - name: run ONTAP gather version pre-update
    na_ontap_rest_info:
      hostname: "{{ lookup('env', 'ClusterName') }}"
      username: "{{ lookup('env', 'ontap_admin_usr') }}"
      password: "{{ lookup('env', 'ontap_admin_pwd') }}"
      use_rest: always
      https: true
      validate_certs: false
      gather_subset:
        - cluster_node_info
      fields:
        - 'version'
    register: cluster_node_info
  - debug:
      var: >- 
        cluster_node_info.ontap_info['cluster/nodes'].records
          | map(attribute='version.full') | list
  - name: "ONTAP software update on {{ lookup('env', 'ClusterName') }}"
    netapp.ontap.na_ontap_software_update:
      state: present
      package_url: "{{ lookup('env', 'ontap_package_url') }}"
      package_version: "{{ lookup('env', 'ontap_package_version') }}"
      ignore_validation_warning: true
      download_only: "{{ lookup('env', 'ontap_package_download_only') }}"
      hostname: "{{ lookup('env', 'ClusterName') }}"
      username: "{{ lookup('env', 'ontap_admin_usr') }}"
      password: "{{ lookup('env', 'ontap_admin_pwd') }}"
      stabilize_minutes: 10
      https: true
      validate_certs: false
      timeout: 7200
  - name: run ONTAP gather version post-update
    na_ontap_rest_info:
      hostname: "{{ lookup('env', 'ClusterName') }}"
      username: "{{ lookup('env', 'ontap_admin_usr') }}"
      password: "{{ lookup('env', 'ontap_admin_pwd') }}"
      use_rest: always
      https: true
      validate_certs: false
      gather_subset:
        - cluster_node_info
      fields:
        - 'version'
    register: cluster_node_info
  - debug:
      var: >- 
        cluster_node_info.ontap_info['cluster/nodes'].records
          | map(attribute='version.full') | listLink to source on GitHub
Ansible/ONTAP_software_update.yml at main · ukcloudgh/Ansible (github.com)
