ONTAP: Use Ansible to Provision NAS Storage

A great way to gain understanding of Ansible (or any language for that matter) is seeing code examples. The Ansible documentation links below also have code examples.

Table of Contents:
  1. References
  2. nas_playbook_v1
    1. What it does
    2. Vars File
    3. Playbook
    4. Running the Playbook
  3. nas_playook_v2
    1. What it does
    2. Vars file
    3. Playbook
    4. Running the Playbook
  4. Using Roles
    1. Folder Structure
    2. provision_nas role: main.yml files
      1. meta > main.yml file
      2. tasks > main.yml file
      3. vars > main.yml file
    3. Example Playbook Using the provision_nas Role
    4. Running the Playbook

1. References
2. nas_playbook_v1

2.1. What it does

Create Volume
Create CIFS share

2.2. Vars File

nas_vars.yml

netapp_hostname: cluster1.yourdomain.com
netapp_username: admin
vserver: svm1_cluster1
volname: vol1
aggr_name: cluster1_01_SSD_1
size: 10

2.3. Playbook

nas_playbook_v1.yml 

---
- hosts: localhost
  gather_facts: false
  name: Provision NAS Storage
  collections:
    - netapp.ontap

  module_defaults:
    group/netapp.ontap.netapp_ontap:
      hostname: "{{ netapp_hostname }}"
      username: "{{ netapp_username }}"
      password: "{{ netapp_password }}"
      vserver: "{{ vserver }}"
      https: true
      validate_certs: false
      use_rest: auto
  vars_prompt:
    - name: "netapp_password"
      prompt: "Enter the NetApp Admin Password"
      private: true
      confirm: true
  vars_files:
    - ./nas_vars.yml

  tasks:
    - name: Create Volume
      na_ontap_volume:
        state: present
        name: "{{ volname }}"
        aggregate_name: "{{ aggr_name }}"
        size: "{{ size }}"
        size_unit: gb
        junction_path: "/{{ volname }}"
        space_guarantee: "none"
        volume_security_style: mixed
    - name: Create CIFS Share
      na_ontap_cifs:
        state: present
        share_name: "{{ volname }}"
        path: "/{{ volname }}"

2.4. Running the Playbook

ansible@ansible:~$ ansible-playbook nas_playbook_v1.yml


3. nas_playbook_v2

3.1. What it does

Create Export Policy
Setup Export Policy Rules
Create Volume NFS
Create Volume CIFS
Create CIFS Share

3.2. Vars file

nas_vars.yml

netapp_hostname: cluster1.yourdomain.com
netapp_username: admin
vserver: svm1_cluster1
aggr_name: cluster1_01_SSD_1
volname: vol4
protocols: 
  - cifs
size: 10
policy_name: uservols
client_matches:
  - match: 192.168.0.0/24
    ro: sys
    rw: sys
    security: sys
  - match: 100.100.0.0/24
    ro: sys
    rw: sys
    security: sys


3.3. Playbook

nas_playbook_v2.yml 

---
- hosts: localhost
  gather_facts: false
  name: Provision NAS Storage
  collections:
    - netapp.ontap

  module_defaults:
    group/netapp.ontap.netapp_ontap:
      hostname: "{{ netapp_hostname }}"
      username: "{{ netapp_username }}"
      password: "{{ netapp_password }}"
      vserver: "{{ vserver }}"
      https: true
      validate_certs: false
      use_rest: auto
  vars_prompt:
    - name: "netapp_password"
      prompt: "Enter the NetApp Admin Password"
      private: true
      confirm: true
  vars_files:
    - ./nas_vars.yml

  tasks:
    - name: Create Export Policy
      na_ontap_export_policy:
        state: present
        name: "{{ policy_name }}"
      when: "'nfs' in protocols"

    - name: Set Up Export Policy Rules
      na_ontap_export_policy_rule:
        state: present
        policy_name: "{{ policy_name }}"
        client_match: "{{ items.match }}"
        ro_rule: items.ro
        rw_rule: items.rw
        super_user_security: items.security
      when: "'nfs' in protocols"
      with_items: "{{ client_matches }}"

    - name: Create Volume NFS
      na_ontap_volume:
        state: present
        name: "{{ volname }}"
        aggregate_name: "{{ aggr_name }}"
        size: "{{ size }}"
        size_unit: gb
        policy: "{{ policy_name }}"
        junction_path: "/{{ volname }}"
        space_guarantee: "none"
        volume_security_style: mixed
      when: "'nfs' in protocols"

    - name: Create Volume CIFS
      na_ontap_volume:
        state: present
        name: "{{ volname }}"
        aggregate_name: "{{ aggr_name }}"
        size: "{{ size }}"
        size_unit: gb
        junction_path: "/{{ volname }}"
        space_guarantee: "none"
        volume_security_style: mixed
      when: "'cifs' in protocols"

    - name: Create CIFS Share
      na_ontap_cifs:
        state: present
        share_name: "{{ volname }}"
        path: "/{{ volname }}"
      when: "'cifs' in protocols"


3.4. Running the Playbook

ansible@ansible:~$ ansible-playbook nas_playbook_v2.yml


4. Using Roles

For reuse-ability, using roles is the recommended way of doing things:

Ansible - Roles (tutorialspoint.com) 

"Roles provide a framework for fully independent, or interdependent collections of variables, tasks, files, templates, and modules.

"In Ansible, the role is the primary mechanism for breaking a playbook into multiple files. This simplifies writing complex playbooks, and it makes them easier to reuse. The breaking of playbook allows you to logically break the playbook into reusable components."

4.1. Folder Structure

In the roles folder, we create our role folder (our role) called - provision_nas - and 3 folders inside that folder - meta, tasks, vars. Each of the 3 sub-folders has a main.yml file.

  • roles
    • provision_nas
      • meta
        • main.yml
      • tasks
        • main.yml
      • vars
        • main.yml
4.2. provision_nas role: main.yml files

4.2.1. meta > main.yml file


collections:
  - netapp.ontap

4.2.2. tasks > main.yml file


---
- name: Create Export Policy
  na_ontap_export_policy:
    state: present
    hostname: "{{ netapp_hostname }}"
    username: "{{ netapp_username }}"
    password: "{{ netapp_password }}"
    vserver: "{{ vserver }}"
    https: true
    validate_certs: false
    use_rest: auto
    name: "{{ policy_name }}"
  when: "'nfs' in protocols"

- name: Set Up Export Policy Rules
  na_ontap_export_policy_rule:
    state: present
    hostname: "{{ netapp_hostname }}"
    username: "{{ netapp_username }}"
    password: "{{ netapp_password }}"
    vserver: "{{ vserver }}"
    https: true
    validate_certs: false
    use_rest: auto
    policy_name: "{{ policy_name }}"
    client_match: "{{ item.match }}"
    ro_rule: "{{ item.ro }}"
    rw_rule: "{{ item.rw }}"
    super_user_security: "{{ item.security }}"
  when: "'nfs' in protocols"
  with_items: "{{ client_matches }}"

- name: Create Volume NFS
  na_ontap_volume:
    state: present
    hostname: "{{ netapp_hostname }}"
    username: "{{ netapp_username }}"
    password: "{{ netapp_password }}"
    vserver: "{{ vserver }}"
    https: true
    validate_certs: false
    use_rest: auto
    name: "{{ volname }}"
    aggregate_name: "{{ aggr_name }}"
    size: "{{ size }}"
    size_unit: gb
    policy: "{{ policy_name }}"
    junction_path: "/{{ volname }}"
    space_guarantee: "none"
    volume_security_style: mixed
  when: "'nfs' in protocols"

- name: Create Volume CIFS
  na_ontap_volume:
    state: present
    hostname: "{{ netapp_hostname }}"
    username: "{{ netapp_username }}"
    password: "{{ netapp_password }}"
    vserver: "{{ vserver }}"
    https: true
    validate_certs: false
    use_rest: auto
    name: "{{ volname }}"
    aggregate_name: "{{ aggr_name }}"
    size: "{{ size }}"
    size_unit: gb
    junction_path: "/{{ volname }}"
    space_guarantee: "none"
    volume_security_style: mixed
  when: "'cifs' in protocols"

- name: Create CIFS Share
  na_ontap_cifs:
    state: present
    hostname: "{{ netapp_hostname }}"
    username: "{{ netapp_username }}"
    password: "{{ netapp_password }}"
    vserver: "{{ vserver }}"
    https: true
    validate_certs: false
    use_rest: auto
    share_name: "{{ volname }}"
    path: "/{{ volname }}"
  when: "'cifs' in protocols"

4.2.3 vars > main.yml file


netapp_hostname: cluster1.yourcompany.com
netapp_username: admin
vserver: svm1_cluster1
aggr_name: cluster1_01_SSD_1
protocols: 
 - cifs
 - nfs
size: 10
policy_name: uservols
client_matches:
  - match: 192.168.0.0/24
    ro: sys
    rw: sys
    security: sys

4.3. Example Playbook Using the provision_nas Role

In our playbook - provision_nas.yml - we simply "call" the role with some inputs. In the example below we use the provision_nas role twice.

provision_nas.yml


- hosts: localhost
  gather_facts: false

  vars_prompt:
    - name: "netapp_password"
      prompt: "Enter the NetApp Admin Password"
      private: true
      confirm: true
  
  roles:
    - role: provision_nas
      volname: vol6
      size: 10
      protocols:
        cifs
    - role: provision_nas
      volname: vol7
      size: 10
      protocols:
        cifs
        nfs
      client_matches:
        - match: 192.168.0.0/24
          ro: sys
          rw: sys
          security: sys

4.4. Running the Playbook

ansible@ansible:~$ ansible-playbook provision_nas.yml

Comments