Init: mediaserver

This commit is contained in:
2023-02-08 12:13:28 +01:00
parent 848bc9739c
commit f7c23d4ba9
31914 changed files with 6175775 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
---
language: python
python: "2.7"
# Use the new container infrastructure
sudo: false
# Install ansible
addons:
apt:
packages:
- python-pip
install:
# Install ansible
- pip install ansible
# Check ansible version
- ansible --version
# Create ansible.cfg with correct roles_path
- printf '[defaults]\nroles_path=../' >ansible.cfg
script:
# Basic role syntax check
- ansible-playbook tests/test.yml -i tests/inventory --syntax-check
notifications:
webhooks: https://galaxy.ansible.com/api/v1/notifications/

View File

@@ -0,0 +1,149 @@
nar_santricity_common
=====================
Discover NetApp E-Series storage systems and configures SANtricity Web Services Proxy.
The following variables will be added to the runtime host inventory.
current_eseries_api_url: # Web Services REST API URL
current_eseries_api_username: # Web Services REST API username
current_eseries_api_password: # Web Services REST API password
current_eseries_ssid: # Arbitrary string for the proxy to represent the storage system.
current_eseries_validate_certs: # Indicates whether SSL certificates should be verified.
current_eseries_api_is_proxy: # Indicates whether Web Services REST API is running on a proxy.
Requirements
------------
- NetApp E-Series E2800 platform or newer or NetApp E-Series SANtricity Web Services Proxy configured for older E-Series storage systems.
Tested Ansible Versions
-----------------------
- Ansible 5.x (ansible-core 2.12)
Example Playbook
----------------
- hosts: eseries_storage_systems
gather_facts: false
collection:
- netapp_eseries.santricity
tasks:
- name: Configure SANtricity Web Services and discover storage systems
import_role:
name: nar_santricity_common
Example Inventory Host file using discovery with proxy
------------------------------------------------------
eseries_proxy_api_url: https://192.168.1.100:8443/devmgr/v2/
eseries_proxy_api_password: admin_password
eseries_subnet: 192.168.1.0/24 # This should only be defined at the group level once when utilizing Web Services Proxy and should be broad enough to include all systems being added to proxy instance.
eseries_system_serial: 012345678901
eseries_system_password: admin_password
eseries_validate_certs: false
(...)
Example Inventory Host file using discovery without proxy
---------------------------------------------------------
**Note that while eseries_management_interfaces or eseries_system_api_url are optional, including at least one of them will prevent the discovery mechanism from being used when the system can be reached from their information.
eseries_subnet: 192.168.1.0/24
eseries_system_serial: 012345678901
eseries_system_password: admin_password
eseries_validate_certs: false
(...)
Example Inventory Host file without using discovery (Embedded Web Services)
---------------------------------------------------------------------------
eseries_system_api_url: https://192.168.1.200:8443/devmgr/v2/
eseries_system_password: admin_password
eseries_validate_certs: false
(...)
Example Inventory Host file without using discovery (Proxy Web Services - system must have already been added to the proxy)
------------------------------------------------------------------------
eseries_proxy_ssid: storage_ssid
eseries_proxy_api_url: https://192.168.2.200:8443/devmgr/v2/
eseries_proxy_api_password: admin_password
(...)
Notes
-----
Use SANtricity Web Services Proxy to avoid the need to discover the storage systems each time nar_santricity_common is executed. The first time nar_santricity_common is executed will add the storage systems the proxy so that they can be recalled without the need to search the subnet each subsequent execution.
The na_santricity_proxy_systems module is used to add storage systems to the proxy but required a complete list of desired systems since it will ensure that only the systems provided will remain on the proxy. As a result any system that is not included will be removed from the proxy.
Role Variables
--------------
eseries_subnet: # Network subnet to search for the storage system specified in CIDR form. Example: 192.168.1.0/24
# Note: eseries_subnet should only be defined once at the group level when utilizing the Web Services Proxy.
eseries_template_api_url: # Template for the web services api url. Default: https://0.0.0.0:8443/devmgr/v2/
eseries_prefer_embedded: false # Overrides the default behavior of using Web Services Proxy when eseries_proxy_api_url is defined. This will only effect storage systems that have Embedded Web Services.
eseries_validate_certs: true # Indicates Whether SSL certificates should be verified. Used for both embedded and proxy. Choices: true, false
# Storage system specific variables
eseries_proxy_ssid: # Arbitrary string for the proxy to represent the storage system. eseries_system_serial will be used when not defined.
eseries_system_serial: # Storage system serial number. (This is located on a label at the top-left towards the front on the device)
eseries_system_addresses: # Storage system management IP addresses. Only required when eseries_system_serial or eseries_system_api_url are not defined. When not specified, addresses will be populated with eseries_management_interfaces controller addresses.
eseries_system_api_url: # Url for the storage system's for embedded web services rest api. Example: https://192.168.10.100/devmgr/v2
eseries_system_username: admin # Username for the storage system's for embedded web services rest api
eseries_system_password: # Password for the storage system's for embedded web services rest api and when the admin password has not been set eseries_system_password will be used to set it.
eseries_system_tags: # Meta tags to associate with storage system when added to the proxy.
# Storage system management interface information
Note: eseries_management_interfaces will be used when eseries_system_serial, eseries_system_api_url, or eseries_system_addresses are not defined.
eseries_management_interfaces: # Subset of the eseries_management_interface variable found in the nar_santricity_management role
controller_a:
- address: # Controller A port 1's IP address
- address: # Controller A port 2's IP address
controller_b:
- address: # Controller B port 1's IP address
- address: # Controller B port 2's IP address
# Web Services Proxy specific variable
Note: eseries_proxy_* variables are required to discover storage systems prior to SANtricity OS version 11.60.2.
eseries_proxy_api_url: # Url for the storage system's for proxy web services rest api. Example: https://192.168.10.100/devmgr/v2
eseries_proxy_api_username: # Username for the storage system's for proxy web services rest api (Default: admin).
eseries_proxy_api_password: # Password for the storage system's for proxy web services rest api and when the admin password has
# not been set eseries_proxy_api_password will be used to set it.
eseries_proxy_api_old_password: # Previous proxy admin password. This is used to change the current admin password by setting this
# variable to the current proxy password and eseries_proxy_api_password to the new password.
eseries_proxy_monitor_password: # Proxy password for the monitor username
eseries_proxy_security_password: # Proxy password for the security username
eseries_proxy_storage_password: # Proxy password for the monitor username
eseries_proxy_support_password: # Proxy password for the support username
eseries_proxy_accept_certifications: # Force automatic acceptance of all storage system's certificate
eseries_proxy_default_system_tags: # Default meta tags to associate with all storage systems
eseries_proxy_default_password: # Default password to associate with all storage systems. This is overridden by eseries_system_password.
eseries_proxy_client_certificate_common_certificates: # List of common proxy client certificate file paths. These files will be appended to each client certificate list.
eseries_proxy_client_certificate_certificates: # List of proxy client certificate file paths
eseries_proxy_server_certificate_common_certificates: # List of common proxy server certificates. These files will be appended to each controller's server certificate list.
eseries_proxy_server_certificate_common_passphrase: # Common passphrase for decrypting PEM (PKCS8) private key.
eseries_proxy_server_certificate_certificates: # List of proxy server certificates. Leave blank to use self-signed certificate.
eseries_proxy_server_certificate_passphrase: # Passphrase for decrypting PEM (PKCS8) private key.
# LDAP configuration defaults
eseries_proxy_ldap_state: # Whether LDAP should be configured for the proxy`
eseries_proxy_ldap_identifier: # The user attributes that should be considered for the group to role mapping
eseries_proxy_ldap_user_attribute: # Attribute used to the provided username during authentication.
eseries_proxy_ldap_bind_username: # User account that will be used for querying the LDAP server.
eseries_proxy_ldap_bind_password: # Password for the bind user account
eseries_proxy_ldap_server: # LDAP server URL.
eseries_proxy_ldap_search_base: # Search base used for find user's group membership
eseries_proxy_ldap_role_mappings: # Dictionary of user groups, each containing the list of access roles.
# Role choices: storage.admin - allows users full read/writes access to storage objects and operations.
# storage.monitor - allows users read-only access to storage objects and operations.
# storage.admin - allows users access to hardware, diagnostic information, major event logs,
# and other critical support-related functionality, but not the sorage configuration.
# security.admin - allows users access to authentication/authorization configuration, as
# well as the audit log configuration, adn certification management.
License
-------
BSD-3-Clause
Author Information
------------------
Nathan Swartz (@ndswartz)

View File

@@ -0,0 +1,45 @@
---
#eseries_subnet: # Network subnet to search for the storage system specified in CIDR form. Example: 192.168.1.0/24
eseries_subnet_default_prefix: 22 # Default subnet prefix to use when no other prefix is supplied. Default: 22
eseries_template_api_url: https://0.0.0.0:8443/devmgr/v2/ # Template for the web services api url. Default: https://0.0.0.0:8443/devmgr/v2/
#eseries_validate_certs: # Whether SSL certificates should be verified. Used for both embedded and proxy. Choices: true, false
eseries_prefer_embedded: false # Overrides the default behavior of using Web Services Proxy when eseries_proxy_api_url is defined. This will only
# effect storage systems that have Embedded Web Services.
# Storage system specific variables
# ---------------------------------
#eseries_proxy_ssid: # Arbitrary string for the proxy to represent the storage system. eseries_system_serial will be used when not defined.
#eseries_system_serial: # Storage system serial number (This is located on a label at the top-left towards the front on the device)
#eseries_system_addresses: # Storage system management IP addresses. Only required when eseries_system_serial or eseries_system_api_url are not
# defined. When not specified, addresses will be populated with eseries_management_interfaces controller addresses
#eseries_system_api_url: # Url for the storage system's for embedded web services rest api. Example: https://192.168.10.100/devmgr/v2
eseries_system_username: admin # Username for the storage system's for embedded web services rest api
#eseries_system_password: # Password for the storage system's for embedded web services rest api and when the admin password has not been set
# eseries_system_password will be used to set it.
#eseries_system_tags: # Meta tags to associate with storage system when added to the proxy.
# Storage system management interface information
# -----------------------------------------------
# Note: eseries_management_interfaces will be used when eseries_system_serial, eseries_system_api_url, or eseries_system_addresses are not defined.
#eseries_management_interfaces: # Subset of the eseries_management_interface variable found in the nar_santricity_management role
# controller_a:
# - address: # Controller A port 1's IP address
# - address: # Controller A port 2's IP address
# controller_b:
# - address: # Controller B port 1's IP address
# - address: # Controller B port 2's IP address
# Web Services Proxy specific variable
# ------------------------------------
# Note: eseries_proxy_* variables are required to discover storage systems prior to SANtricity OS version 11.60.2.
#eseries_proxy_api_url: # Url for the storage system's for proxy web services rest api. Example: https://192.168.10.100/devmgr/v2
eseries_proxy_api_username: admin # Username for the storage system's for proxy web services rest api.
#eseries_proxy_api_password: # Password for the storage system's for proxy web services rest api and when the admin password has not been set
# eseries_proxy_api_password will be used to set it.
#eseries_proxy_monitor_password: # Proxy password for the monitor username
#eseries_proxy_security_password: # Proxy password for the security username
#eseries_proxy_storage_password: # Proxy password for the monitor username
#eseries_proxy_support_password: # Proxy password for the support username
#eseries_proxy_accept_certifications: # Force automatic acceptance of all storage system's certificate
#eseries_proxy_default_system_tags: # Default meta tags to associate with all storage systems
#eseries_proxy_default_password: # Default password to associate with all storage systems. This is overridden by eseries_system_password.

View File

@@ -0,0 +1,13 @@
galaxy_info:
author: Nathan Swartz (@ndswartz)
description: Discover NetApp E-Series storage systems and configures SANtricity Web Services Proxy.
company: NetApp, Inc
license: BSD-3-Clause
platforms: []
min_ansible_version: 2.13
galaxy_tags:
- netapp
- eseries
- storage
dependencies: []

View File

@@ -0,0 +1,38 @@
- name: Collect storage system facts
uri:
url: |-
{%- if eseries_prefer_embedded == True -%}
{{- eseries_system_api_url | default(eseries_proxy_api_url) | regex_replace('v2/?$', 'utils/about') -}}
{%- else -%}
{{- eseries_proxy_api_url | default(eseries_system_api_url) | regex_replace('v2/?$', 'utils/about') -}}
{%- endif -%}
headers:
Content-Type: "application/json"
Accept: "application/json"
validate_certs: false
connection: local
register: about
failed_when: false
when: eseries_proxy_api_url is defined or eseries_system_api_url is defined
tags: always
- name: Determine whether SANtricity Web Services REST API is proxy and information
set_fact:
current_eseries_api_is_proxy: "{{ about['json']['runningAsProxy'] | default(False) }}"
tags: always
- name: Collect Web Services information from either proxy or embedded with a preference for embedded.
include_tasks: collect_facts/prefer_embedded.yml
when: (current_eseries_api_is_proxy == True and eseries_prefer_embedded == True) or current_eseries_api_is_proxy == False
tags: always
- name: Collect Web Services information from proxy.
include_tasks: collect_facts/prefer_proxy.yml
when: current_eseries_api_is_proxy == True and current_eseries_api_url is not defined
tags: always
- name: Check whether current_eseries_api_url is defined
fail:
msg: "Could not determine or discover storage system contact information!"
when: current_eseries_api_url is not defined or current_eseries_ssid is not defined
tags: always

View File

@@ -0,0 +1,64 @@
- name: Check whether eseries_system_serial is defined.
ansible.builtin.fail:
msg: "Unable to search for storage system! The variable eseries_system_serial must be defined (See SANtricity README, section Storage System Credentials)."
when: eseries_system_serial is not defined
- name: Determine associated management interface subnet information.
ansible.builtin.set_fact:
eseries_subnets: |-
{%- set subnets = [] %}
{%- if eseries_subnet is defined -%}
{%- if subnets.append(eseries_subnet) -%}{%- endif -%}
{%- endif -%}
{%- set interfaces = eseries_management_interfaces["controller_a"] | default([]) + eseries_management_interfaces["controller_b"] | default([]) -%}
{%- for interface in interfaces if interface["address"] is defined -%}
{%- if subnets.append(interface["address"] ~ "/" ~ interface["subnet_mask"] | default(eseries_management_interfaces["subnet_mask"] | default(eseries_management_subnet_mask | default(eseries_subnet_default_prefix)))) -%}{%- endif -%}
{%- endfor -%}
{{- subnets | ansible.utils.ipaddr('network/prefix') | unique -}}
- name: Ensure there is at least one subnet to search for storage systems.
ansible.builtin.fail:
msg: "There is not enough management information to search for the storage system(s)! (See SANtricity README, section Storage System Credentials)"
when: eseries_subnets | length == 0
- name: Discover storage systems from all subnet ranges
netapp_eseries.santricity.na_santricity_discover:
proxy_url: "{{ item['value']['proxy_url'] }}"
proxy_username: "{{ item['value']['proxy_username'] }}"
proxy_password: "{{ item['value']['proxy_password'] }}"
proxy_validate_certs: "{{ item['value']['proxy_validate_certs'] }}"
subnet_mask: "{{ item['key'] }}"
prefer_embedded: "{{ item['value']['prefer_embedded'] }}"
run_once: true
connection: local
register: discovered_systems
loop: "{{ subnets | dict2items }}"
tags: always
vars:
subnets: |-
{#- Build a dictionary subnet searches and any proxies should they be available #}
{%- set systems = {} %}
{%- for array in ansible_play_hosts_all %}
{%- for eseries_subnet in hostvars[array]["eseries_subnets"] | default([]) -%}
{%- if "eseries_proxy_api_url" in (hostvars[array].keys() | list) -%}
{%- if systems.update({eseries_subnet: {
"proxy_url": hostvars[array]["eseries_proxy_api_url"] | default(omit),
"proxy_username": hostvars[array]["eseries_proxy_api_username"] | default("admin"),
"proxy_password": hostvars[array]["eseries_proxy_api_password"] | default(omit),
"prefer_embedded": hostvars[array]["eseries_prefer_embedded"] | default(omit),
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit)}}) %}
{%- endif %}
{%- else -%}
{%- if systems.update({eseries_subnet: {
"proxy_url": hostvars[array]["eseries_proxy_api_url"] | default(omit),
"proxy_username": hostvars[array]["eseries_proxy_api_username"] | default(omit),
"proxy_password": hostvars[array]["eseries_proxy_api_password"] | default(omit),
"prefer_embedded": hostvars[array]["eseries_prefer_embedded"] | default(omit),
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit)}}) %}
{%- endif %}
{%- endif -%}
{%- endfor %}
{%- endfor %}
{{ systems }}

View File

@@ -0,0 +1,150 @@
# Test whether eseries_system_api_url is a valid storage system web services api.
- name: Validate the storage system embedded Web Services REST API supplied in eseries_system_api_url.
block:
- name: Determine management url based on eseries_system_api_url.
set_fact:
eseries_api_url_list: "{{ [eseries_system_api_url] }}"
- name: Check for valid storage system Web Services API url.
include_tasks: collect_facts/validate_system_api_url.yml
when: (current_eseries_api_url is not defined or current_eseries_ssid is not defined) and eseries_system_api_url is defined
tags: always
# Test when a valid storage system web services api can be extrapolated from eseries_management_interfaces
- name: Validate the storage system embedded Web Services REST API derived from eseries_management_interfaces.
block:
- name: Determine management interface IP addresses
set_fact:
eseries_api_url_list: |-
{%- set addresses = [] -%}
{%- set url_info = eseries_template_api_url | urlsplit %}
{%- for address in [eseries_management_interfaces["controller_a"][0]["address"] | default(""),
eseries_management_interfaces["controller_a"][1]["address"] | default(""),
eseries_management_interfaces["controller_b"][0]["address"] | default(""),
eseries_management_interfaces["controller_b"][1]["address"] | default("")] -%}
{%- if address != "" and addresses.append([url_info["scheme"], "://", address, ":", url_info["port"], url_info["path"]] | join("")) %}{%- endif -%}
{%- endfor %}
{{ addresses }}
- name: Check for valid storage system Web Services API url.
include_tasks: collect_facts/validate_system_api_url.yml
when: (current_eseries_api_url is not defined or current_eseries_ssid is not defined) and eseries_management_interfaces is defined
tags: always
# If proxy is available get information from there and avoid the discovery process.
- name: Attempt to retrieve the storage system from Web Services Proxy.
block:
- name: Determine existing storage systems in Web Services Proxy.
uri:
url: "{{ eseries_proxy_api_url | regex_replace('v2/?$', 'v2/storage-systems') }}"
headers:
Content-Type: "application/json"
Accept: "application/json"
url_username: "{{ eseries_proxy_api_username | default('admin') }}"
url_password: "{{ eseries_proxy_api_password }}"
validate_certs: false
connection: local
register: proxy_systems
- name: Determine associated management interface IP addresses.
set_fact:
eseries_system_addresses: |-
{%- set addresses = [] %}
{%- set url_info = eseries_template_api_url | urlsplit %}
{%- for address in [eseries_management_interfaces["controller_a"][0]["address"] | default(""),
eseries_management_interfaces["controller_a"][1]["address"] | default(""),
eseries_management_interfaces["controller_b"][0]["address"] | default(""),
eseries_management_interfaces["controller_b"][1]["address"] | default("")] %}
{%- if address != "" and addresses.append(address) -%}{%- endif %}
{%- endfor %}
{{ addresses }}
when: eseries_management_interfaces is defined
- name: Determine storage system SSID based on storage system serial number or associated IP addresses.
set_fact:
eseries_api_url_list: |-
{#- Determine any system that either has the expected serial number or a management ip address -#}
{%- set ssids = [] -%}
{%- set addresses = [] -%}
{#- Search discovered storage systems -#}
{%- set url_info = eseries_template_api_url | urlsplit %}
{%- for system in proxy_systems["json"] -%}
{#- Check for serial number match -#}
{%- if eseries_system_serial is defined and system["chassisSerialNumber"] == eseries_system_serial -%}
{%- if ssids.append(system["id"]) -%}{%- endif -%}
{%- for address in system["managementPaths"] -%}
{%- if addresses.append([url_info["scheme"], "://", address, ":", url_info["port"], url_info["path"]] | join("")) %}{%- endif -%}
{%- endfor -%}
{%- elif eseries_proxy_ssid is defined and eseries_proxy_ssid == system["id"] -%}
{%- if ssids.append(system["id"]) -%}{%- endif -%}
{%- for address in system["managementPaths"] -%}
{%- if addresses.append([url_info["scheme"], "://", address, ":", url_info["port"], url_info["path"]] | join("")) %}{%- endif -%}
{%- endfor -%}
{%- elif eseries_system_addresses is defined and eseries_system_addresses | length > 0 -%}
{%- for address in eseries_system_addresses -%}
{%- if address in system["managementPaths"] -%}
{%- if ssids.append(system["id"]) -%}{%- endif -%}
{%- for address in system["managementPaths"] -%}
{%- if addresses.append([url_info["scheme"], "://", address, ":", url_info["port"], url_info["path"]] | join("")) %}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{%- if ssids | unique | length == 1 -%}
{{- addresses -}}
{%- else -%}[]{%- endif -%}
- name: Check for valid storage system Web Services API url.
include_tasks: collect_facts/validate_system_api_url.yml
when: current_eseries_api_is_proxy == True and (current_eseries_api_url is not defined or current_eseries_ssid is not defined)
tags: always
# Try discovering eseries_system_api_url if known eseries_system_api_url is not valid
- name: Attempt to discover storage system.
block:
- name: Search subnet for storage system.
include_tasks: collect_facts/discovery.yml
when: discovered_systems is not defined
- name: Determine storage system Web Services information
set_fact:
current_eseries_api_info: |-
{%- set info = {} -%}
{%- if eseries_system_serial is defined -%}
{%- set serial = eseries_system_serial | string -%}
{%- for result in discovered_systems["results"] if result["systems_found"][serial] is defined -%}
{%- if info.update(result["systems_found"][serial]) %}{%- endif -%}
{%- endfor %}
{%- endif -%}
{{ info }}
- name: Check whether storage system was discovered.
fail:
msg: "Storage system failed to be discovered! Serial [{{ eseries_system_serial }}]."
when: current_eseries_api_info == {}
- name: Set storage systems Web Services URL information
set_fact:
current_eseries_api_is_proxy: "{{ current_eseries_api_info['proxy_required'] }}"
current_eseries_api_url: "{{ current_eseries_api_info['api_urls'][0] }}"
current_eseries_ssid: |-
{%- if current_eseries_api_info["proxy_required"] == False -%}
1
{%- elif current_eseries_api_info["proxy_required"] == True and current_eseries_api_info['proxy_ssid'] != "" -%}
{{- current_eseries_api_info['proxy_ssid'] -}}
{%- else -%}
{{- eseries_system_serial -}}
{%- endif -%}
current_eseries_api_username: "{% if current_eseries_api_info['proxy_required'] %}{{ eseries_proxy_api_username | default('admin') }}{% else %}{{ eseries_system_username | default('admin') }}{% endif %}"
current_eseries_api_password: "{% if current_eseries_api_info['proxy_required'] %}{{ eseries_proxy_api_password }}{% else %}{{ eseries_system_password }}{% endif %}"
current_eseries_validate_certs: "{{ eseries_validate_certs | default(omit) }}"
no_log: true
when: current_eseries_api_url is not defined or current_eseries_ssid is not defined
tags: always

View File

@@ -0,0 +1,107 @@
- name: Determine existing storage systems in Web Services Proxy.
uri:
url: "{{ eseries_proxy_api_url | regex_replace('v2/?$', 'v2/storage-systems') }}"
headers:
Content-Type: "application/json"
Accept: "application/json"
url_username: "{{ eseries_proxy_api_username | default('admin') }}"
url_password: "{{ eseries_proxy_api_password }}"
validate_certs: false
connection: local
register: proxy_systems
tags: always
- name: Determine associated management interface IP addresses.
set_fact:
eseries_system_addresses: |-
{%- set addresses = [] %}
{%- set url_info = eseries_template_api_url | urlsplit %}
{%- for address in [eseries_management_interfaces["controller_a"][0]["address"] | default(""),
eseries_management_interfaces["controller_a"][1]["address"] | default(""),
eseries_management_interfaces["controller_b"][0]["address"] | default(""),
eseries_management_interfaces["controller_b"][1]["address"] | default("")] %}
{%- if address != "" and addresses.append(address) -%}{%- endif %}
{%- endfor %}
{{ addresses }}
when: eseries_management_interfaces is defined
tags: always
- name: Determine storage system SSID based on storage system serial number or associated IP addresses.
set_fact:
eseries_ssid_list: |-
{#- Determine any system that either has the expected serial number or a management ip address -#}
{%- set ssids = [] -%}
{#- Search discovered storage systems -#}
{%- for system in proxy_systems["json"] -%}
{#- Check for serial number match -#}
{%- if eseries_system_serial is defined and system["chassisSerialNumber"] == eseries_system_serial -%}
{%- if ssids.append(system["id"]) -%}{%- endif -%}
{%- elif eseries_proxy_ssid is defined and eseries_proxy_ssid == system["id"] -%}
{%- if ssids.append(system["id"]) -%}{%- endif -%}
{%- elif eseries_system_addresses is defined and eseries_system_addresses | length > 0 -%}
{%- for address in eseries_system_addresses -%}
{%- if address in system["managementPaths"] -%}
{%- if ssids.append(system["id"]) -%}{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{{- ssids | unique -}}
tags: always
- name: Use the Web Services Proxy REST API
set_fact:
current_eseries_api_url: "{{ eseries_proxy_api_url }}"
current_eseries_ssid: "{{ eseries_ssid_list[0] }}"
current_eseries_api_username: "{{ eseries_proxy_api_username | default('admin') }}"
current_eseries_api_password: "{{ eseries_proxy_api_password }}"
current_eseries_validate_certs: "{{ eseries_validate_certs | default(omit) }}"
no_log: true
when: eseries_ssid_list | length == 1 and (eseries_proxy_ssid is not defined or eseries_proxy_ssid == eseries_ssid_list[0])
tags: always
- name: Search subnet for storage system.
block:
- name: Search subnet for storage system.
include_tasks: collect_facts/discovery.yml
when: discovered_systems is not defined
- name: Determine storage system Web Services information
set_fact:
current_eseries_api_info: |-
{%- set info = {} -%}
{%- if eseries_system_serial is defined -%}
{%- set serial = eseries_system_serial | string -%}
{%- for result in discovered_systems["results"] if result["systems_found"][serial] is defined -%}
{%- if info.update(result["systems_found"][serial]) %}{%- endif -%}
{%- endfor %}
{%- endif -%}
{{ info }}
- name: Check whether storage system was discovered.
fail:
msg: "Storage system failed to be discovered! Serial [{{ eseries_system_serial }}]."
when: current_eseries_api_info == {}
- name: Set storage systems Web Services URL information
set_fact:
current_eseries_api_is_proxy: "{{ current_eseries_api_info['proxy_required'] }}"
current_eseries_api_url: "{{ current_eseries_api_info['api_urls'][0] }}"
current_eseries_ssid: |-
{%- if eseries_proxy_ssid is defined -%}
{{- eseries_proxy_ssid -}}
{%- elif current_eseries_api_info["proxy_ssid"] != "" -%}
{{- current_eseries_api_info["proxy_ssid"] -}}
{%- else -%}
{{- eseries_system_serial -}}
{%- endif -%}
current_eseries_api_username: "{{ eseries_proxy_api_username | default('admin') }}"
current_eseries_api_password: "{{ eseries_proxy_api_password }}"
current_eseries_validate_certs: "{{ eseries_validate_certs | default(omit) }}"
no_log: true
when: current_eseries_api_url is not defined or current_eseries_ssid is not defined
tags: always

View File

@@ -0,0 +1,34 @@
- name: Validate storage system urls.
block:
- name: Collect storage system facts.
uri:
url: "{{ item | regex_replace('v2/?$', 'utils/about') }}"
headers:
Content-Type: "application/json"
Accept: "application/json"
validate_certs: false
ignore_errors: true
connection: local
register: about_results
loop: "{{ lookup('list', eseries_api_url_list) }}"
- name: Determine the first successful Web Services REST API url.
set_fact:
current_eseries_api_url: |-
{%- set valid_urls = [] %}
{%- for result in about_results["results"] if result["failed"] == false -%}
{%- if valid_urls.append(result['item']) %}{%- endif %}
{%- endfor %}
{{ valid_urls[0] | default("") }}
- name: Set Web Services REST API credentials.
set_fact:
current_eseries_api_is_proxy: False
current_eseries_ssid: "{{ current_eseries_ssid | default('1') }}"
current_eseries_api_username: "{{ eseries_system_username | default('admin') }}"
current_eseries_api_password: "{{ eseries_system_password }}"
current_eseries_validate_certs: "{{ eseries_validate_certs | default(omit) }}"
when: current_eseries_api_url != ""
no_log: true
when: eseries_api_url_list is defined and eseries_api_url_list | length > 0
tags: always

View File

@@ -0,0 +1,14 @@
- name: Configure SANtricity Web Services Proxy's passwords, certificates, and LDAP.
import_tasks: proxy_security.yml
run_once: true
- name: Build information for Web Services
import_tasks: build_info.yml
tags:
- always
- name: Configure SANtricity WebServices Proxy
import_tasks: proxy.yml
run_once: true
tags:
- always

View File

@@ -0,0 +1,49 @@
- name: Add storage systems to SANtricity Web Services Proxy
na_santricity_proxy_systems:
api_url: "{{ item['key'] }}"
api_username: "{{ item['value']['proxy_username'] }}"
api_password: "{{ item['value']['proxy_password'] }}"
validate_certs: "{{ item['value']['proxy_validate_certs'] | default(omit) }}"
accept_certificate: "{{ item['value']['proxy_accept_certifications'] | default(omit) }}"
subnet_mask: "{{ item['value']['proxy_subnet'] }}"
password: "{{ item['value']['proxy_default_password'] | default(omit) }}"
tags: "{{ item['value']['proxy_default_system_tags'] | default(omit) }}"
systems: "{{ item['value']['proxy_systems'] }}"
connection: local
loop: "{{ lookup('dict', proxy_systems_info, wantlist=True) }}"
no_log: true
vars:
proxy_systems_info: |-
{#- Build a dictionary of all inventoried proxies keyed by their api url #}
{%- set systems = {} %}
{%- for array in ansible_play_hosts_all %}
{%- if hostvars[array]["current_eseries_api_is_proxy"] %}
{%- set array_info = {} %}
{%- if "eseries_system_serial" in hostvars[array] or "eseries_system_addresses" in hostvars[array] %}
{%- if array_info.update({
"ssid": hostvars[array]["current_eseries_ssid"] | default(omit),
"password": hostvars[array]["eseries_system_password"] | default(omit),
"serial": hostvars[array]["eseries_system_serial"] | default(omit),
"addresses": hostvars[array]["eseries_system_addresses"] | default(omit),
"tags": hostvars[array]["eseries_system_tags"] | default(omit)}) %}
{%- endif %}
{%- endif %}
{%- if "eseries_proxy_api_url" in hostvars[array] and "eseries_proxy_api_password" in hostvars[array] %}
{%- if hostvars[array]["eseries_proxy_api_url"] in systems %}
{%- if systems[hostvars[array]["eseries_proxy_api_url"]]["proxy_systems"].append(array_info) %}{%- endif %}
{%- else %}
{%- if systems.update({hostvars[array]["eseries_proxy_api_url"]: {
"proxy_username": hostvars[array]["eseries_proxy_api_username"] | default("admin"),
"proxy_password": hostvars[array]["eseries_proxy_api_password"] | default(omit),
"proxy_subnet": hostvars[array]["eseries_subnet"] | default(omit),
"proxy_systems": [array_info],
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit),
"proxy_accept_certifications": hostvars[array]["eseries_proxy_accept_certifications"] | default(omit),
"proxy_default_system_tags": hostvars[array]["eseries_proxy_default_system_tags"] | default(omit),
"proxy_default_password": hostvars[array]["eseries_proxy_default_password"] | default(omit)}}) %}
{%- endif %}
{%- endif %}
{%- endif %}
{%- endif %}
{%- endfor %}
{{ systems }}

View File

@@ -0,0 +1,241 @@
- name: Ensure proxy admin password has been set
na_santricity_auth:
ssid: proxy
api_url: "{{ item['key'] }}"
api_username: "{{ item['value']['proxy_username'] }}"
api_password: "{{ item['value']['current_proxy_password'] }}"
validate_certs: "{{ item['value']['proxy_validate_certs'] }}"
user: admin
password: "{{ item['value']['proxy_password'] }}"
minimum_password_length: "{{ item['value']['proxy_minimum_password_length'] }}"
connection: local
loop: "{{ lookup('dict', proxy_admin, wantlist=True) }}"
no_log: true
vars:
proxy_admin: |-
{#- Build a dictionary of all inventoried proxies keyed by their api url #}
{%- set systems = {} %}
{%- for array in ansible_play_hosts_all %}
{%- if "eseries_proxy_api_url" in hostvars[array] and "eseries_proxy_api_password" in hostvars[array] %}
{%- if systems.update({hostvars[array]["eseries_proxy_api_url"]: {
"proxy_username": hostvars[array]["eseries_proxy_api_username"] | default('admin'),
"proxy_password": hostvars[array]["eseries_proxy_api_password"],
"current_proxy_password": hostvars[array]["eseries_proxy_api_old_password"] | default(hostvars[array]["eseries_proxy_api_password"]),
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit),
"proxy_minimum_password_length": hostvars[array]["eseries_proxy_minimum_password_length"] | default(omit)}}) %}
{%- endif %}
{%- endif %}
{%- endfor %}
{{ systems }}
tags:
- always
- name: Ensure proxy non-admin passwords have been set
na_santricity_auth:
ssid: proxy
api_url: "{{ item['value']['proxy_url'] }}"
api_username: "{{ item['value']['proxy_url_username'] }}"
api_password: "{{ item['value']['proxy_url_password'] }}"
validate_certs: "{{ item['value']['proxy_validate_certs'] }}"
user: "{{ item['value']['proxy_username'] }}"
password: "{{ item['value']['proxy_password'] }}"
connection: local
loop: "{{ lookup('dict', proxy_non_admin, wantlist=True) }}"
no_log: true
vars:
proxy_non_admin: |-
{#- Build a dictionary of all inventoried proxies keyed by their api url containing non-admin usernames/passwords #}
{%- set systems = {} %}
{%- for array in ansible_play_hosts_all %}
{%- if "eseries_proxy_api_url" in hostvars[array] and "eseries_proxy_api_password" in hostvars[array] and
(("eseries_proxy_monitor_password" in hostvars[array] and hostvars[array]["eseries_proxy_monitor_password"]) or
("eseries_proxy_security_password" in hostvars[array] and hostvars[array]["eseries_proxy_security_password"]) or
("eseries_proxy_storage_password" in hostvars[array] and hostvars[array]["eseries_proxy_storage_password"]) or
("eseries_proxy_support_password" in hostvars[array] and hostvars[array]["eseries_proxy_support_password"])) %}
{%- if "eseries_proxy_monitor_password" in hostvars[array] and hostvars[array]["eseries_proxy_monitor_password"] and
systems.update({[hostvars[array]["eseries_proxy_api_url"], 'monitor'] | join("-"): {
"proxy_url": hostvars[array]["eseries_proxy_api_url"],
"proxy_url_username": hostvars[array]["eseries_proxy_api_username"] | default('admin'),
"proxy_url_password": hostvars[array]["eseries_proxy_api_password"],
"proxy_username": 'monitor',
"proxy_password": hostvars[array]["eseries_proxy_monitor_password"],
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit)}}) %}
{%- endif %}
{%- if "eseries_proxy_security_password" in hostvars[array] and hostvars[array]["eseries_proxy_security_password"] and
systems.update({[hostvars[array]["eseries_proxy_api_url"], 'security'] | join("-"): {
"proxy_url": hostvars[array]["eseries_proxy_api_url"],
"proxy_url_username": hostvars[array]["eseries_proxy_api_username"] | default('admin'),
"proxy_url_password": hostvars[array]["eseries_proxy_api_password"],
"proxy_username": 'security',
"proxy_password": hostvars[array]["eseries_proxy_security_password"],
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit)}}) %}
{%- endif %}
{%- if "eseries_proxy_storage_password" in hostvars[array] and hostvars[array]["eseries_proxy_storage_password"] and
systems.update({[hostvars[array]["eseries_proxy_api_url"], 'storage'] | join("-"): {
"proxy_url": hostvars[array]["eseries_proxy_api_url"],
"proxy_url_username": hostvars[array]["eseries_proxy_api_username"] | default('admin'),
"proxy_url_password": hostvars[array]["eseries_proxy_api_password"],
"proxy_username": 'storage',
"proxy_password": hostvars[array]["eseries_proxy_storage_password"],
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit)}}) %}
{%- endif %}
{%- if "eseries_proxy_support_password" in hostvars[array] and hostvars[array]["eseries_proxy_support_password"] and
systems.update({[hostvars[array]["eseries_proxy_api_url"], 'support'] | join("-"): {
"proxy_url": hostvars[array]["eseries_proxy_api_url"],
"proxy_url_username": hostvars[array]["eseries_proxy_api_username"] | default('admin'),
"proxy_url_password": hostvars[array]["eseries_proxy_api_password"],
"proxy_username": 'support',
"proxy_password": hostvars[array]["eseries_proxy_support_password"],
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit)}}) %}
{%- endif %}
{%- endif %}
{%- endfor %}
{{ systems }}
- name: Ensure proxy client certificates are installed
na_santricity_client_certificate:
ssid: proxy
api_url: "{{ item['key'] }}"
api_username: "{{ item['value']['proxy_username'] }}"
api_password: "{{ item['value']['proxy_password'] }}"
validate_certs: "{{ item['value']['proxy_validate_certs'] }}"
certificates: "{{ item['value']['certificates'] }}"
connection: local
loop: "{{ lookup('dict', proxy_client_certificates, wantlist=True) }}"
when: item['value']['certificates'] | length > 0
no_log: true
vars:
proxy_client_certificates: |-
{#- Build a dictionary of all inventoried proxies keyed by their api url #}
{%- set systems = {} %}
{%- for array in ansible_play_hosts_all %}
{%- if "eseries_proxy_api_url" in hostvars[array] and "eseries_proxy_api_password" in hostvars[array] %}
{%- set certs = [] -%}
{#- Add common proxy client certificates -#}
{%- if "eseries_proxy_client_certificate_common_certificates" in (hostvars[array].keys() | list) -%}
{%- if hostvars[array]["eseries_proxy_client_certificate_common_certificates"] is string -%}
{%- if certs.append(hostvars[array]["eseries_proxy_client_certificate_common_certificates"]) -%}{%- endif -%}
{%- elif hostvars[array]["eseries_proxy_client_certificate_common_certificates"] is iterable -%}
{%- if certs.extend(hostvars[array]["eseries_proxy_client_certificate_common_certificates"]) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{#- Add proxy specific client certificates -#}
{%- if "eseries_proxy_client_certificate_certificates" in (hostvars[array].keys() | list) -%}
{%- if hostvars[array]["eseries_proxy_client_certificate_certificates"] is string -%}
{%- if hostvars[array]["eseries_proxy_client_certificate_certificates"] not in certs -%}
{%- if certs.append(hostvars[array]["eseries_proxy_client_certificate_certificates"]) -%}{%- endif -%}
{%- endif -%}
{%- elif hostvars[array]["eseries_proxy_client_certificate_certificates"] is iterable -%}
{%- for client_cert in hostvars[array]["eseries_proxy_client_certificate_certificates"] if client_cert not in certs -%}
{%- if certs.append(client_cert) -%}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endif -%}
{%- if systems.update({hostvars[array]["eseries_proxy_api_url"]: {
"proxy_username": hostvars[array]["eseries_proxy_api_username"] | default('admin'),
"proxy_password": hostvars[array]["eseries_proxy_api_password"],
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit),
"certificates": certs}}) %}
{%- endif %}
{%- endif %}
{%- endfor %}
{{ systems }}
- name: Ensure proxy server certificates are installed
na_santricity_server_certificate:
ssid: proxy
api_url: "{{ item['key'] }}"
api_username: "{{ item['value']['proxy_username'] }}"
api_password: "{{ item['value']['proxy_password'] }}"
validate_certs: "{{ item['value']['proxy_validate_certs'] }}"
certificates: "{{ item['value']['certificates'] }}"
passphrase: "{{ item['value']['passphrase'] }}"
connection: local
loop: "{{ lookup('dict', proxy_server_certificates, wantlist=True) }}"
when: item['value']['certificates'] | length > 0
no_log: true
vars:
proxy_server_certificates: |-
{#- Build a dictionary of all inventoried proxies keyed by their api url #}
{%- set systems = {} %}
{%- for array in ansible_play_hosts_all %}
{%- if "eseries_proxy_api_url" in hostvars[array] and "eseries_proxy_api_password" in hostvars[array] %}
{%- set certs = [] -%}
{#- Add common proxy server certificates -#}
{%- if "eseries_proxy_server_certificate_common_certificates" in (hostvars[array].keys() | list) -%}
{%- if hostvars[array]["eseries_proxy_server_certificate_common_certificates"] is string -%}
{%- if certs.append(hostvars[array]["eseries_proxy_server_certificate_common_certificates"]) -%}{%- endif -%}
{%- elif hostvars[array]["eseries_proxy_server_certificate_common_certificates"] is iterable -%}
{%- if certs.extend(hostvars[array]["eseries_proxy_server_certificate_common_certificates"]) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{#- Add proxy specific server certificates -#}
{%- if "eseries_proxy_server_certificate_certificates" in (hostvars[array].keys() | list) -%}
{%- if hostvars[array]["eseries_proxy_server_certificate_certificates"] is string -%}
{%- if hostvars[array]["eseries_proxy_server_certificate_certificates"] not in certs -%}
{%- if certs.append(hostvars[array]["eseries_proxy_server_certificate_certificates"]) -%}{%- endif -%}
{%- endif -%}
{%- elif hostvars[array]["eseries_proxy_server_certificate_certificates"] is iterable -%}
{%- for client_cert in hostvars[array]["eseries_proxy_server_certificate_certificates"] if client_cert not in certs -%}
{%- if certs.append(client_cert) -%}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endif -%}
{%- if systems.update({hostvars[array]["eseries_proxy_api_url"]: {
"proxy_username": hostvars[array]["eseries_proxy_api_username"] | default('admin'),
"proxy_password": hostvars[array]["eseries_proxy_api_password"],
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit),
"certificates": certs,
"passphrase": hostvars[array]["eseries_proxy_server_certificate_passphrase"] | default(hostvars[array]["eseries_proxy_server_certificate_common_passphrase"] | default(omit))}}) %}
{%- endif %}
{%- endif %}
{%- endfor %}
{{ systems }}
- name: Ensure proxy LDAP have been configured
na_santricity_ldap:
ssid: proxy
api_url: "{{ item['key'] }}"
api_username: "{{ item['value']['proxy_username'] }}"
api_password: "{{ item['value']['current_password'] | default(item['value']['proxy_password']) }}"
validate_certs: "{{ item['value']['proxy_validate_certs'] }}"
state: "{{ item['value']['ldap_state'] }}"
identifier: "{{ item['value']['ldap_identifier'] | default(omit) }}"
server_url: "{{ item['value']['ldap_server'] | default(omit) }}"
bind_user: "{{ item['value']['ldap_bind_username'] | default(omit) }}"
bind_password: "{{ item['value']['ldap_bind_password'] | default(omit) }}"
search_base: "{{ item['value']['ldap_search_base'] | default(omit) }}"
user_attribute: "{{ item['value']['ldap_user_attribute'] | default(omit) }}"
role_mappings: "{{ item['value']['ldap_role_mappings'] | default(omit) }}"
ignore_errors: true
connection: local
loop: "{{ lookup('dict', proxy_admin, wantlist=True) }}"
vars:
proxy_admin: |-
{#- Build a dictionary of all inventoried proxies keyed by their api url #}
{%- set systems = {} %}
{%- for array in ansible_play_hosts_all %}
{%- if "eseries_proxy_api_url" in hostvars[array] and "eseries_proxy_api_password" in hostvars[array] and "eseries_proxy_ldap_state" in hostvars[array] %}
{%- if systems.update({hostvars[array]["eseries_proxy_api_url"]: {
"proxy_username": hostvars[array]["eseries_proxy_api_username"] | default('admin'),
"proxy_password": hostvars[array]["eseries_proxy_api_password"],
"current_proxy_password": hostvars[array]["eseries_proxy_current_api_password"] | default(omit),
"proxy_validate_certs": hostvars[array]["eseries_validate_certs"] | default(omit),
"ldap_state": hostvars[array]["eseries_proxy_ldap_state"],
"ldap_identifier": hostvars[array]["eseries_proxy_ldap_identifier"] | default(omit),
"ldap_server": hostvars[array]["eseries_proxy_ldap_server"] | default(omit),
"ldap_bind_username": hostvars[array]["eseries_proxy_ldap_bind_username"] | default(omit),
"ldap_bind_password": hostvars[array]["eseries_proxy_ldap_bind_password"] | default(omit),
"ldap_search_base": hostvars[array]["eseries_proxy_ldap_search_base"] | default(omit),
"ldap_user_attribute": hostvars[array]["eseries_proxy_ldap_user_attribute"] | default(omit),
"ldap_role_mappings": hostvars[array]["eseries_proxy_ldap_role_mappings"] | default(omit)}}) %}
{%- endif %}
{%- endif %}
{%- endfor %}
{{ systems }}

View File

@@ -0,0 +1,443 @@
nar_santricity_host
=========
Configures storage pools, volumes, hosts, host groups, and port interfaces for NetApp E-Series storage arrays
using iSCSI, FC, SAS, IB, NVMe protocols.
Requirements
------------
- NetApp E-Series E2800 platform or newer or NetApp E-Series SANtricity Web Services Proxy configured for older E-Series Storage arrays.
Tested Ansible Versions
-----------------------
- Ansible 5.x (ansible-core 2.12)
Example Playbook
----------------
- hosts: eseries_storage_systems
gather_facts: false
collection:
- netapp_eseries.santricity
tasks:
- name: Ensure NetApp E-Series storage system is properly configured
import_role:
name: nar_santricity_host
Example Storage System Inventory File (Discover storage system with proxy)
-------------------------------------
eseries_system_serial: "012345678901" # Be sure to quote if the serial is all numbers and begins with zero.
eseries_system_password: admin_password
eseries_proxy_api_url: https://192.168.1.100:8443/devmgr/v2/
eseries_proxy_api_password: admin_password
eseries_subnet: 192.168.1.0/24
eseries_prefer_embedded: true
eseries_validate_certs: false
eseries_initiator_protocol: iscsi
# Controller port definitions
eseries_controller_iscsi_port_config_method: static
eseries_controller_iscsi_port_subnet_mask: 255.255.255.0
eseries_controller_iscsi_port:
controller_a:
- address: 192.168.2.100
- address: 192.168.2.110
controller_b:
- address: 192.168.3.100
- address: 192.168.3.110
# Storage pool and volume configuration
eseries_storage_pool_configuration:
- name: pool[1-2]
raid_level: raid6
criteria_drive_count: 10
volumes:
- name: "[pool]_volume[A-C]"
host: server_group
size: 4096
Example Storage System Inventory File (Without storage system discovery)
-------------------------------------
eseries_system_api_url: https://192.168.1.200:8443/devmgr/v2/
eseries_system_password: admin_password
eseries_validate_certs: false
(...) # Same as the previous example
Yet Another Example System Inventory File
-----------------------------------------
eseries_system_api_url: https://192.168.1.200:8443/devmgr/v2/
eseries_system_password: admin_password
eseries_validate_certs: false
eseries_initiator_protocol: nvme_ib
eseries_controller_nvme_ib_port:
controller_a:
- 192.168.1.100
- 192.168.1.110
controller_b:
- 192.168.2.100
- 192.168.2.110
eseries_storage_pool_configuration:
- name: vg[1-2]
raid_level: raid6
criteria_drive_count: 12
criteria_volume_count: 4
criteria_reserve_free_capacity_pct: 7
common_volume_host: server_group
Role Variables
--------------
**Note that when values are specified below, they indicate the default value.**
# Web Services Embedded information
eseries_subnet: # Network subnet to search for the storage system specified in CIDR form. Example: 192.168.1.0/24
eseries_system_serial: # Storage system serial number. Be sure to quote if the serial is all numbers and begins with zero. (This is located
# on a label at the top-left towards the front on the device)
eseries_system_addresses: # Storage system management IP addresses. Only required when eseries_system_serial or eseries_system_api_url are not
# defined. When not specified, addresses will be populated with eseries_management_interfaces controller addresses.
eseries_system_api_url: # Url for the storage system's for embedded web services rest api. Example: https://192.168.10.100/devmgr/v2
eseries_system_username: admin # Username for the storage system's for embedded web services rest api
eseries_system_password: # Password for the storage system's for embedded web services rest api and when the admin password has not been set
# eseries_system_password will be used to set it.
eseries_proxy_ssid: # Arbitrary string for the proxy to represent the storage system. eseries_system_serial will be used when not defined.
eseries_template_api_url: # Template for the web services api url. Default: https://0.0.0.0:8443/devmgr/v2/
eseries_prefer_embedded: false # Overrides the default behavior of using Web Services Proxy when eseries_proxy_api_url is defined. This will only effect storage systems that have Embedded Web Services.
eseries_validate_certs: true # Indicates Whether SSL certificates should be verified. Used for both embedded and proxy. Choices: true, false
# Web Services Proxy information
Note: eseries_proxy_* variables are required to discover storage systems prior to SANtricity OS version 11.60.2.
eseries_proxy_api_url: # Url for the storage system's for proxy web services rest api. Example: https://192.168.10.100/devmgr/v2
eseries_proxy_api_username: # Username for the storage system's for proxy web services rest api.
eseries_proxy_api_password: # Password for the storage system's for proxy web services rest api and when the admin password has not been set
# eseries_proxy_api_password will be used to set it.
# Controller iSCSI Interface Port Default Policy Specifications
eseries_controller_iscsi_port_state: enabled # Generally specifies whether a controller port definition should be applied Choices: enabled, disabled
eseries_controller_iscsi_port_config_method: dhcp # General port configuration method definition for both controllers. Choices: static, dhcp
eseries_controller_iscsi_port_gateway: # General port IPv4 gateway for both controllers.
eseries_controller_iscsi_port_subnet_mask: # General port IPv4 subnet mask for both controllers.
eseries_controller_iscsi_port_mtu: 9000 # General port maximum transfer units (MTU) for both controllers. Any value greater than 1500 (bytes).
eseries_controller_iscsi_port_speed: # General port speed for both controllers.
eseries_controller_iscsi_port:
controller_a: # Ordered list of controller A channel definition.
- state: # Whether the port should be enabled. Choices: enabled, disabled
config_method: # Port configuration method Choices: static, dhcp
address: # Port IPv4 address
gateway: # Port IPv4 gateway
subnet_mask: # Port IPv4 subnet_mask
mtu: # Port IPv4 mtu
speed: # Port speed
controller_b: # Ordered list of controller B channel definition.
- (...) # Same as controller A but for controller B
# Controller InfiniBand iSER Interface Channel
eseries_controller_ib_iser_port:
controller_a: # Ordered list of controller A channel address definition.
- # Port IPv4 address for channel 1
- (...) # So on and so forth
controller_b: # Ordered list of controller B channel address definition.
# Controller NVMe over InfiniBand Interface Channel
eseries_controller_nvme_ib_port:
controller_a: # Ordered list of controller A channel address definition.
- # Port IPv4 address for channel 1
- (...) # So on and so forth
controller_b: # Ordered list of controller B channel address definition.
# Controller NVMe RoCE Interface Port Default Policy Specifications
eseries_controller_nvme_roce_port_state: enabled # Generally specifies whether a controller port definition should be applied Choices: enabled, disabled
eseries_controller_nvme_roce_port_config_method: dhcp # General port configuration method definition for both controllers. Choices: static, dhcp
eseries_controller_nvme_roce_port_gateway: # General port IPv4 gateway for both controllers.
eseries_controller_nvme_roce_port_subnet_mask: # General port IPv4 subnet mask for both controllers.
eseries_controller_nvme_roce_port_mtu: 4200 # General port maximum transfer units (MTU). Any value greater than 1500 (bytes).
eseries_controller_nvme_roce_port_speed: auto # General interface speed. Value must be a supported speed or auto for automatically negotiating the speed with the port.
eseries_controller_nvme_roce_port:
controller_a: # Ordered list of controller A channel definition.
- state: # Whether the port should be enabled.
config_method: # Port configuration method Choices: static, dhcp
address: # Port IPv4 address
subnet_mask: # Port IPv4 subnet_mask
gateway: # Port IPv4 gateway
mtu: # Port IPv4 mtu
speed: # Port IPv4 speed
controller_b: # Ordered list of controller B channel definition.
- (...) # Same as controller A but for controller B
# Target discovery specifications
Note: add the following to ansible-playbook command to update the chap secret: --extra-vars "eseries_target_chap_secret_update=True
eseries_target_name: # iSCSI target name that will be seen by the initiator
eseries_target_ping: True # Enables ICMP ping response from the configured iSCSI ports (boolean)
eseries_target_unnamed_discovery: True # Whether the iSCSI target iqn should be returned when an initiator performs a discovery session.
eseries_target_chap_secret: # iSCSI chap secret. When left blank, the chap secret will be removed from the storage system.
eseries_target_chap_secret_update: False # DO NOT REMOVE! Since na_santricity_iscsi_target cannot compare the chap secret with the current and chooses to always
# return changed=True, this flag is used to force the module to update the chap secret. It is preferable to
# leave this value False and to add the --extra-vars "eseries_target_chap_secret_update=True".
# Storage Pool Default Policy Specifications
eseries_storage_pool_state: present # Default storage pool state. Choices: present, absent
eseries_storage_pool_raid_level: raidDiskPool # Default volume raid level. Choices: raid0, raid1, raid5, raid6, raidDiskPool
eseries_storage_pool_secure_pool: false # Default for storage pool drive security. This flag will enable the security at rest feature. There
# must be sufficient FDE or FIPS security capable drives. Choices: true, false
eseries_storage_pool_criteria_drive_count: # Default storage pool drive count.
eseries_storage_pool_reserve_drive_count: # Default reserve drive count for drive reconstruction for storage pools using dynamic disk pool and
# the raid level must be set for raidDiskPool.
eseries_storage_pool_criteria_min_usable_capacity: # Default minimum required capacity for storage pools.
eseries_storage_pool_criteria_drive_type: # Default drive type for storage pools. Choices: hdd, ssd
eseries_storage_pool_criteria_drive_interface_type: # Default interface type to use when selecting drives for the storage pool.
# Choices: scsi, fibre, sata, pata, fibre520b, sas, sas4k, nvme4k
eseries_storage_pool_criteria_size_unit: gb # Default unit size for all storage pool related sizing.
# Choices: bytes, b, kb, mb, gb, tb, pb, eb, zb, yb
eseries_storage_pool_criteria_drive_min_size: # Default minimum drive size for storage pools.
eseries_storage_pool_criteria_drive_max_size: # Default maximum drive size for storage pools.
eseries_storage_pool_criteria_drive_require_da: # Default for whether storage pools are required to have data assurance (DA) compatible drives.
# Choices: true, false
eseries_storage_pool_criteria_drive_require_fde: # Default for whether storage pools are required to have drive security compatible drives.
# Choices: true, false
eseries_storage_pool_remove_volumes: # Default policy for deleting volumes prior to removing storage pools.
eseries_storage_pool_erase_secured_drives: # Default policy for erasing the content drives during create and delete storage pool operations.
# Choices: true, false
eseries_storage_pool_ddp_critical_threshold_pct: # Default policy for dynamic disk pool alert critical threshold.
eseries_storage_pool_ddp_warning_threshold_pct: # Default policy for dynamic disk pool alert warning threshold.
# Volume Default Policy Specifications
eseries_volume_state: present # Default volume state. Choices: present, absent
eseries_volume_size_unit: gb # Default unit size for all volume sizing options.
# Choices: bytes, b, kb, mb, gb, tb, pb, eb, zb, yb, pct
eseries_volume_size: # Default volume size or the presented size for thinly provisioned volumes.
eseries_volume_data_assurance_enabled: # Default for whether data assurance(DA) is required to be enabled.
eseries_volume_segment_size_kb: # Default segment size measured in kib.
eseries_volume_read_cache_enable: # Default for read caching which will cache all read requests.
eseries_volume_read_ahead_enable: # Default for read ahead caching; this is good for sequential workloads to cache subsequent blocks.
eseries_volume_write_cache_enable: # Default for write caching which will cache all writes.
eseries_volume_write_cache_mirror_enable: # Default for write cache mirroring which mirrors writes to both controller's cache.
eseries_volume_cache_without_batteries: # Default for allowing caching when batteries are not present.
eseries_volume_thin_provision: # Default for whether volumes should be thinly provisioned.
eseries_volume_thin_volume_repo_size: # Default for actually allocated space for thinly provisioned volumes.
eseries_volume_thin_volume_max_repo_size: # Default for the maximum allocated space allowed for thinly provisioned volumes.
eseries_volume_thin_volume_expansion_policy: # Default thin volume expansion policy. Choices: automatic, manual
eseries_volume_thin_volume_growth_alert_threshold: # Default thin volume growth alert threshold; this is the threshold for when the thin volume expansion
# policy will be enacted. Allowable values are between and including 10% and 99%
eseries_volume_ssd_cache_enabled: # Default for ssd cache which will enable the volume to use an existing SSD cache on the storage array.
eseries_volume_host: # Default host for all volumes; the value can be any host from the Ansible inventory. Any initiator may be
# used whether connected or not since the storage array does not require connectivity in order to create
# host objects.
eseries_volume_workload_name: # Default workload tag name
eseries_volume_workload_metadata: # Default workload metadata
eseries_volume_volume_metadata: # Default volume_metadata
eseries_volume_owning_controller # Default preferred owning controller
eseries_volume_allow_expansion: false # Default for whether volume expansions are permitted
eseries_volume_wait_for_initialization: false # Default for whether volume creation with wait for initialization to complete
# Storage Pool-Volume Mapping Default Policy Specifications
eseries_lun_mapping_state: present # Generally specifies whether a LUN mapping should be present. This is useful when adding a default host for all
# volumes. Choices: present, absent
eseries_lun_mapping_host: # Default host for all volumes not specifically give a host either in common_volume_configuration or in
# eseries_storage_pool_configuration.
# Storage Pool-Volume Default Policy Specifications
Name schemes: Storage pool and volume names can be used to specify a naming scheme to produce a list of storage pools and volumes. The scheme are defined by
brackets and can be used to specify a range of lowercase letters, uppercase letters, range of single digit numbers, any top-level inventory
variables, and the current defined storage pool (volume only).
eseries_storage_pool_configuration:
- name: # Name or name scheme (see above) for the storage pool.
state: # Specifies whether the storage pool should exist (present, absent). When removing an existing storage array all of the
# volumes must be defined with state=absent.
raid_level # Volume group raid level. Choices: raid0, raid1, raid5, raid6, raidDiskPool (Default: raidDiskPool)
secure_pool: # Default for storage pool drive security. This flag will enable the security at rest feature. There must be sufficient FDE
# or FIPS security capable drives. Choices: true, false
criteria_drive_count: # Default storage pool drive count.
criteria_volume_count: # Number of equally sized volumes to create. All available storage pool space will be used. The option will be ignored
# if volumes is defined.
criteria_reserve_free_capacity_pct # Percent of reserve free space capacity to leave when creating the criteria_volume_count volumes.
common_volume_host # Host or host group for the criteria_volume_count volumes should be mapped.
reserve_drive_count: # Default reserve drive count for drive reconstruction for storage pools using dynamic disk pool and the raid level must be
# set for raidDiskPool.
criteria_size_unit: # Unit size for all storage pool related sizing. Choices: bytes, b, kb, mb, gb, tb, pb, eb, zb, yb, pct
criteria_min_usable_capacity: # Minimum required capacity for storage pools.
criteria_drive_type: # Drive type for storage pools. Choices: hdd, ssd
criteria_drive_interface_type # Interface type to use when selecting drives for the storage pool. Choices: scsi, fibre, sata, pata, fibre520b, sas, sas4k, nvme4k
criteria_drive_min_size: # Minimum drive size for storage pools.
criteria_drive_max_size: # Maximum drive size for storage pools.
criteria_drive_require_da: # Whether storage pools are required to have data assurance (DA) compatible drives. Choices: true, false
criteria_drive_require_fde: # Whether storage pools are required to have drive security compatible drives. Choices: true, false
remove_volumes: # Policy for deleting volumes prior to removing storage pools.
erase_secured_drives: # Policy for erasing the content drives during create and delete storage pool operations. Choices: true, false
common_volume_configuration: # Any option that can be specified at the volume level can be generalized here at the storage pool level. This is useful when
# all volumes share common configuration definitions.
volumes: # List of volumes associated the storage pool.
- state: # Specifies whether the volume should exist (present, absent)
name: # (required) Name or name scheme (see above) for the volume(s) to be created in the storage pool(s)
host: # host or host group for the volume should be mapped to.
host_type: # Only required when using something other than Linux kernel 3.10 or later with DM-MP (Linux DM-MP),
# non-clustered Windows (Windows), or the storage system default host type is incorrect. Common definitions below:
# - AIX MPIO: The Advanced Interactive Executive (AIX) OS and the native MPIO driver
# - AVT 4M: Silicon Graphics, Inc. (SGI) proprietary multipath driver; refer to the SGI installation documentation for more information
# - HP-UX: The HP-UX OS with native multipath driver
# - Linux ATTO: The Linux OS and the ATTO Technology, Inc. driver (must use ATTO FC HBAs)
# - Linux DM-MP: The Linux OS and the native DM-MP driver
# - Linux Pathmanager: The Linux OS and the SGI proprietary multipath driver; refer to the SGI installation documentation for more information
# - Mac: The Mac OS and the ATTO Technology, Inc. driver
# - ONTAP: FlexArray
# - Solaris 11 or later: The Solaris 11 or later OS and the native MPxIO driver
# - Solaris 10 or earlier: The Solaris 10 or earlier OS and the native MPxIO driver
# - SVC: IBM SAN Volume Controller
# - VMware: ESXi OS
# - Windows: Windows Server OS and Windows MPIO with a DSM driver
# - Windows Clustered: Clustered Windows Server OS and Windows MPIO with a DSM driver
# - Windows ATTO: Windows OS and the ATTO Technology, Inc. driver
size: # Size of the volume or presented size of the thinly provisioned volume.
size_unit: # Unit size for the size, thin_volume_repo_size, and thin_volume_max_repo_size
# Choices: bytes, b, kb, mb, gb, tb, pb, eb, zb, yb, pct
segment_size_kb: # Indicates the amount of data stored on a drive before moving on to the next drive in the volume group. Does not apply to pool volumes.
thin_provision: # Whether volumes should be thinly provisioned.
thin_volume_repo_size: # Actually allocated space for thinly provisioned volumes.
thin_volume_max_repo_size: # Maximum allocated space allowed for thinly provisioned volumes.
thin_volume_expansion_policy: # Thin volume expansion policy. Choices: automatic, manual
thin_volume_growth_alert_threshold: # Thin volume growth alert threshold; this is the threshold for when the thin volume expansion
# policy will be enacted. Allowable values are between and including 10% and 99%
ssd_cache_enabled: # Enables ssd cache which will enable the volume to use an existing SSD cache on the storage array.
data_assurance_enabled: # Enables whether data assurance(DA) is required to be enabled.
read_cache_enable: # Enables read caching which will cache all read requests.
read_ahead_enable: # Enables read ahead caching; this is good for sequential workloads to cache subsequent blocks.
write_cache_enable: # Enables write caching which will cache all writes.
write_cache_mirror_enable: # Enables write cache mirroring which mirrors writes to both controller's cache.
workload_name: # Name of the volume's workload. This can be defined using the metadata option or, if already defined, specify one already
# created on the storage array.
workload_metadata: # Dictionary containing arbitrary entries normally used for defining the volume(s) workload.
volume_metadata # Dictionary containing arbitrary entries used to define information about the volume itself.
# Note: format_type, format_options[0-9]?, mount_directory, mount_options[0-9]? are used by netapp_eseries.host.mount role to format and mount volumes.
allow_expansion: # Whether volume expansions are permitted
wait_for_initialization: # Whether volume creation with wait for initialization to complete
# Snapshot Consistency Group Default Policy Specifications
eseries_snapshot_remove_unspecified: # Whether to remove any snapshot group or view that is not specified (Default: false).
eseries_snapshot_groups_maximum_snapshots: # Default maximum point-in-time snapshot images (Default: 32).
eseries_snapshot_groups_reserve_capacity_pct: # Default reserve capacity percentage (Default: 40)
eseries_snapshot_groups_preferred_reserve_storage_pool: # Preferred storage pool or volume group for the reserve capacity volume.
eseries_snapshot_groups_reserve_capacity_full_policy: # Default full reserve capacity policy (Default: purge). Choices: [purge, reject]
eseries_snapshot_groups_alert_threshold_pct: # Default reserve capacity percentage full to alert administrators (Default 75).
eseries_snapshot_groups:
- name: # Name of snapshot consistency group.
maximum_snapshots: # Maximum allowed snapshot point-in-time images for consistency group (Default: 32).
reserve_capacity_pct: # Reserve capacity measured as a percentage of the base volume (Default: 40). Reserve capacity can be expanded
# and trimmed; however, the trim operation requires there be no base volume snapshots images in the group.
reserve_capacity_full_policy: # Policy to implement when reserve capacity is full (Default: purge). Choices [purge, reject]
alert_threshold_pct: # Reserve capacity full alert threshold for storage system administrators (Default: 75).
rollback_priority: # Storage system priority for base volume rollback (Default: medium). Choices [lowest, low, medium, high, highest]
volumes: # Information for each volume in the consistency group.
- volume: # Base volume name
reserve_capacity_pct: # Reserve capacity measured as a percentage of the base volume (Default: 40). Reserve capacity can be expanded
# and trimmed; however, the trim operation requires there be no base volume snapshots images in the group.
preferred_reserve_storage_pool: # Preferred reserve capacity storage pool or volume group. This will default to the base volume's
# storage pool or volume group. The reserve capacity volume cannot be changed once created.
- (...)
# Snapshot Consistency Group View Default Policy Specifications
eseries_snapshot_views_host: # Default host or host group to map all snapshot volumes.
eseries_snapshot_views_reserve_capacity_pct: # Default reserve capacity percentage (Default: 40)
eseries_snapshot_views_preferred_reserve_storage_pool: # Preferred storage pool or volume group for the reserve capacity volume.
eseries_snapshot_views_alert_threshold_pct: # Default reserve capacity percentage full to alert administrators (Default 75).
eseries_snapshot_views_writable: # Default for whether to make snapshot volumes writable.
eseries_snapshot_views_validate: # Default for whether to validate snapshot volumes after creation.
eseries_snapshot_views:
- volume: # Consistency group's snapshot view's name.
group_name: # Snapshot consistency group's name.
pit_name: # Point-in-time snapshot images group name. (Only available when specified using Ansible na_santricity_module (via direct or role)
pit_timestamp: # Point-in-time snapshot images group timestamp. Snapshot image timestamp in the YYYY-MM-DD HH:MM:SS (AM|PM) (hours, minutes, seconds, and day-period are optional)
host: # Host or host group to map snapshot volumes.
writable: # Whether snapshot volume of base volume images should be writable.
validate: # Whether snapshot volume should be validated which includes both a media scan and parity validation.
reserve_capacity_pct: # Percentage of base volume capacity to reserve for snapshot copy-on-writes (COW). Only used when snapshot volume is writable.
preferred_reserve_storage_pool: # Preferred storage pool or volume group for the reserve capacity volume.
alert_threshold: # Reserve capacity percentage full to alert administrators
volumes: # (Optional) Select subset of volumes within the snapshot consistency group.
- name: # Name of volume within consistency group.
host: # Host or host group to map snapshot volumes.
lun: # Logical unit number (LUN) mapping for the host or host group.
writable: # Whether snapshot volume of base volume images should be writable.
validate: # Whether snapshot volume should be validated which includes both a media scan and parity validation.
reserve_capacity_pct: # Percentage of base volume capacity to reserve for snapshot copy-on-writes (COW). Only used when snapshot volume is writable.
preferred_reserve_storage_pool: # Preferred storage pool or volume group for the reserve capacity volume.
# Snapshot Consistency Group Rollback Default Policy Specifications
eseries_snapshot_rollback_priority: medium # Default point-in-time rollback priority (Default: medium). Choices [lowest, low, medium, high, highest]
eseries_snapshot_rollback_backup: true # Default whether snapshot should be taken prior to rolling back base volumes (Default: true).
eseries_snapshot_rollbacks:
- group_name: # Snapshot consistency group's name.
pit_name: # Point-in-time snapshot images group name (Only available when specified using Ansible na_santricity_module (via direct or role)
pit_timestamp: # Point-in-time snapshot images group timestamp. Snapshot image timestamp in the YYYY-MM-DD HH:MM:SS (AM|PM) (hours, minutes, seconds, and day-period are optional)
rollback_priority: # Storage system priority for base volume rollback (Default: medium). Choices [lowest, low, medium, high, highest]
rollback_backup: # Whether to create point-in-time snapshot images of the consistency group prior to rollback.
volumes:
# Initiator-Target Protocol Variable Defaults
Note that the following commands need to produce a unique list of IQNs or WWNs of the interfaces used, line separated. Overwrite as necessary.
eseries_initiator_protocol: fc # This variable defines which protocol the storage array will use. Choices: fc, iscsi, sas, ib_iser, ib_srp, nvme_ib, nvme_fc, nvme_roce
eseries_initiator_command:
fc:
linux: "cat /sys/class/fc_host/host*/port_name | sort | uniq"
windows: "(Get-InitiatorPort | Where-Object -P ConnectionType -EQ 'Fibre Channel' | Select-Object -Property PortAddress |
Format-Table -AutoSize -HideTableHeaders | Out-String).trim()"
iscsi:
linux: "grep -o iqn.* /etc/iscsi/initiatorname.iscsi"
windows: "(get-initiatorPort | select-object -property nodeaddress | sort-object | get-unique | ft -autoSize | out-string -stream |
select-string iqn | out-string).trim()"
sas:
# NetApp IMT for SAS attached E-Series SAN hosts recommends adding all possible SAS addresses with the base address
# starting at 0, and the last address ending in 3 for single port HBAs, or 7 for dual port HBAs. Since determining
# single vs . dual port HBAs adds complexity, we always add all 8 possible permutations of the SAS address.
linux: "cat /sys/class/sas_host/host*/device/scsi_host/*/host_sas_address | sort | uniq"
windows: "(Get-InitiatorPort | Where-Object -P ConnectionType -EQ 'SAS' | Select-Object -Property PortAddress | Format-Table -AutoSize -HideTableHeaders | Out-String).trim()"
ib_iser:
linux: "grep -o iqn.* /etc/iscsi/initiatorname.iscsi"
windows: "" # add windows command for determining host iqn address(es)
ib_srp:
linux: "for fp in /sys/class/infiniband/*/ports/*/gids/*; do out=`cat $fp | tr -d :`; port=`expr substr $out 17 32`; if [ $port != 0000000000000000 ]; then echo 0x$port; fi; done | sort | uniq"
windows: "" # add windows command for determining host guid
nvme_ib:
linux: "grep -o nqn.* /etc/nvme/hostnqn"
windows: "" # add windows command for determining host nqn address(es)
nvme_fc:
linux: "grep -o nqn.* /etc/nvme/hostnqn"
windows: "" # add windows command for determining host nqn address(es)
nvme_roce:
linux: "grep -o nqn.* /etc/nvme/hostnqn"
windows: "" # add windows command for determining host nqn address(es)
# Manual host definitions, Linux and Windows systems can be automatically populated based on host mappings found in eseries_storage_pool_configuration
eseries_host_force_port: true # Default for whether ports are to be allowed to be re-assigned (boolean)
eseries_host_remove_unused_hostgroup: true # Forces any unused groups to be removed
eseries_host_object:
- name: # Host label as referenced by the storage array.
state: # Specifies whether host definition should be exist. Choices: present, absent
ports: # List of port definitions
- type: # Port protocol definition (iscsi, fc, sas, ib, nvme). Note that you should use 'iscsi' prior to Santricity version 11.60 for IB iSER.
label: # Arbitrary port label
port: # Port initiator (iqn, wwn, etc)
group: # Host's host group
host_type: # Only required when using something other than Linux kernel 3.10 or later with DM-MP (Linux DM-MP),
# non-clustered Windows (Windows), or the storage system default host type is incorrect. Common definitions below:
# - AIX MPIO: The Advanced Interactive Executive (AIX) OS and the native MPIO driver
# - AVT 4M: Silicon Graphics, Inc. (SGI) proprietary multipath driver; refer to the SGI installation documentation for more information
# - HP-UX: The HP-UX OS with native multipath driver
# - Linux ATTO: The Linux OS and the ATTO Technology, Inc. driver (must use ATTO FC HBAs)
# - Linux DM-MP: The Linux OS and the native DM-MP driver
# - Linux Pathmanager: The Linux OS and the SGI proprietary multipath driver; refer to the SGI installation documentation for more information
# - Mac: The Mac OS and the ATTO Technology, Inc. driver
# - ONTAP: FlexArray
# - Solaris 11 or later: The Solaris 11 or later OS and the native MPxIO driver
# - Solaris 10 or earlier: The Solaris 10 or earlier OS and the native MPxIO driver
# - SVC: IBM SAN Volume Controller
# - VMware: ESXi OS
# - Windows: Windows Server OS and Windows MPIO with a DSM driver
# - Windows Clustered: Clustered Windows Server OS and Windows MPIO with a DSM driver
# - Windows ATTO: Windows OS and the ATTO Technology, Inc. driver
License
-------
BSD-3-Clause
Author Information
------------------
Nathan Swartz (@ndswartz)

View File

@@ -0,0 +1,367 @@
# Web Services Embedded information
#eseries_subnet: # Network subnet to search for the storage system specified in CIDR form. Example: 192.168.1.0/24
#eseries_system_serial: # Storage system serial number. Be sure to quote if the serial is all numbers and begins with zero. (This is located
# on a label at the top-left towards the front on the device)
#eseries_system_addresses: # Storage system management IP addresses. Only required when eseries_system_serial or eseries_system_api_url are not
# defined. When not specified, addresses will be populated with eseries_management_interfaces controller addresses.
#eseries_system_api_url: # Url for the storage system's for embedded web services rest api. Example: https://192.168.10.100/devmgr/v2
#eseries_system_username: # Username for the storage system's for embedded web services rest api
#eseries_system_password: # Password for the storage system's for embedded web services rest api and when the admin password has not been set
# eseries_system_password will be used to set it.
#eseries_proxy_ssid: # Arbitrary string for the proxy to represent the storage system. eseries_system_serial will be used when not defined.
#eseries_template_api_url: # Template for the web services api url. Default: https://0.0.0.0:8443/devmgr/v2/
#eseries_validate_certs: # Indicates Whether SSL certificates should be verified. Used for both embedded and proxy. Choices: true, false
# Web Services Proxy information
# Note: eseries_proxy_* variables are required to discover storage systems prior to SANtricity OS version 11.60.2.
#eseries_proxy_api_url: # Url for the storage system's for proxy web services rest api. Example: https://192.168.10.100/devmgr/v2
#eseries_proxy_api_username: # Username for the storage system's for proxy web services rest api.
#eseries_proxy_api_password: # Password for the storage system's for proxy web services rest api and when the admin password has not been set
# eseries_proxy_api_password will be used to set it.
# Storage Pool Default Policy Specifications
# ------------------------------------------
eseries_storage_pool_state: present # Default storage pool state. Choices: present, absent
eseries_storage_pool_raid_level: raidDiskPool # Default volume raid level. Choices: raid0, raid1, raid5, raid6, raidDiskPool
eseries_storage_pool_secure_pool: false # Default for storage pool drive security. This flag will enable the security at rest feature. There
# must be sufficient FDE or FIPS security capable drives. Type: boolean
#eseries_storage_pool_criteria_drive_count: # Default storage pool drive count.
#eseries_storage_pool_reserve_drive_count: # Default reserve drive count for drive reconstruction for storage pools using dynamic disk pool and
# the raid level must be set for raidDiskPool.
#eseries_storage_pool_criteria_min_usable_capacity: # Default minimum required capacity for storage pools.
#eseries_storage_pool_criteria_drive_type: # Default drive type for storage pools. Choices: hdd, ssd
eseries_storage_pool_criteria_size_unit: gb # Default unit size for all storage pool related sizing.
# Choices: bytes, b, kb, mb, gb, tb, pb, eb, zb, yb
#eseries_storage_pool_criteria_drive_min_size: # Default minimum drive size for storage pools.
#eseries_storage_pool_criteria_drive_require_da: # Default for whether storage pools are required to have data assurance (DA) compatible drives.
# Type: boolean
#eseries_storage_pool_criteria_drive_require_fde: # Default for whether storage pools are required to have drive security compatible drives.
# Type: boolean
#eseries_storage_pool_usable_drives: # Ordered list of <tray_number>:<drive_slot> strings for drive candidates. This is useful to control
# drive selections.
eseries_storage_pool_remove_volumes: True # Default policy for deleting volumes prior to removing storage pools.
#eseries_storage_pool_erase_secured_drives: # Default policy for erasing the content drives during create and delete storage pool operations.
# Type: boolean
#eseries_storage_pool_ddp_critical_threshold_pct: # Default policy for dynamic disk pool alert critical threshold.
#eseries_storage_pool_ddp_warning_threshold_pct: # Default policy for dynamic disk pool alert warning threshold.
# Volume Default Policy Specifications
# ------------------------------------
eseries_volume_state: present # Default volume state. Choices: present, absent
eseries_volume_size_unit: gb # Default unit size for all volume sizing options.
#eseries_volume_size: # Default volume size or the presented size for thinly provisioned volumes.
#eseries_volume_data_assurance_enabled: # Default for whether data assurance(DA) is required to be enabled.
#eseries_volume_segment_size_kb: # Default segment size measured in kib.
#eseries_volume_read_cache_enable: # Default for read caching which will cache all read requests.
#eseries_volume_read_ahead_enable: # Default for read ahead caching; this is good for sequential workloads to cache subsequent blocks.
#eseries_volume_write_cache_enable: # Default for write caching which will cache all writes.
#eseries_volume_cache_without_batteries: # Default for allowing caching when batteries are not present.
#eseries_volume_thin_provision: # Default for whether volumes should be thinly provisioned.
#eseries_volume_thin_volume_repo_size: # Default for actually allocated space for thinly provisioned volumes.
#eseries_volume_thin_volume_max_repo_size: # Default for the maximum allocated space allowed for thinly provisioned volumes.
#eseries_volume_thin_volume_expansion_policy: # Default thin volume expansion policy. Choices: automatic, manual
#eseries_volume_thin_volume_growth_alert_threshold: # Default thin volume growth alert threshold; this is the threshold for when the thin volume expansion
# policy will be enacted. Allowable values are between and including 10% and 99%
#eseries_volume_ssd_cache_enabled: # Default for ssd cache which will enable the volume to use an existing SSD cache on the storage array.
#eseries_volume_host: # Default host for all volumes; the value can be any host from the Ansible inventory. Any initiator may be
# used whether connected or not since the storage array does not require connectivity in order to create
# host objects.
#eseries_volume_workload_name: # Default workload tag name
#eseries_volume_metadata: # Default metadata
#eseries_volume_owning_controller # Default preferred owning controller
eseries_volume_wait_for_initialization: false # Default for whether volume creation with wait for initialization to complete
# Storage Pool-Volume Mapping Default Policy Specifications
# ---------------------------------------------------------
eseries_lun_mapping_state: present # Generally specifies whether a LUN mapping should be present. This is useful when adding a default host for all
# volumes. Choices: present, absent
#eseries_lun_mapping_host: # Default host for all volumes not specifically give a host either in common_volume_configuration or in
# eseries_storage_pool_configuration.
# Controller iSCSI Interface Port Default Policy Specifications
# -------------------------------------------------------
eseries_controller_iscsi_port_state: enabled # Generally specifies whether a controller port definition should be applied Choices: enabled, disabled
eseries_controller_iscsi_port_config_method: dhcp # General port configuration method definition for both controllers. Choices: static, dhcp
#eseries_controller_iscsi_port_gateway: # General port IPv4 gateway for both controllers.
#eseries_controller_iscsi_port_subnet_mask: # General port IPv4 subnet mask for both controllers.
eseries_controller_iscsi_port_mtu: 9000 # General port maximum transfer units (MTU) for both controllers. Any value greater than 1500 (bytes).
#eseries_controller_iscsi_port:
# controller_a: # Controller A port definition.
# state: # General definitions for all ports on controller A. Any option specified in the ports definition can be
# specified here to generalize for all controller A ports. Choices: enabled, disabled
# config_method: # Port configuration method Choices: static, dhcp
# address: # Port IPv4 address
# gateway: # Port IPv4 gateway
# subnet_mask: # Port IPv4 subnet_mask
# mtu: # Port IPv4 mtu
# ports: # List containing ports definitions
# - state: # Whether the port should be enabled. Choices: enabled, disabled
# config_method: # Port configuration method Choices: static, dhcp
# address: # Port IPv4 address
# gateway: # Port IPv4 gateway
# subnet_mask: # Port IPv4 subnet_mask
# controller_b: # Controller B port definition.
# (...) # Same as controller A but for controller B
# Controller InfiniBand iSER Interface Channel
# --------------------------------------------
#eseries_controller_ib_iser_port:
# controller_a: # Ordered list of controller A channel address definition.
# - # Port IPv4 address for channel 1
# - (...) # So on and so forth
# controller_b: # Ordered list of controller B channel address definition.
# Controller NVMe over InfiniBand Interface Channel
# -------------------------------------------------
#eseries_controller_nvme_ib_port:
# controller_a: # Ordered list of controller A channel address definition.
# - # Port IPv4 address for channel 1
# - (...) # So on and so forth
# controller_b: # Ordered list of controller B channel address definition.
# Controller NVMe RoCE Interface Port Default Policy Specifications
# -------------------------------------------------------
eseries_controller_nvme_roce_port_state: enabled # Generally specifies whether a controller port definition should be applied Choices: enabled, disabled
eseries_controller_nvme_roce_port_config_method: dhcp # General port configuration method definition for both controllers. Choices: static, dhcp
#eseries_controller_nvme_roce_port_gateway: # General port IPv4 gateway for both controllers.
#eseries_controller_nvme_roce_port_subnet_mask: # General port IPv4 subnet mask for both controllers.
eseries_controller_nvme_roce_port_mtu: 4200 # General port maximum transfer units (MTU). Any value greater than 1500 (bytes).
eseries_controller_nvme_roce_port_speed: auto # General interface speed. Value must be a supported speed or auto for automatically negotiating the speed with the port.
#eseries_controller_nvme_roce_port:
# controller_a: # Controller A port definition.
# state: # General definitions for all ports on controller A. Any option specified in the ports definition can be
# specified here to generalize for all controller A ports.
# config_method: # Port configuration method Choices: static, dhcp
# address: # Port IPv4 address
# gateway: # Port IPv4 gateway
# subnet_mask: # Port IPv4 subnet_mask
# mtu: # Port IPv4 mtu
# speed: # Port IPv4 speed
# ports: # List containing ports definitions
# - channel: # Channel of the port to modify. This will be a numerical value that represents the port; typically read
# left to right on the HIC.
# state: # Whether the port should be enabled.
# config_method: # Port configuration method Choices: static, dhcp
# address: # Port IPv4 address
# gateway: # Port IPv4 gateway
# subnet_mask: # Port IPv4 subnet_mask
# controller_b: # Controller B port definition.
# state: # General definitions for all ports on controller B. Any option specified in the ports definition can be
# specified here to generalize for all controller A ports.
# config_method: # Port configuration method Choices: static, dhcp
# address: # Port IPv4 address
# gateway: # Port IPv4 gateway
# subnet_mask: # Port IPv4 subnet_mask
# mtu: # Port IPv4 mtu
# speed: # Port IPv4 speed
# ports: # List containing ports definitions
# - channel: # Channel of the port to modify. This will be a numerical value that represents the port; typically read
# left to right on the HIC.
# state: # Whether the port should be enabled.
# config_method: # Port configuration method Choices: static, dhcp
# address: # Port IPv4 address
# gateway: # Port IPv4 gateway
# subnet_mask: # Port IPv4 subnet_mask
# Target Discovery Default Policy Specifications
# ----------------------------------------------
#eseries_target_name: # iSCSI target name
eseries_target_ping: True # Enables ICMP ping response from the configured iSCSI ports (boolean)
eseries_target_unnamed_discovery: True # Whether the iSCSI target iqn should be returned when an initiator performs a discovery session.
eseries_target_chap_secret: # iSCSI chap secret. When left blank, the chap secret will be removed from the storage system.
eseries_target_chap_secret_update: False # DO NOT REMOVE! Since netapp_e_iscsi_target cannot compare the chap secret with the current and chooses to always
# return changed=True, this flag is used to force the module to update the chap secret. It is preferable to
# leave this value False and to add the --extra-vars "eseries_target_chap_secret_update=True".
# Host Default Policy Specifications
# ----------------------------------
eseries_host_force_port: True # Default for whether ports are to be allowed to be re-assigned (boolean)
eseries_host_remove_unused_hostgroup: True # Forces any unused groups to be removed
#eseries_host_object:
# - name: # Host label as referenced by the storage array.
# state:
# host_type: # Windows (non-clustering) 1, Windows (clustering) 6, Vmware 10, Linux (using kernal 3.10 and later) 28
# group: # Host's host group
# ports: # List of port definitions
# - type: # Port protocol definition (iscsi, fc, sas, ib, nvme)
# label: # Arbitrary port label
# port: # Port initiator (iqn, wwn, etc)
# Storage Pool-Volume Default Policy Specifications
# -------------------------------------------------
# Name schemes: Storage pool and volume names can be used to specify a naming scheme to produce a list of storage pools and volumes. The scheme are defined by
# brackets and can be used to specify a range of lowercase letters, uppercase letters, range of single digit numbers, any top-level inventory
# variables, and the current defined storage pool (volume only).
#eseries_storage_pool_configuration:
# - name: # Name or name scheme (see above) for the storage pool.
# state: # Specifies whether the storage pool should exist (present, absent). When removing an existing storage array all of the
# volumes must be defined with state=absent.
# raid_level # Volume group raid level. Choices: raid0, raid1, raid5, raid6, raidDiskPool (Default: raidDiskPool)
# secure_pool: no # Default for storage pool drive security. This flag will enable the security at rest feature. There must be sufficient FDE
# or FIPS security capable drives. Type: boolean
# criteria_drive_count: # Default storage pool drive count.
# reserve_drive_count: # Default reserve drive count for drive reconstruction for storage pools using dynamic disk pool and the raid level must be
# set for raidDiskPool.
# criteria_min_usable_capacity: # Default minimum required capacity for storage pools.
# criteria_drive_type: # Default drive type for storage pools. Choices: hdd, ssd
# criteria_size_unit: gb # Default unit size for all storage pool related sizing. Choices: bytes, b, kb, mb, gb, tb, pb, eb, zb, yb
# criteria_drive_min_size: # Default minimum drive size for storage pools.
# criteria_drive_require_da: # Default for whether storage pools are required to have data assurance (DA) compatible drives. Type: boolean
# criteria_drive_require_fde: # Default for whether storage pools are required to have drive security compatible drives. Type: boolean
# usable_drives: # Ordered list of <tray_number>:<drive_slot> strings for drive candidates. This is useful to control
# drive selections.
# remove_volumes: # Default policy for deleting volumes prior to removing storage pools.
# erase_secured_drives: # Default policy for erasing the content drives during create and delete storage pool operations. Type: boolean
# common_volume_configuration: # Any option that can be specified at the volume level can be generalized here at the storage pool level. This is useful when
# all volumes share common configuration definitions.
# volumes: # List of volumes associated the storage pool.
# - state: # Specifies whether the volume should exist (present, absent)
# name: # (required) Name or name scheme (see above) for the volume(s) to be created in the storage pool(s)
# host: # host or host group for the volume should be mapped to.
# host_type: # Only required when using something other than Linux kernel 3.10 or later with DM-MP (Linux DM-MP),
# non-clustered Windows (Windows), or the storage system default host type is incorrect. Common definitions below:
# - AIX MPIO: The Advanced Interactive Executive (AIX) OS and the native MPIO driver
# - AVT 4M: Silicon Graphics, Inc. (SGI) proprietary multipath driver; refer to the SGI installation documentation for more information
# - HP-UX: The HP-UX OS with native multipath driver
# - Linux ATTO: The Linux OS and the ATTO Technology, Inc. driver (must use ATTO FC HBAs)
# - Linux DM-MP: The Linux OS and the native DM-MP driver
# - Linux Pathmanager: The Linux OS and the SGI proprietary multipath driver; refer to the SGI installation documentation for more information
# - Mac: The Mac OS and the ATTO Technology, Inc. driver
# - ONTAP: FlexArray
# - Solaris 11 or later: The Solaris 11 or later OS and the native MPxIO driver
# - Solaris 10 or earlier: The Solaris 10 or earlier OS and the native MPxIO driver
# - SVC: IBM SAN Volume Controller
# - VMware: ESXi OS
# - Windows: Windows Server OS and Windows MPIO with a DSM driver
# - Windows Clustered: Clustered Windows Server OS and Windows MPIO with a DSM driver
# - Windows ATTO: Windows OS and the ATTO Technology, Inc. driver
# size: # Size of the volume or presented size of the thinly provisioned volume.
# size_unit: # Unit size for the size, thin_volume_repo_size, and thin_volume_max_repo_size
# Choices: bytes, b, kb, mb, gb, tb, pb, eb, zb, yb
# segment_size_kb: # Indicates the amount of data stored on a drive before moving on to the next drive in the volume group. Does not apply to pool volumes.
# thin_provision: # Whether volumes should be thinly provisioned.
# thin_volume_repo_size: # Actually allocated space for thinly provisioned volumes.
# thin_volume_max_repo_size: # Maximum allocated space allowed for thinly provisioned volumes.
# thin_volume_expansion_policy: # Thin volume expansion policy. Choices: automatic, manual
# thin_volume_growth_alert_threshold: # Thin volume growth alert threshold; this is the threshold for when the thin volume expansion
# policy will be enacted. Allowable values are between and including 10% and 99%
# ssd_cache_enabled: # Enables ssd cache which will enable the volume to use an existing SSD cache on the storage array.
# data_assurance_enabled: # Enables whether data assurance(DA) is required to be enabled.
# read_cache_enable: # Enables read caching which will cache all read requests.
# read_ahead_enable: # Enables read ahead caching; this is good for sequential workloads to cache subsequent blocks.
# write_cache_enable: # Enables write caching which will cache all writes.
# workload_name: # Name of the volume's workload. This can be defined using the metadata option or, if already defined, specify one already
# created on the storage array.
# metadata: # Dictionary containing arbitrary entries normally used for defining the volume(s) workload.
# wait_for_initialization: # Whether volume creation with wait for initialization to complete
# Snapshot Consistency Group Default Policy Specifications
# --------------------------------------------------------
eseries_snapshot_remove_unspecified: false # Whether to remove any snapshot group or view that is not specified (Default: false).
#eseries_snapshot_groups_maximum_snapshots: # Default maximum point-in-time snapshot images (Default: 32).
#eseries_snapshot_groups_reserve_capacity_pct: # Default reserve capacity percentage (Default: 40)
#eseries_snapshot_groups_preferred_reserve_storage_pool: # Preferred storage pool or volume group for the reserve capacity volume.
#eseries_snapshot_groups_reserve_capacity_full_policy: # Default full reserve capacity policy (Default: purge). Choices: [purge, reject]
#eseries_snapshot_groups_alert_threshold_pct: # Default reserve capacity percentage full to alert administrators (Default 75).
#eseries_snapshot_groups:
# - name: # Name of snapshot consistency group.
# maximum_snapshots: # Maximum allowed snapshot point-in-time images for consistency group (Default: 32).
# reserve_capacity_pct: # Reserve capacity measured as a percentage of the base volume (Default: 40). Reserve capacity can be expanded
# # and trimmed; however, the trim operation requires there be no base volume snapshots images in the group.
# reserve_capacity_full_policy: # Policy to implement when reserve capacity is full (Default: purge). Choices [purge, reject]
# alert_threshold_pct: # Reserve capacity full alert threshold for storage system administrators (Default: 75).
# rollback_priority: # Storage system priority for base volume rollback (Default: medium). Choices [lowest, low, medium, high, highest]
# volumes: # Information for each volume in the consistency group.
# - volume: # Base volume name
# reserve_capacity_pct: # Reserve capacity measured as a percentage of the base volume (Default: 40). Reserve capacity can be expanded
# and trimmed; however, the trim operation requires there be no base volume snapshots images in the group.
# preferred_reserve_storage_pool: # Preferred reserve capacity storage pool or volume group. This will default to the base volume's
# storage pool or volume group. The reserve capacity volume cannot be changed once created.
# - (...)
#eseries_snapshot_views_host: # Default host or host group to map all snapshot volumes.
#eseries_snapshot_views_reserve_capacity_pct: # Default reserve capacity percentage (Default: 40)
#eseries_snapshot_views_preferred_reserve_storage_pool: # Preferred storage pool or volume group for the reserve capacity volume.
#eseries_snapshot_views_alert_threshold_pct: # Default reserve capacity percentage full to alert administrators (Default 75).
#eseries_snapshot_views_writable: # Default for whether to make snapshot volumes writable.
#eseries_snapshot_views_validate: # Default for whether to validate snapshot volumes after creation.
#eseries_snapshot_views:
# - volume: # Consistency group's snapshot view's name.
# group_name: # Snapshot consistency group's name.
# pit_name: # Point-in-time snapshot images group name. (Only available when specified using Ansible na_santricity_module (via direct or role)
# pit_timestamp: # Point-in-time snapshot images group timestamp. Snapshot image timestamp in the YYYY-MM-DD HH:MM:SS (AM|PM) (hours, minutes, seconds, and day-period are optional)
# host: # Host or host group to map snapshot volumes.
# writable: # Whether snapshot volume of base volume images should be writable.
# validate: # Whether snapshot volume should be validated which includes both a media scan and parity validation.
# reserve_capacity_pct: # Percentage of base volume capacity to reserve for snapshot copy-on-writes (COW). Only used when snapshot volume is writable.
# preferred_reserve_storage_pool: # Preferred storage pool or volume group for the reserve capacity volume.
# alert_threshold: # Reserve capacity percentage full to alert administrators
# volumes: # (Optional) Select subset of volumes within the snapshot consistency group.
# - name: # Name of volume within consistency group.
# host: # Host or host group to map snapshot volumes.
# writable: # Whether snapshot volume of base volume images should be writable.
# validate: # Whether snapshot volume should be validated which includes both a media scan and parity validation.
# reserve_capacity_pct: # Percentage of base volume capacity to reserve for snapshot copy-on-writes (COW). Only used when snapshot volume is writable.
# preferred_reserve_storage_pool: # Preferred storage pool or volume group for the reserve capacity volume.
#eseries_snapshot_rollback_priority: medium # Default point-in-time rollback priority (Default: medium). Choices [lowest, low, medium, high, highest]
#eseries_snapshot_rollback_backup: true # Default whether snapshot should be taken prior to rolling back base volumes (Default: true).
#eseries_snapshot_rollbacks:
# - group_name: # Snapshot consistency group's name.
# pit_name: # Point-in-time snapshot images group name (Only available when specified using Ansible na_santricity_module (via direct or role)
# pit_timestamp: # Point-in-time snapshot images group timestamp. Snapshot image timestamp in the YYYY-MM-DD HH:MM:SS (AM|PM) (hours, minutes, seconds, and day-period are optional)
# rollback_priority: # Storage system priority for base volume rollback (Default: medium). Choices [lowest, low, medium, high, highest]
# rollback_backup: # Whether to create point-in-time snapshot images of the consistency group prior to rollback.
# volumes: # (Optional) Select subset of volume names within the snapshot consistency group to rollback.
# Initiator-Target Protocol Variable Defaults
# -------------------------------------------
# Note that the following commands produce a unique list of IQNs or WWNs of the interfaces used, line separated.
eseries_initiator_protocol: # This variable defines which protocol the storage array will use. Choices: iscsi, fc, sas, ib_iser, ib_srp, nvme_ib, nvme_fc, nvme_roce
eseries_initiator_command:
fc:
linux: "cat /sys/class/fc_host/host*/port_name | sort | uniq"
windows: "(Get-InitiatorPort | Where-Object -P ConnectionType -EQ 'Fibre Channel' | Select-Object -Property PortAddress |
Format-Table -AutoSize -HideTableHeaders | Out-String).trim()"
iscsi:
linux: "grep -o iqn.* /etc/iscsi/initiatorname.iscsi"
windows: "(get-initiatorPort | select-object -property nodeaddress | sort-object | get-unique | ft -autoSize | out-string -stream |
select-string iqn | out-string).trim()"
sas:
# NetApp IMT for SAS attached E-Series SAN hosts recommends adding all possible SAS addresses with the base address
# starting at 0, and the last address ending in 3 for single port HBAs, or 7 for dual port HBAs. Since determining
# single vs . dual port HBAs adds complexity, we always add all 8 possible permutations of the SAS address.
linux: "cat /sys/class/sas_host/host*/device/scsi_host/*/host_sas_address | sort | uniq"
windows: "(Get-InitiatorPort | Where-Object -P ConnectionType -EQ 'SAS' | Select-Object -Property PortAddress | Format-Table -AutoSize -HideTableHeaders | Out-String).trim()"
ib_iser:
linux: "grep -o iqn.* /etc/iscsi/initiatorname.iscsi"
windows: "" # add windows command for determining host iqn address(es)
ib_srp:
linux: "for fp in /sys/class/infiniband/*/ports/*/gids/*; do out=`cat $fp | tr -d :`; port=`expr substr $out 17 32`; if [ $port != 0000000000000000 ]; then echo 0x$port; fi; done | sort | uniq"
windows: "" # add windows command for determining host guid
nvme_ib:
linux: "grep -o nqn.* /etc/nvme/hostnqn"
windows: "" # add windows command for determining host nqn address(es)
nvme_fc:
linux: "grep -o nqn.* /etc/nvme/hostnqn"
windows: "" # add windows command for determining host nqn address(es)
nvme_roce:
linux: "grep -o nqn.* /etc/nvme/hostnqn"
windows: "" # add windows command for determining host nqn address(es)
eseries_iscsi_iqn_prefix: "iqn.2005-03.org.open-iscsi:" # Last 12 characters from host machine-id (uuid) will be appended to the prefix if the host does not have a required iqn.
eseries_nvme_nqn_prefix: "nqn.2014-08.org.nvmexpress:uuid:" # Host machine-id (uuid) will be appended to the prefix if the host does not have a required nqn.
eseries_protocols_using_eseries_iscsi_iqn: ["iscsi", "ib_iser"]
eseries_protocols_using_eseries_nvme_nqn: ["nvme_ib", "nvme_fc", "nvme_roce"]
eseries_iscsi_iqn_path: "/etc/iscsi/" #initiatorname.iscsi"
eseries_nvme_nqn_path: "/etc/nvme/" #hostnqn"
eseries_remove_all_configuration: False # WARNING!!! This flag will force any storage pool, volume, host, hostgroup and mapping to be absent. Choices: True, False

View File

@@ -0,0 +1,19 @@
galaxy_info:
author: Nathan Swartz (@ndswartz)
description: Manages NetApp E-Series storage system's interfaces, storage pools, volumes, hosts, hostgroups, and volume mappings.
company: NetApp, Inc
license: BSD-3 Clause
platforms:
min_ansible_version: 2.13
galaxy_tags:
- netapp
- eseries
- storage
- iscsi
- sas
- fc
- infiniband
- ib
- nvme
dependencies: []

View File

@@ -0,0 +1,114 @@
---
# netapp_eseries_iscsi/tasks/initiator.yml
- name: Collect facts on the storage array
na_santricity_facts:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
connection: local
register: storage_array_facts
when: eseries_host_object is defined
- name: Organize current and expected hostgroups
set_fact:
current_storage_array_hostgroups: |-
{%- set current_hostgroup={} %}
{%- for group in storage_array_facts["storage_array_facts"]["netapp_host_groups"] %}
{%- if current_hostgroup.update( {group["name"]: []} ) %}{%- endif %}
{%- for host in storage_array_facts["storage_array_facts"]["netapp_hosts"] %}
{%- if group["id"] == host["group_id"] and current_hostgroup[group["name"]].append(host["name"]) %}{%- endif %}
{%- endfor %}
{%- endfor %}
{{ current_hostgroup }}
hostgroups: |-
{%- set hostgroups=[] %}
{%- for host in eseries_host_object %}
{%- if "group" in (host.keys()|list) and host["group"] not in hostgroups and
("state" not in (host.keys()|list) or host["state"] == "present") and hostgroups.append(host["group"]) %}
{%- endif %}
{%- endfor %}
{{ hostgroups }}
when: eseries_host_object is defined
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} inventory-defined hostgroup definitions"
na_santricity_hostgroup:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ eseries_remove_all_configuration_state | default('present') }}"
name: "{{ item }}"
hosts: "{{ current_storage_array_hostgroups[item] | default(omit) }}"
connection: local
loop: "{{ lookup('list', hostgroups) }}"
when: eseries_host_object is defined and (hostgroups | length > 0)
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} inventory-defined host definitions"
na_santricity_host:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ eseries_remove_all_configuration_state | default(item['state'] | default(omit)) }}"
name: "{{ item['name'] }}"
ports: "{{ item['ports'] | default(omit) }}"
force_port: "{{ item['force_port'] | default(eseries_host_force_port | default(omit)) }}"
group: "{{ item['group'] | default(eseries_host_group | default(omit)) }}"
host_type: "{{ item['host_type_index'] | default(item['host_type'] | default(eseries_host_type_index | default(omit))) }}"
connection: local
loop: "{{ lookup('list', eseries_host_object) }}"
when: eseries_host_object is defined
- name: Collect facts on the storage array
na_santricity_facts:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
connection: local
register: storage_array_facts
when: eseries_host_object is defined
- name: Update the current storage array hostgroups
set_fact:
current_storage_array_hostgroups: |-
{%- set current_hostgroup={} %}
{%- for group in storage_array_facts["storage_array_facts"]["netapp_host_groups"] %}
{%- if current_hostgroup.update( {group["name"]: []} ) %}{%- endif %}
{%- for host in storage_array_facts["storage_array_facts"]["netapp_hosts"] %}
{%- if group["id"] == host["group_id"] and current_hostgroup[group["name"]].append(host["name"]) %}{%- endif %}
{%- endfor %}
{%- endfor %}
{{ current_hostgroup }}
when: eseries_host_object is defined
- name: Create list of unused hostgroups
set_fact:
unused_hostgroups: |-
{%- set unused_hostgroup = [] %}
{%- for current_host_name in (current_storage_array_hostgroups.keys()|list) %}
{%- if (current_storage_array_hostgroups[current_host_name]|length==0) and unused_hostgroup.append(current_host_name) %}{%- endif %}
{%- endfor %}
{{ unused_hostgroup }}
when: eseries_host_object is defined
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} inventory-defined hostgroup definitions"
na_santricity_hostgroup:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: absent
name: "{{ item }}"
hosts: "{{ current_storage_array_hostgroups[item] | default(omit) }}"
connection: local
loop: "{{ lookup('list', unused_hostgroups) }}"
when: "eseries_host_object is defined and (unused_hostgroups|length>0) and eseries_host_remove_unused_hostgroup is
defined and eseries_host_remove_unused_hostgroup"

View File

@@ -0,0 +1,27 @@
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controllers iSCSI interface ports"
import_tasks: interface/iscsi.yml
delegate_to: localhost
when: eseries_initiator_protocol == "iscsi"
tags:
- iscsi
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controllers InfiniBand iSER interface ports"
import_tasks: interface/ib_iser.yml
delegate_to: localhost
when: eseries_initiator_protocol == "ib_iser"
tags:
- ib_iser
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controllers NVMe interface ports over InfiniBand"
import_tasks: interface/nvme_ib.yml
delegate_to: localhost
when: eseries_initiator_protocol == "nvme_ib"
tags:
- nvme_ib
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controllers NVMe interface ports on RoCE"
import_tasks: interface/nvme_roce.yml
delegate_to: localhost
when: eseries_initiator_protocol == "nvme_roce"
tags:
- nvme_roce

View File

@@ -0,0 +1,29 @@
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controller A inventory-defined controller port definitions for InfiniBand iSER"
na_santricity_ib_iser_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: A
channel: "{{ channel + 1 }}"
address: "{{ item }}"
loop: "{{ lookup('list', eseries_controller_ib_iser_port['controller_a']) }}"
loop_control:
index_var: channel
when: eseries_controller_ib_iser_port is defined and eseries_controller_ib_iser_port['controller_a'] is defined
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controller B inventory-defined controller port definitions for InfiniBand iSER"
na_santricity_ib_iser_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: B
channel: "{{ channel + 1 }}"
address: "{{ item }}"
loop: "{{ lookup('list', eseries_controller_ib_iser_port['controller_b']) }}"
loop_control:
index_var: channel
when: eseries_controller_ib_iser_port is defined and eseries_controller_ib_iser_port['controller_b'] is defined

View File

@@ -0,0 +1,56 @@
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controller A inventory-defined controller port definitions for iSCSI"
na_santricity_iscsi_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ item['state'] | default(eseries_controller_iscsi_port_state | default(omit)) }}"
port: "{{ port + 1 }}"
controller: A
config_method: "{{ item['config_method'] | default(eseries_controller_iscsi_port_config_method | default(omit)) }}"
address: "{{ item['address'] | default(omit) }}"
gateway: "{{ item['gateway'] | default(eseries_controller_iscsi_port_gateway | default(omit)) }}"
subnet_mask: "{{ item['subnet_mask'] | default(eseries_controller_iscsi_port_subnet_mask | default(omit)) }}"
mtu: "{{ item['mtu'] | default(eseries_controller_iscsi_port_mtu | default(omit)) }}"
speed: "{{ item['speed'] | default(eseries_controller_iscsi_port_speed | default(omit)) }}"
loop: "{{ lookup('list', eseries_controller_iscsi_port['controller_a']) }}"
loop_control:
index_var: port
when: eseries_controller_iscsi_port is defined and eseries_controller_iscsi_port['controller_a'] is defined
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controller B inventory-defined controller port definitions for iSCSI"
na_santricity_iscsi_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ item['state'] | default(eseries_controller_iscsi_port_state | default(omit)) }}"
port: "{{ port + 1 }}"
controller: B
config_method: "{{ item['config_method'] | default(eseries_controller_iscsi_port_config_method | default(omit)) }}"
address: "{{ item['address'] | default(omit) }}"
gateway: "{{ item['gateway'] | default(eseries_controller_iscsi_port_gateway | default(omit)) }}"
subnet_mask: "{{ item['subnet_mask'] | default(eseries_controller_iscsi_port_subnet_mask | default(omit)) }}"
mtu: "{{ item['mtu'] | default(eseries_controller_iscsi_port_mtu | default(omit)) }}"
speed: "{{ item['speed'] | default(eseries_controller_iscsi_port_speed | default(omit)) }}"
loop: "{{ lookup('list', eseries_controller_iscsi_port['controller_b']) }}"
loop_control:
index_var: port
when: eseries_controller_iscsi_port is defined and eseries_controller_iscsi_port['controller_b'] is defined
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} iSCSI discovery parameters"
na_santricity_iscsi_target:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
name: "{{ eseries_iscsi_target_name | default(omit) }}"
chap_secret: "{%- if eseries_iscsi_target_chap_secret_update %}{{ eseries_iscsi_target_chap_secret }}{%- endif %}"
ping: "{{ eseries_iscsi_target_ping | default(omit) }}"
unnamed_discovery: "{{ eseries_iscsi_target_unnamed_discovery | default(omit) }}"
when: ((eseries_iscsi_target_chap_secret is defined and eseries_iscsi_target_chap_secret_update) or
eseries_iscsi_target_name is defined or eseries_iscsi_target_ping is defined or
eseries_iscsi_target_unnamed_discovery is defined)

View File

@@ -0,0 +1,29 @@
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controller A inventory-defined controller port definitions for NVMe interface ports over InfiniBand"
na_santricity_nvme_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: A
channel: "{{ channel + 1 }}"
address: "{{ item }}"
loop: "{{ lookup('list', eseries_controller_nvme_ib_port['controller_a']) }}"
loop_control:
index_var: channel
when: eseries_controller_nvme_ib_port is defined and eseries_controller_nvme_ib_port['controller_a'] is defined
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controller B inventory-defined controller port definitions for NVMe interface ports over InfiniBand"
na_santricity_nvme_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: B
channel: "{{ channel + 1 }}"
address: "{{ item }}"
loop: "{{ lookup('list', eseries_controller_nvme_ib_port['controller_b']) }}"
loop_control:
index_var: channel
when: eseries_controller_nvme_ib_port is defined and eseries_controller_nvme_ib_port['controller_b'] is defined

View File

@@ -0,0 +1,41 @@
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controller A inventory-defined controller port definitions for NVMe interface ports on RoCE"
na_santricity_nvme_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ item['state'] | default(eseries_controller_nvme_roce_port_state | default(omit)) }}"
controller: A
channel: "{{ channel + 1 }}"
config_method: "{{ item['config_method'] | default(eseries_controller_nvme_roce_port_config_method | default(omit)) }}"
address: "{{ item['address'] | default(omit) }}"
gateway: "{{ item['gateway'] | default(eseries_controller_nvme_roce_port_gateway | default(omit)) }}"
subnet_mask: "{{ item['subnet_mask'] | default(eseries_controller_nvme_roce_port_subnet_mask | default(omit)) }}"
mtu: "{{ item['mtu'] | default(eseries_controller_nvme_roce_port_mtu | default(omit)) }}"
speed: "{{ item['speed'] | default(eseries_controller_nvme_roce_port_speed | default(omit)) }}"
loop: "{{ lookup('list', eseries_controller_nvme_roce_port['controller_a']) }}"
loop_control:
index_var: channel
when: eseries_controller_nvme_roce_port is defined and eseries_controller_nvme_roce_port['controller_a'] is defined
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} controller B inventory-defined controller port definitions for NVMe interface ports on RoCE"
na_santricity_nvme_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ item['state'] | default(eseries_controller_nvme_roce_port_state | default(omit)) }}"
controller: B
channel: "{{ channel + 1 }}"
config_method: "{{ item['config_method'] | default(eseries_controller_nvme_roce_port_config_method | default(omit)) }}"
address: "{{ item['address'] | default(omit) }}"
gateway: "{{ item['gateway'] | default(eseries_controller_nvme_roce_port_gateway | default(omit)) }}"
subnet_mask: "{{ item['subnet_mask'] | default(eseries_controller_nvme_roce_port_subnet_mask | default(omit)) }}"
mtu: "{{ item['mtu'] | default(eseries_controller_nvme_roce_port_mtu | default(omit)) }}"
speed: "{{ item['speed'] | default(eseries_controller_nvme_roce_port_speed | default(omit)) }}"
loop: "{{ lookup('list', eseries_controller_nvme_roce_port['controller_b']) }}"
loop_control:
index_var: channel
when: eseries_controller_nvme_roce_port is defined and eseries_controller_nvme_roce_port['controller_b'] is defined

View File

@@ -0,0 +1,178 @@
- name: Collect facts on the storage array
na_santricity_facts:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
connection: local
register: storage_array_facts
- name: Collect volume host and host group list
set_fact:
hosts: "{{ lookup('netapp_eseries.santricity.santricity_host', hostvars[inventory_hostname],
volumes=lookup('netapp_eseries.santricity.santricity_volume', hostvars[inventory_hostname])) }}"
- name: Retrieve required details and map luns
block:
- name: Collect host/host group networking information
setup:
gather_subset: min
register: hosts_info
delegate_to: "{{ item }}"
delegate_facts: True
loop: "{{ lookup('list', (hosts['expected_hosts'].keys() | list)) }}"
- name: Collect Ansible defined host and host group interface information
set_fact:
host_interface_ansible: |-
{%- set host_interfaces = [] -%}
{%- for host in (hosts['expected_hosts'].keys() | list) -%}
{%- if "eseries_iscsi_iqn" in (hostvars[host].keys() | list) -%}
{%- if host_interfaces.append({"item": host, "stdout_lines": [hostvars[host]["eseries_iscsi_iqn"]]}) -%}{%- endif -%}
{%- elif "eseries_nvme_nqn" in (hostvars[host].keys() | list) -%}
{%- if host_interfaces.append({"item": host, "stdout_lines": [hostvars[host]["eseries_nvme_nqn"]]}) -%}{%- endif -%}
{%- endif -%}
{%- endfor -%}
{{ host_interfaces }}
- name: Collect host and host group interface information for Linux
shell: "{{ eseries_initiator_command[eseries_initiator_protocol]['linux'] }}"
register: host_interface_linux
delegate_to: "{{ item }}"
become: True
changed_when: False
failed_when: "host_interface_linux.rc != 0 and not (eseries_initiator_protocol in eseries_protocols_using_eseries_iscsi_iqn or
eseries_initiator_protocol in eseries_protocols_using_eseries_nvme_nqn)"
when: '((hostvars[item]["ansible_facts"]["system"] | lower) == "linux" and
("eseries_iscsi_iqn" not in (hostvars[item].keys() | list) or eseries_initiator_protocol not in eseries_protocols_using_eseries_iscsi_iqn) and
("eseries_nvme_nqn" not in (hostvars[item].keys() | list) or eseries_initiator_protocol not in eseries_protocols_using_eseries_nvme_nqn))'
loop: "{{ lookup('list', (hosts['expected_hosts'].keys() | list)) }}"
- name: Collect host and host group interface information for Windows
win_shell: "{{ eseries_initiator_command[eseries_initiator_protocol]['windows'] }}"
register: host_interface_windows
delegate_to: "{{ item }}"
changed_when: False
failed_when: "host_interface_windows.rc != 0"
when: '((hostvars[item]["ansible_facts"]["os_family"] | lower == "windows") and
("eseries_iscsi_iqn" not in (hostvars[item].keys() | list) or eseries_initiator_protocol not in eseries_protocols_using_eseries_iscsi_iqn) and
("eseries_nvme_nqn" not in (hostvars[item].keys() | list) or eseries_initiator_protocol not in eseries_protocols_using_eseries_nvme_nqn))'
loop: "{{ lookup('list', (hosts['expected_hosts'].keys() | list)) }}"
- name: Aggregate host/host group interface information
set_fact:
host_interface: |-
{%- set host_interfaces = [] -%}
{%- for host in (hosts['expected_hosts'].keys() | list) -%}
{%- set found_interfaces = host_interface_ansible + host_interface_linux['results'] + host_interface_windows['results'] -%}
{%- for interface in found_interfaces if interface["item"] == host and "skip_reason" not in (interface.keys() | list) and interface["stdout_lines"] -%}
{%- if host_interfaces.append(interface) -%}{%- endif -%}
{%- else -%}
{%- if eseries_initiator_protocol in eseries_protocols_using_eseries_iscsi_iqn -%}
{%- if host_interfaces.append({"item": host, "stdout_lines": [eseries_iscsi_iqn_prefix ~ hostvars[host]["ansible_machine_id"][-12:]], "generate": True}) -%}{%- endif -%}
{%- elif eseries_initiator_protocol in eseries_protocols_using_eseries_nvme_nqn -%}
{%- if host_interfaces.append({"item": host, "stdout_lines": [eseries_nvme_nqn_prefix ~ hostvars[host]["ansible_machine_id"]], "generate": True}) -%}{%- endif -%} {%- endif -%}
{%- endfor -%}
{%- endfor -%}
{{- host_interfaces -}}
- name: Generate missing host IQN (Linux only).
block:
- name: Ensure path for initiatorname.iscsi exists.
file:
state: directory
path: "{{ eseries_iscsi_iqn_path }}"
delegate_to: "{{ item['item'] }}"
become: true
loop: "{{ host_interface }}"
when: "(hostvars[item['item']]['ansible_facts']['system'] | lower) == 'linux' and (item['generate'] | default(False)) == True"
- name: Generate initiatorname.iscsi file.
ansible.builtin.template:
src: initiatorname_iscsi.j2
dest: "{{ eseries_iscsi_iqn_path }}initiatorname.iscsi"
delegate_to: "{{ item['item'] }}"
become: true
loop: "{{ host_interface }}"
when: "(hostvars[item['item']]['ansible_facts']['system'] | lower) == 'linux' and (item['generate'] | default(False)) == True"
when: eseries_initiator_protocol in eseries_protocols_using_eseries_iscsi_iqn
- name: Generate missing host NQN (Linux only).
block:
- name: Ensure NVMe NQN directory exists on host.
file:
state: directory
path: "{{ eseries_nvme_nqn_path }}"
delegate_to: "{{ item['item'] }}"
become: true
loop: "{{ host_interface }}"
when: "(hostvars[item['item']]['ansible_facts']['system'] | lower) == 'linux' and (item['generate'] | default(False)) == True"
- name: Generate NVMe NQN for host if one was not discovered.
ansible.builtin.template:
src: hostnqn.j2
dest: "{{ eseries_nvme_nqn_path }}hostnqn"
delegate_to: "{{ item['item'] }}"
become: true
loop: "{{ host_interface }}"
when: "(hostvars[item['item']]['ansible_facts']['system'] | lower) == 'linux' and (item['generate'] | default(False)) == True"
when: eseries_initiator_protocol in eseries_protocols_using_eseries_nvme_nqn
- name: Organize host/host group interface information and update hosts variable
set_fact:
hosts: "{{ lookup('netapp_eseries.santricity.santricity_host_detail',
hosts, hosts_info=hosts_info['results'], host_interface_ports=host_interface, protocol=eseries_initiator_protocol) }}"
- name: "{{'Create' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Delete' }} all hosts objects on the storage array"
na_santricity_host:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ eseries_remove_all_configuration_state | default(hosts['expected_hosts'][item]['state'] | default(omit)) }}"
name: "{{ hosts['expected_hosts'][item]['sanitized_hostname'] }}"
ports: "{{ hosts['expected_hosts'][item]['ports'] }}"
force_port: "{{ eseries_host_force_port | default(omit) }}"
host_type: "{{ hosts['expected_hosts'][item]['host_type'] | default(omit) }}"
connection: local
loop: "{{ lookup('list', (hosts['expected_hosts'].keys()|list)) }}"
- name: "{{'Create' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Delete' }} all required host groups on the storage array"
na_santricity_hostgroup:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ eseries_remove_all_configuration_state | default('present') }}"
name: "{{ item }}"
hosts: "{{ hosts['host_groups'][item] | default(omit) }}"
connection: local
loop: "{{ lookup('list', (hosts['host_groups'].keys()|list)) }}"
- name: Update facts on the storage array
na_santricity_facts:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
connection: local
register: storage_array_facts
when: eseries_remove_all_configuration_state is not defined or eseries_remove_all_configuration_state == False
- name: "{{'Map' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unmap' }} volume to host or host group."
na_santricity_lun_mapping:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ 'present' if item['target'] is defined else 'absent' }}"
volume: "{{ item['volume'] }}"
target: "{{ item['target'] | default(eseries_lun_mapping_host) | default(omit) }}"
lun: "{{ item['lun'] | default(omit) }}"
connection: local
loop: "{{ lookup('netapp_eseries.santricity.santricity_lun_mapping', storage_array_facts,
volumes=lookup('netapp_eseries.santricity.santricity_volume', hostvars[inventory_hostname]), wantlist=True) }}"
when: hosts != []

View File

@@ -0,0 +1,52 @@
- name: Set current storage system credentials
include_role:
name: netapp_eseries.santricity.nar_santricity_common
tasks_from: build_info.yml
when: current_eseries_api_url is not defined
tags:
- always
- name: Override all inventory configuration states.
set_fact:
eseries_remove_all_configuration_state: absent
when: eseries_remove_all_configuration is defined and eseries_remove_all_configuration == True
tags:
- always
- name: Unconfigure snapshot consistency groups
import_tasks: snapshot.yml
when: eseries_remove_all_configuration == True | default(False)
- name: Configure NetApp E-Series storage system disk pool configuration
import_tasks: storage_pool_present.yml
tags:
- storage_pools
- name: Configure NetApp E-Series storage system volume configuration
import_tasks: volume.yml
tags:
- volumes
- name: Configure NetApp E-Series storage system disk pool configuration
import_tasks: storage_pool_absent.yml
tags:
- storage_pools
- name: Configure storage system's hosts/hostgroups initiators
import_tasks: initiator.yml
tags:
- initiators
- name: Map storage system's volumes to host objects
import_tasks: lun_mapping.yml
tags:
- lun_mappings
- name: Configure controllers interfaces
import_tasks: interface.yml
tags:
- interface
- name: Configure snapshot consistency groups
import_tasks: snapshot.yml
when: eseries_remove_all_configuration == False | default(True)

View File

@@ -0,0 +1,19 @@
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} all snapshot consistency groups."
import_tasks: snapshot/group.yml
when: eseries_snapshot_groups | default(False) or eseries_snapshot_remove_unspecified == True
tags:
- snapshot_group
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} all snapshot consistency group views."
import_tasks: snapshot/view.yml
when: eseries_snapshot_views | default(False) or eseries_snapshot_remove_unspecified == True
tags:
- snapshot_view
- name: Rollback base volumes to point-in-time snapshot images.
import_tasks: snapshot/rollback.yml
when: 'eseries_remove_all_configuration == False | default(True) and
(eseries_snapshot_rollbacks | default(False) or
eseries_snapshot_remove_unspecified == True)'
tags:
- snapshot_rollback

View File

@@ -0,0 +1,75 @@
- name: Determine if any snapshot consistency groups are no longer needed.
block:
- name: Retrieve all snapshot consistency groups
uri:
url: "{{ current_eseries_api_url }}storage-systems/{{ current_eseries_ssid }}/consistency-groups"
method: GET
url_password: "{{ current_eseries_api_password }}"
url_username: "{{ current_eseries_api_username }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
connection: local
register: existing_consistency_groups
- name: Ensure all unspecified snapshot consistency groups are removed.
na_santricity_snapshot:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: absent
type: group
group_name: "{{ item }}"
connection: local
loop: "{{ unspecified_groups }}"
vars:
unspecified_groups: |-
{%- set unspecified_groups = [] -%}
{%- for existing_group in existing_consistency_groups["json"] -%}
{%- for group in eseries_snapshot_groups | default([]) if existing_group["name"] == group["name"] -%}
{%- else -%}
{%- if unspecified_groups.append(existing_group["name"]) -%}{%- endif -%}
{%- endfor -%}
{%- endfor -%}
{{- unspecified_groups -}}
when: (eseries_remove_all_configuration | default(False)) == False and eseries_snapshot_remove_unspecified == True
- name: "Ensure all snapshot consistency groups {{'exist' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'are removed' }}."
na_santricity_snapshot:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ eseries_remove_all_configuration_state | default('present') }}"
type: group
group_name: "{{ item['name'] }}"
maximum_snapshots: "{{ item['maximum_snapshots'] }}"
alert_threshold_pct: "{{ item['alert_threshold_pct'] }}"
reserve_capacity_full_policy: "{{ item['reserve_capacity_full_policy'] }}"
preferred_reserve_storage_pool: "{{ item['preferred_reserve_storage_pool'] }}"
rollback_priority: "{{ item['rollback_priority'] }}"
volumes: "{{ item['volumes'] }}"
connection: local
loop: "{{ consistency_groups }}"
vars:
consistency_groups: |-
{%- set consistency_groups = [] -%}
{%- for group in eseries_snapshot_groups | default([]) -%}
{%- set info = {"name": group["name"],
"maximum_snapshots": group["maximum_snapshots"] | default(eseries_snapshot_groups_maximum_snapshots | default(omit)),
"reserve_capacity_pct": group["reserve_capacity_pct"] | default(eseries_snapshot_groups_reserve_capacity_pct | default(omit)),
"preferred_reserve_storage_pool": group["preferred_reserve_storage_pool"] | default(eseries_snapshot_groups_preferred_reserve_storage_pool | default(omit)),
"reserve_capacity_full_policy": group["reserve_capacity_full_policy"] | default(eseries_snapshot_groups_reserve_capacity_full_policy | default(omit)),
"alert_threshold_pct": group["alert_threshold_pct"] | default(eseries_snapshot_groups_alert_threshold_pct | default(omit)),
"rollback_priority": group["rollback_priority"] | default(eseries_snapshot_rollback_priority | default(omit)),
"volumes": []} -%}
{%- for volume in group["volumes"] -%}
{%- set volume_info = {"volume": volume["volume"]} -%}
{%- if volume["reserve_capacity_pct"] | default(False) and volume_info.update({"reserve_capacity_pct": volume["reserve_capacity_pct"]}) -%}{%- endif -%}
{%- if volume["reserve_capacity_pct"] | default(False) and volume_info.update({"preferred_reserve_storage_pool": volume["preferred_reserve_storage_pool"]}) -%}{%- endif -%}
{%- if info["volumes"].append(volume_info) -%}{%- endif -%}
{%- endfor -%}
{%- if consistency_groups.append(info) -%}{%- endif -%}
{%- endfor -%}
{{- consistency_groups -}}

View File

@@ -0,0 +1,41 @@
- name: Roll volumes back to expected point-in-time.
na_santricity_snapshot:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: rollback
group_name: "{{ item['group_name'] }}"
pit_name: "{{ item['pit_name'] | default(omit) }}"
pit_timestamp: "{{ item['pit_timestamp'] | default(omit) }}"
rollback_priority: "{{ item['rollback_priority'] | default(omit) }}"
rollback_backup: "{{ item['rollback_backup'] | default(omit) }}"
volumes: "{{ item['volumes'] | default(omit) }}"
connection: local
loop: "{{ consistency_group_rollbacks }}"
vars:
consistency_group_rollbacks: |-
{%- set consistency_group_rollbacks = [] -%}
{%- for rollback in eseries_snapshot_rollbacks | default([]) -%}
{%- set rollback_info = {"group_name": rollback["group_name"]} -%}
{%- if "pit_name" in (rollback.keys() | list) and rollback_info.update({"pit_name": rollback["pit_name"]}) -%}{%- endif -%}
{%- if "pit_timestamp" in (rollback.keys() | list) and rollback_info.update({"pit_timestamp": rollback["pit_timestamp"]}) -%}{%- endif -%}
{%- if "rollback_priority" in (rollback.keys() | list) or eseries_snapshot_rollback_priority is defined -%}
{%- if rollback_info.update({"rollback_priority": rollback["rollback_priority"] | default(eseries_snapshot_rollback_priority)}) -%}{%- endif -%}
{%- endif -%}
{%- if "rollback_backup" in (rollback.keys() | list) or eseries_snapshot_rollback_backup is defined -%}
{%- if rollback_info.update({"rollback_backup": rollback["rollback_backup"] | default(eseries_snapshot_rollback_backup)}) -%}{%- endif -%}
{%- endif -%}
{%- if "volumes" in (rollback.keys() | list) -%}
{%- if rollback_info.update({"volumes": []}) -%}{%- endif -%}
{%- for volume in rollback["volumes"] -%}
{%- if rollback_info["volumes"].append({"volume": volume}) -%}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- if consistency_group_rollbacks.append(rollback_info) -%}{%- endif -%}
{%- endfor -%}
{{- consistency_group_rollbacks -}}

View File

@@ -0,0 +1,116 @@
- name: Determine if any snapshot consistency group views are not specified.
block:
- name: Retrieve all snapshot consistency groups
uri:
url: "{{ current_eseries_api_url }}storage-systems/{{ current_eseries_ssid }}/consistency-groups"
method: GET
url_password: "{{ current_eseries_api_password }}"
url_username: "{{ current_eseries_api_username }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
connection: local
register: existing_consistency_groups
- name: Retrieve all snapshot consistency group views
uri:
url: "{{ current_eseries_api_url }}storage-systems/{{ current_eseries_ssid }}/consistency-groups/views"
method: GET
url_password: "{{ current_eseries_api_password }}"
url_username: "{{ current_eseries_api_username }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
connection: local
register: existing_consistency_group_views
- name: Ensure all unspecified snapshot consistency group views are removed.
na_santricity_snapshot:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: absent
type: view
group_name: "{{ item['group_name'] }}"
view_name: "{{ item['view_name'] }}"
connection: local
loop: "{{ unspecified_groups }}"
vars:
unspecified_groups: |-
{%- set unspecified_group_views = [] -%}
{%- for existing_view in existing_consistency_group_views["json"] -%}
{%- for view in eseries_snapshot_views | default([]) if existing_view["name"] == view["name"] -%}
{#- DO NOTHING -#}
{%- else -%}
{%- for group in existing_consistency_groups["json"] if group["id"] == existing_view["groupRef"] -%}
{%- if unspecified_group_views.append({"group_name": group["name"], "view_name": existing_view["name"]}) -%}{%- endif -%}
{%- endfor -%}
{%- endfor -%}
{%- endfor -%}
{{- unspecified_group_views -}}
when: (eseries_remove_all_configuration | default(False)) == False and eseries_snapshot_remove_unspecified == True
- name: "Ensure all snapshot consistency views {{'exist' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'are removed' }}."
na_santricity_snapshot:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ eseries_remove_all_configuration_state | default('present') }}"
type: view
view_name: "{{ item['name'] }}"
group_name: "{{ item['group_name'] }}"
pit_name: "{{ item['pit_name'] | default(omit) }}"
pit_timestamp: "{{ item['pit_timestamp'] | default(omit) }}"
volumes: "{{ item['volumes'] | default(omit) }}"
reserve_capacity_pct: "{{ item['reserve_capacity_pct'] | default(omit) }}"
preferred_reserve_storage_pool: "{{ item['preferred_reserve_storage_pool'] | default(omit) }}"
alert_threshold_pct: "{{ item['alert_threshold_pct'] | default(omit) }}"
view_host: "{{ item['host'] | default(omit) }}"
view_writable: "{{ item['writable'] | default(omit) }}"
view_validate: "{{ item['validate'] | default(omit) }}"
connection: local
loop: "{{ consistency_group_views }}"
vars:
consistency_group_views: |-
{%- set consistency_group_views = [] -%}
{%- for view in eseries_snapshot_views | default([]) -%}
{%- set view_info = {"name": view["name"], "group_name": view["group_name"]} -%}
{%- if "pit_name" in (view.keys() | list) and view_info.update({"pit_name": view["pit_name"]}) -%}{%- endif -%}
{%- if "pit_timestamp" in (view.keys() | list) and view_info.update({"pit_timestamp": view["pit_timestamp"]}) -%}{%- endif -%}
{%- if "host" in (view.keys() | list) or eseries_snapshot_views_host is defined -%}
{%- if view_info.update({"host": view["host"] | default(eseries_snapshot_views_host)}) -%}{%- endif -%}{%- endif -%}
{%- if "reserve_capacity_pct" in (view.keys() | list) or eseries_snapshot_views_reserve_capacity_pct is defined -%}
{%- if view_info.update({"reserve_capacity_pct": view["reserve_capacity_pct"] | default(eseries_snapshot_views_reserve_capacity_pct)}) -%}{%- endif -%}{%- endif -%}
{%- if "preferred_reserve_storage_pool" in (view.keys() | list) or eseries_snapshot_views_preferred_reserve_storage_pool is defined -%}
{%- if view_info.update({"preferred_reserve_storage_pool": view["preferred_reserve_storage_pool"] | default(eseries_snapshot_views_preferred_reserve_storage_pool)}) -%}{%- endif -%}{%- endif -%}
{%- if "alert_threshold_pct" in (view.keys() | list) or eseries_snapshot_views_alert_threshold_pct is defined -%}
{%- if view_info.update({"alert_threshold_pct": view["alert_threshold_pct"] | default(eseries_snapshot_views_alert_threshold_pct)}) -%}{%- endif -%}{%- endif -%}
{%- if "writable" in (view.keys() | list) or eseries_snapshot_views_writable is defined -%}
{%- if view_info.update({"writable": view["writable"] | default(eseries_snapshot_views_writable)}) -%}{%- endif -%}{%- endif -%}
{%- if "validate" in (view.keys() | list) or eseries_snapshot_views_validate is defined -%}
{%- if view_info.update({"validate": view["validate"] | default(eseries_snapshot_views_validate)}) -%}{%- endif -%}{%- endif -%}
{%- if "alert_threshold_pct" in (view.keys() | list) or eseries_snapshot_views_alert_threshold_pct is defined -%}
{%- if view_info.update({"alert_threshold_pct": view["alert_threshold_pct"] | default(eseries_snapshot_views_alert_threshold_pct)}) -%}{%- endif -%}{%- endif -%}
{%- if "volumes" in (view.keys() | list) -%}
{%- if view_info.update({"volumes": [] }) -%}{%- endif -%}
{%- for volume in view["volumes"] -%}
{%- set volume_info = {"volume": volume["volume"],
"reserve_capacity_pct": volume["reserve_capacity_pct"] | default(view_info["reserve_capacity_pct"] | default(False)),
"snapshot_volume_writable": volume["writable"] | default(view_info["writable"] | default(True)),
"snapshot_volume_validate": volume["validate"] | default(view_info["validate"] | default(False))} -%}
{%- if "host" in (volume.keys() | list) or "host" in (view_info.keys() | list) -%}
{%- if volume_info.update({"snapshot_volume_host": volume["host"] | default(view_info["host"])}) -%}{%- endif -%}{%- endif -%}
{%- if "lun" in (volume.keys() | list) -%}
{%- if volume_info.update({"snapshot_volume_lun": volume["lun"]}) -%}{%- endif -%}{%- endif -%}
{%- if "preferred_reserve_storage_pool" in (volume.keys() | list) or "preferred_reserve_storage_pool" in (view_info.keys() | list) -%}
{%- if volume_info.update({"preferred_reserve_storage_pool": volume["preferred_reserve_storage_pool"] | default(view_info["preferred_reserve_storage_pool"])}) -%}{%- endif -%}{%- endif -%}
{%- if view_info["volumes"].append(volume_info) -%}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- if consistency_group_views.append(view_info) -%}{%- endif -%}
{%- endfor -%}
{{- consistency_group_views -}}

View File

@@ -0,0 +1,27 @@
- name: Unconfigure NetApp E-Series storage system disk pool configuration
na_santricity_storagepool:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ item['state'] }}"
name: "{{ item['name'] }}"
raid_level: "{{ item['raid_level'] | default(eseries_storage_pool_raid_level | default(omit)) }}"
secure_pool: "{{ item['secure_pool'] | default(eseries_storage_pool_secure_pool | default(omit)) }}"
criteria_drive_count: "{{ item['criteria_drive_count'] | default(eseries_storage_pool_criteria_drive_count | default(omit)) }}"
reserve_drive_count: "{{ item['reserve_drive_count'] | default(eseries_storage_pool_reserve_drive_count | default(omit)) }}"
criteria_min_usable_capacity: "{{ item['criteria_min_usable_capacity'] | default(eseries_storage_pool_criteria_min_usable_capacity | default(omit)) }}"
criteria_drive_type: "{{ item['criteria_drive_type'] | default(eseries_storage_pool_criteria_drive_type | default(omit)) }}"
criteria_size_unit: "{{ item['criteria_size_unit'] | default(eseries_storage_pool_criteria_size_unit | default(omit)) }}"
criteria_drive_min_size: "{{ item['criteria_drive_min_size'] | default(eseries_storage_pool_criteria_drive_min_size | default(omit)) }}"
criteria_drive_max_size: "{{ item['criteria_drive_max_size'] | default(eseries_storage_pool_criteria_drive_max_size | default(omit)) }}"
criteria_drive_require_da: "{{ item['criteria_drive_require_da'] | default(eseries_storage_pool_criteria_drive_require_da | default(omit)) }}"
criteria_drive_require_fde: "{{ item['criteria_drive_require_fde'] | default(eseries_storage_pool_criteria_drive_require_fde | default(omit)) }}"
usable_drives: "{{ item['usable_drives'] | default(eseries_storage_pool_usable_drives | default(omit)) }}"
remove_volumes: "{{ item['remove_volumes'] | default(eseries_storage_pool_remove_volumes | default(omit)) }}"
erase_secured_drives: "{{ item['erase_secured_drives'] | default(eseries_storage_pool_erase_secured_drives | default(omit)) }}"
ddp_critical_threshold_pct: "{{ item['ddp_critical_threshold_pct'] | default(eseries_storage_pool_ddp_critical_threshold_pct | default(omit)) }}"
ddp_warning_threshold_pct: "{{ item['ddp_warning_threshold_pct'] | default(eseries_storage_pool_ddp_warning_threshold_pct | default(omit)) }}"
connection: local
loop: "{{ query('netapp_eseries.santricity.santricity_storage_pool', hostvars[inventory_hostname], state='absent') }}"

View File

@@ -0,0 +1,28 @@
- name: Configure NetApp E-Series storage system disk pool configuration
na_santricity_storagepool:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ item['state'] }}"
name: "{{ item['name'] }}"
raid_level: "{{ item['raid_level'] | default(eseries_storage_pool_raid_level | default(omit)) }}"
secure_pool: "{{ item['secure_pool'] | default(eseries_storage_pool_secure_pool | default(omit)) }}"
criteria_drive_count: "{{ item['criteria_drive_count'] | default(eseries_storage_pool_criteria_drive_count | default(omit)) }}"
reserve_drive_count: "{{ item['reserve_drive_count'] | default(eseries_storage_pool_reserve_drive_count | default(omit)) }}"
criteria_min_usable_capacity: "{{ item['criteria_min_usable_capacity'] | default(eseries_storage_pool_criteria_min_usable_capacity | default(omit)) }}"
criteria_drive_type: "{{ item['criteria_drive_type'] | default(eseries_storage_pool_criteria_drive_type | default(omit)) }}"
criteria_drive_interface_type: "{{ item['criteria_drive_interface_type'] | default(eseries_storage_pool_criteria_drive_interface_type | default(omit)) }}"
criteria_size_unit: "{{ item['criteria_size_unit'] | default(eseries_storage_pool_criteria_size_unit | default(omit)) }}"
criteria_drive_min_size: "{{ item['criteria_drive_min_size'] | default(eseries_storage_pool_criteria_drive_min_size | default(omit)) }}"
criteria_drive_max_size: "{{ item['criteria_drive_max_size'] | default(eseries_storage_pool_criteria_drive_max_size | default(omit)) }}"
criteria_drive_require_da: "{{ item['criteria_drive_require_da'] | default(eseries_storage_pool_criteria_drive_require_da | default(omit)) }}"
criteria_drive_require_fde: "{{ item['criteria_drive_require_fde'] | default(eseries_storage_pool_criteria_drive_require_fde | default(omit)) }}"
usable_drives: "{{ item['usable_drives'] | default(eseries_storage_pool_usable_drives | default(omit)) }}"
remove_volumes: "{{ item['remove_volumes'] | default(eseries_storage_pool_remove_volumes | default(omit)) }}"
erase_secured_drives: "{{ item['erase_secured_drives'] | default(eseries_storage_pool_erase_secured_drives | default(omit)) }}"
ddp_critical_threshold_pct: "{{ item['ddp_critical_threshold_pct'] | default(eseries_storage_pool_ddp_critical_threshold_pct | default(omit)) }}"
ddp_warning_threshold_pct: "{{ item['ddp_warning_threshold_pct'] | default(eseries_storage_pool_ddp_warning_threshold_pct | default(omit)) }}"
connection: local
loop: "{{ query('netapp_eseries.santricity.santricity_storage_pool', hostvars[inventory_hostname], state='present') }}"

View File

@@ -0,0 +1,34 @@
- name: "{{'Configure' if (eseries_remove_all_configuration_state | default('present')) == 'present' else 'Unconfigure' }} Netapp E-Series storage system disk pool volume configuration"
na_santricity_volume:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ item['state'] }}"
name: "{{ item['name'] }}"
storage_pool_name: "{{ item['storage_pool_name'] }}"
size: "{{ item['size'] | default(eseries_volume_size | default(omit)) }}"
size_unit: "{{ item['size_unit'] | default(eseries_volume_size_unit | default(omit)) }}"
segment_size_kb: "{{ item['segment_size_kb'] | default(eseries_volume_segment_size_kb | default(omit)) }}"
owning_controller: "{{ item['owning_controller'] | default(eseries_volume_owning_controller | default(omit)) }}"
thin_provision: "{{ item['thin_provision'] | default(eseries_volume_thin_provision | default(omit)) }}"
thin_volume_repo_size: "{{ item['thin_volume_repo_size'] | default(eseries_volume_thin_volume_repo_size | default(omit)) }}"
thin_volume_max_repo_size: "{{ item['thin_volume_max_repo_size'] | default(eseries_volume_thin_volume_max_repo_size | default(omit)) }}"
thin_volume_expansion_policy: "{{ item['thin_volume_expansion_policy'] | default(eseries_volume_thin_volume_expansion_policy | default(omit)) }}"
thin_volume_growth_alert_threshold: "{{ item['thin_volume_growth_alert_threshold'] | default(eseries_volume_thin_volume_growth_alert_threshold | default(omit)) }}"
ssd_cache_enabled: "{{ item['ssd_cache_enabled'] | default(eseries_volume_ssd_cache_enabled | default(omit)) }}"
data_assurance_enabled: "{{ item['data_assurance_enabled'] | default(eseries_volume_data_assurance_enabled | default(omit)) }}"
read_cache_enable: "{{ item['read_cache_enable'] | default(eseries_volume_read_cache_enable | default(omit)) }}"
read_ahead_enable: "{{ item['read_ahead_enable'] | default(eseries_volume_read_ahead_enable | default(omit)) }}"
write_cache_enable: "{{ item['write_cache_enable'] | default(eseries_volume_write_cache_enable | default(omit)) }}"
write_cache_mirror_enable: "{{ item['write_cache_mirror_enable'] | default(eseries_volume_write_cache_mirror_enable | default(omit)) }}"
cache_without_batteries: "{{ item['cache_without_batteries'] | default(eseries_volume_cache_without_batteries | default(omit)) }}"
allow_expansion: "{{ item['allow_expansion'] | default(eseries_volume_allow_expansion | default(omit)) }}"
wait_for_initialization: "{{ item['wait_for_initialization'] | default(eseries_volume_wait_for_initialization | default(omit)) }}"
workload_name: "{{ item['workload_name'] | default(eseries_volume_workload_name | default(omit)) }}"
workload_metadata: "{{ item['workload_metadata'] | default(item['metadata'] | default(eseries_volume_workload_metadata | default(eseries_volume_metadata | default(omit)))) }}"
volume_metadata: "{{ item['volume_metadata'] | default(eseries_volume_volume_metadata | default(omit)) }}"
connection: local
when: eseries_storage_pool_configuration is defined
loop: "{{ query('netapp_eseries.santricity.santricity_volume', hostvars[inventory_hostname]) }}"

View File

@@ -0,0 +1,11 @@
##
## /etc/iscsi/iscsi.initiatorname
##
## Default iSCSI Initiatorname.
##
## DO NOT EDIT OR REMOVE THIS FILE!
## If you remove this file, the iSCSI daemon will not start.
## If you change the InitiatorName, existing access control lists
## may reject this initiator. The InitiatorName must be unique
## for each iSCSI initiator. Do NOT duplicate iSCSI InitiatorNames.
InitiatorName={{ item["stdout_lines"][0] }}

View File

@@ -0,0 +1,29 @@
---
language: python
python: "2.7"
# Use the new container infrastructure
sudo: false
# Install ansible
addons:
apt:
packages:
- python-pip
install:
# Install ansible
- pip install ansible
# Check ansible version
- ansible --version
# Create ansible.cfg with correct roles_path
- printf '[defaults]\nroles_path=../' >ansible.cfg
script:
# Basic role syntax check
- ansible-playbook tests/test.yml -i tests/inventory --syntax-check
notifications:
webhooks: https://galaxy.ansible.com/api/v1/notifications/

View File

@@ -0,0 +1,301 @@
nar_santricity_management
=========
Manages NetApp E-Series storage system's name, passwords, management interfaces, alerts, syslog, auditlog, asup, ldap, certificates, drive firmware and controller firmware.
Requirements
------------
- NetApp E-Series E2800 platform or newer or NetApp E-Series SANtricity Web Services Proxy configured for older E-Series storage systems.
Tested Ansible Versions
-----------------------
- Ansible 5.x (ansible-core 2.12)
Example Playbook
----------------
- hosts: eseries_storage_systems
gather_facts: false
collection:
- netapp_eseries.santricity
tasks:
- name: Ensure NetApp E-Series storage system is properly configured
import_role:
name: nar_santricity_management
Example Storage System Inventory File (Discover storage system with proxy)
-------------------------------------
eseries_system_serial: "012345678901" # Be sure to quote if the serial is all numbers and begins with zero.
eseries_system_password: admin_password
eseries_proxy_api_url: https://192.168.1.100:8443/devmgr/v2/
eseries_proxy_api_password: admin_password
eseries_subnet: 192.168.1.0/24
eseries_prefer_embedded: false # Overrides the default behavior of using Web Services Proxy when eseries_proxy_api_url is defined. This will only effect storage systems that have Embedded Web Services.
eseries_validate_certs: false
eseries_system_name: my_eseries_array
eseries_system_cache_block_size: 128
eseries_system_cache_flush_threshold: 90
eseries_system_autoload_balance: enabled
eseries_system_host_connectivity_reporting: enabled
eseries_system_default_host_type: Linux DM-MP
eseries_management_interfaces:
config_method: static
subnet_mask: 255.255.255.0
gateway: 192.168.1.1
dns_config_method: static
dns_address: 192.168.1.253
dns_address_backup: 192.168.1.254
ssh: true
ntp_config_method: static
ntp_address: 192.168.1.200
ntp_address_backup: 192.168.1.201
controller_a:
- address: 192.168.1.100
- address: 192.168.1.101
controller_b:
- address: 192.168.1.102
- address: 192.168.1.103
eseries_ldap_state: present
eseries_ldap_bind_username:
eseries_ldap_bind_password:
eseries_ldap_server:
eseries_ldap_search_base:
eseries_ldap_role_mappings:
".*":
- storage.admin
- storage.monitor
- support.admin
- security.admin
eseries_client_certificate_certificates:
- /path/to/client_certificate.crt
eseries_server_certificate:
controller_a:
public_certificate: "/path/to/controller_a_server_certificate_bundle.pem"
controller_b:
public_certificate: "/path/to/controller_b_server_certificate_bundle.pem"
eseries_firmware_firmware: "/path/to/firmware.dlp"
eseries_firmware_nvsram: "/path/to/nvsram.dlp"
eseries_drive_firmware_firmware_list:
- "/path/to/drive_firmware.dlp"
eseries_asup_state: enabled
eseries_asup_active: true
eseries_asup_days: [sunday, saturday]
eseries_asup_start: 17
eseries_asup_end: 24
eseries_asup_validate: false
eseries_asup_method: email
eseries_asup_email:
server: smtp.example.com
sender: noreply@example.com
eseries_syslog_state: present
eseries_syslog_address: 192.168.1.150
eseries_syslog_protocol: udp
eseries_syslog_port: 514
eseries_alert_syslog_servers:
- "address": 192.168.1.150
"port": 514
Example Storage System Inventory File (Without storage system discovery)
-------------------------------------
eseries_system_api_url: https://192.168.1.200:8443/devmgr/v2/
eseries_system_password: admin_password
eseries_validate_certs: false
(...) # Same as the previous example
Role Variables
--------------
**Note that when values are specified below, they indicate the default value.**
# Web Services Embedded information
eseries_subnet: # Network subnet to search for the storage system specified in CIDR form. Example: 192.168.1.0/24
eseries_system_serial: # Storage system serial number. Be sure to quote if the serial is all numbers and begins with zero. (This is located on a label at the top-left towards the front on the device)
eseries_system_addresses: # Storage system management IP addresses. Only required when eseries_system_serial or eseries_system_api_url are not defined. When not specified, addresses will be populated with eseries_management_interfaces controller addresses.
eseries_system_api_url: # Url for the storage system's for embedded web services rest api. Example: https://192.168.10.100/devmgr/v2
eseries_system_username: admin # Username for the storage system's for embedded web services rest api
eseries_system_password: # Password for the storage system's for embedded web services rest api and when the admin password has not been set eseries_system_password will be used to set it.
eseries_system_old_password: # Previous admin password. This is used to change the current admin password by setting this variable to the current
# password and eseries_system_password to the new password.
eseries_proxy_ssid: # Arbitrary string for the proxy to represent the storage system. eseries_system_serial will be used when not defined.
eseries_template_api_url: # Template for the web services api url. Default: https://0.0.0.0:8443/devmgr/v2/
eseries_prefer_embedded: false # Overrides the default behavior of using Web Services Proxy when eseries_proxy_api_url is defined. This will only effect storage systems that have Embedded Web Services.
eseries_validate_certs: true # Indicates Whether SSL certificates should be verified. Used for both embedded and proxy. Choices: true, false
# Web Services Proxy information
Note: eseries_proxy_* variables are required to discover storage systems prior to SANtricity OS version 11.60.2.
eseries_proxy_api_url: # Url for the storage system's for proxy web services rest api. Example: https://192.168.10.100/devmgr/v2
eseries_proxy_api_username: # Username for the storage system's for proxy web services rest api.
eseries_proxy_api_password: # Password for the storage system's for proxy web services rest api and when the admin password has not been set
# eseries_proxy_api_password will be used to set it.
# Global storage system information
eseries_system_name: # Name of the storage system.
eseries_system_cache_block_size: # Cache block size
eseries_system_cache_flush_threshold: # Unwritten data will be flushed when exceeds this threshold
eseries_system_autoload_balance: # Whether automatic load balancing should be enabled. Choices: enabled, disabled
eseries_system_host_connectivity_reporting: # Whether host connectivity reporting should be enabled. Choices: enabled, disabled
eseries_system_login_banner_message: # Message that appears prior to the login.
eseries_system_controller_shelf_id: # Controller shelf identifier.
eseries_system_default_host_type: # Only required when using something other than Linux kernel 3.10 or later with DM-MP (Linux DM-MP),
# non-clustered Windows (Windows), or the storage system default host type is incorrect. Common definitions below:
# - AIX MPIO: The Advanced Interactive Executive (AIX) OS and the native MPIO driver
# - AVT 4M: Silicon Graphics, Inc. (SGI) proprietary multipath driver; refer to the SGI installation documentation for more information
# - HP-UX: The HP-UX OS with native multipath driver
# - Linux ATTO: The Linux OS and the ATTO Technology, Inc. driver (must use ATTO FC HBAs)
# - Linux DM-MP: The Linux OS and the native DM-MP driver
# - Linux Pathmanager: The Linux OS and the SGI proprietary multipath driver; refer to the SGI installation documentation for more information
# - Mac: The Mac OS and the ATTO Technology, Inc. driver
# - ONTAP: FlexArray
# - Solaris 11 or later: The Solaris 11 or later OS and the native MPxIO driver
# - Solaris 10 or earlier: The Solaris 10 or earlier OS and the native MPxIO driver
# - SVC: IBM SAN Volume Controller
# - VMware: ESXi OS
# - Windows: Windows Server OS and Windows MPIO with a DSM driver
# - Windows Clustered: Clustered Windows Server OS and Windows MPIO with a DSM driver
# - Windows ATTO: Windows OS and the ATTO Technology, Inc. driver
# Role-based username passwords
eseries_system_monitor_password: # Storage system monitor username password
eseries_system_security_password: # Storage system security username password
eseries_system_storage_password: # Storage system storage username password
eseries_system_support_password: # Storage system support username password
# SSL/TLS certificate configurations
eseries_client_certificate_common_certificates: # List of common client certificate file paths. These files will be appended to each client certificate list.
eseries_client_certificate_certificates: # List of client certificate file paths
eseries_server_certificate_common_certificates: # List of common server certificates. These files will be appended to each controller's server certificate list.
eseries_server_certificate_common_passphrase: # Common passphrase for decrypting PEM (PKCS8) private key.
eseries_server_certificate:
controller_a:
certificates: # List of server certificates for the storage systems controller A. Leave blank to use self-signed certificate.
passphrase: # Passphrase for decrypting PEM (PKCS8) private key.
controller_b:
certificates: # List of server certificates for the storage systems controller B. Leave blank to use self-signed certificate.
passphrase: # Passphrase for decrypting PEM (PKCS8) private key.
# Storage management interface defaults
Note: eseries_management_* variables have the lowest priority and will be overwritten by those found in eseries_management_interfaces; use these to defined host group defaults.
eseries_management_config_method: # Default config method for all management interfaces. Choices: static, dhcp
eseries_management_subnet_mask: # Default subnet mask for all management interfaces
eseries_management_gateway: # Default gateway for all management interfaces
eseries_management_dns_config_method: # Default DNS config method for all management interfaces
eseries_management_dns_address: # Default primary DNS address for all management interfaces
eseries_management_dns_address_backup: # Default backup DNS address for all management interfaces
eseries_management_ntp_config_method: # Default NTP config method for all management interfaces
eseries_management_ntp_address: # Default primary NTP address for all management interfaces
eseries_management_ntp_address_backup: # Default backup NTP address for all management interfaces
eseries_management_ssh: # Default SSH access for all management interfaces. Choices: true, false
eseries_management_interfaces:
config_method: # Config method for all management interfaces. Choices: static, dhcp
subnet_mask: # Subnet mask for all management interfaces
gateway_mask: # Gateway for all management interfaces
dns_config_method: # DNS config method for all management interfaces
dns_address: # Primary DNS address for all management interfaces
dns_address_backup: # Backup DNS address for all management interfaces
ntp_config_method: # NTP config method for all management interfaces
ntp_address: # Primary NTP address for all management interfaces
ntp_address_backup: # Backup NTP address for all management interfaces
ssh: # SSH access for all management interfaces. Choices: true, false
controller_a: # List of controller A ports
- address: # IPv4 address for controller A
config_method: # Config method for controller A. Choices: static, dhcp
subnet_mask: # Subnet mask for controller A
gateway: # Gateway for controller A
dns_config_method: # DNS config method for controller A
dns_address: # Primary DNS address for controller A
dns_address_backup: # Backup DNS address for controller A
ntp_config_method: # NTP config method for controller A
ntp_address: # Primary NTP address for controller A
ntp_address_backup: # Backup NTP address for controller A
ssh: # SSH access for controller A. Choices: true, false
controller_b: # List of controller B ports
- (...) # Same as for controller A but for controller B.
# Alerts configuration defaults
eseries_alerts_state: # Whether to enable storage system alerts. Choices: enabled, disabled
eseries_alerts_contact: # This allows owner to specify free-form contact information such as email or phone number.
eseries_alerts_recipients: # List containing e-mails that should be sent notifications when alerts are issued.
eseries_alerts_sender: # Sender email. This does not necessarily need to be a valid e-mail.
eseries_alerts_server: # Fully qualified domain name, IPv4 address, or IPv6 address of the mail server.
eseries_alerts_test: false # When changes are made to the storage system alert configuration a test e-mail will be sent. Choices: true, false
eseries_alert_syslog_servers: # List of dictionaries where each dictionary contains a syslog server entry. [{"address": <syslog_address>, "port": 514}]
eseries_alert_syslog_test: false # When changes are made to the alerts syslog servers configuration a test message will be sent to them. Choices: true, false
# LDAP configuration defaults
eseries_ldap_state: # Whether LDAP should be configured
eseries_ldap_identifier: # The user attributes that should be considered for the group to role mapping
eseries_ldap_user_attribute: # Attribute used to the provided username during authentication.
eseries_ldap_bind_username: # User account that will be used for querying the LDAP server.
eseries_ldap_bind_password: # Password for the bind user account
eseries_ldap_server: # LDAP server URL.
eseries_ldap_search_base: # Search base used for find user's group membership
eseries_ldap_role_mappings: # Dictionary of user groups, each containing the list of access roles.
# Role choices: storage.admin - allows users full read/writes access to storage objects and operations.
# storage.monitor - allows users read-only access to storage objects and operations.
# storage.admin - allows users access to hardware, diagnostic information, major event logs,
# and other critical support-related functionality, but not the sorage configuration.
# security.admin - allows users access to authentication/authorization configuration, as
# well as the audit log configuration, adn certification management.
# Drive firmware defaults
eseries_drive_firmware_firmware_list: # Local path list for drive firmware.
eseries_drive_firmware_wait_for_completion: # Forces drive firmware upgrades to wait for all associated tasks to complete. Choices: true, false
eseries_drive_firmware_ignore_inaccessible_drives: # Forces drive firmware upgrades to ignore any inaccessible drives. Choices: true, false
eseries_drive_firmware_upgrade_drives_online: # Forces drive firmware upgrades to be performed while I/Os are accepted. Choices: true, false
# Controller firmware defaults
eseries_firmware_nvsram: # Local path for NVSRAM file.
eseries_firmware_firmware: # Local path for controller firmware file.
eseries_firmware_wait_for_completion: # Forces controller firmware upgrade to wait until upgrade has completed before continuing. Choices: true, false
eseries_firmware_clear_mel_events: # Forces firmware upgrade to be attempted regardless of the health check results. Choices: true, false
# Auto-Support configuration defaults
eseries_asup_state: # Whether auto support (ASUP) should be enabled. Choices: enabled, disabled
eseries_asup_active: # Enables active monitoring which allows NetApp support personnel to request support data to resolve issues. Choices: true, false
eseries_asup_days: # List of days of the week. Choices: monday, tuesday, wednesday, thursday, friday, saturday, sunday
eseries_asup_start: # Hour of the day(s) to start ASUP bundle transmissions. Start time must be less than end time. Choices: 0-23
eseries_asup_end: # Hour of the day(s) to end ASUP bundle transmissions. Start time must be less than end time. Choices: 1-24
eseries_asup_method: # ASUP delivery method. Choices https, http, email (default: https)
eseries_asup_routing_type: # ASUP delivery routing type for https or http. Choices: direct, proxy, script (default: direct)
eseries_asup_proxy: # ASUP proxy delivery method information.
host: # ASUP proxy host IP address or FQDN. When eseries_asup_routing_type==proxy this must be specified.
port: # ASUP proxy host port. When eseries_asup_routing_type==proxy this must be specified.
username: # ASUP proxy username.
password: # ASUP proxy password.
script: # ASUP proxy host script.
eseries_asup_email: # ASUP email delivery configuration information
server: # ASUP email server
sender: # ASUP email sender
test_recipient: # ASUP configuration mail test recipient
eseries_maintenance_duration: # Duration in hours (1-72) the ASUP maintenance mode will be active
eseries_maintenance_emails: # List of email addresses for maintenance notifications
eseries_asup_validate: # Verify ASUP configuration prior to applying changes
# Audit-log configuration defaults
eseries_auditlog_enforce_policy: # Whether to make audit-log policy changes. Choices: true, false
eseries_auditlog_force: # Forces audit-log to delete log messages when fullness threshold has been exceeded. Applicable when eseries_auditlog_full_policy=preventSystemAccess. Choices: true, false
eseries_auditlog_full_policy: # Policy for what to do when record limit has been reached. Choices: overWrite, preventSystemAccess
eseries_auditlog_log_level: # Filters logs based on the specified level. Choices: all, writeOnly
eseries_auditlog_max_records: # Maximum number of audit-log messages retained. Choices: 100-50000.
eseries_auditlog_threshold: # Memory full percentage threshold that audit-log will start issuing warning messages. Choices: 60-90
# Syslog configuration defaults
eseries_syslog_state: # Whether syslog servers should be added or removed from storage system. Choices: present, absent
eseries_syslog_address: # Syslog server IPv4 address or fully qualified hostname.
eseries_syslog_test: # Whether a test messages should be sent to syslog server when added to the storage system. Choices: true, false
eseries_syslog_protocol: # Protocol to be used when transmitting log messages to syslog server. Choices: udp, tc, tls
eseries_syslog_port: # Port to be used when transmitting log messages to syslog server.
eseries_syslog_components: # List of components log to syslog server. Choices: auditLog, (others may become available)
License
-------
BSD-3-Clause
Author Information
------------------
Nathan Swartz (@ndswartz)

View File

@@ -0,0 +1,197 @@
# Storage system specific credentials
# -----------------------------------
eseries_system_username: admin # Storage system username. Default: admin
#eseries_system_password: # Storage system admin password.
#eseries_validate_certs: # Whether the SSL certificates should be verified. (boolean)
#eseries_system_subnet: # IPv4 search range for discovering E-Series storage. Must be in CIDR form.
#eseries_system_serial: # Storage system chassis serial number. This is used to automatically discover the system.
#eseries_system_addresses: # (list) Controller address(es) for the storage system. Only applicable for proxy web services.
#eseries_system_tags: # Meta tags to associate to the storage system. Only applicable for proxy web services.
#eseries_system_password: # Required when adding storage systems to SANtricity Web Services Proxy.
#eseries_system_minimum_password_length: # Minimum required password length
# SANtricity Web Services Proxy specific variables
# ------------------------------------------------
#eseries_proxy_ssid: # Storage array identifier. This value will be 1 when interacting with the embedded web services,
#eseries_proxy_api_url: # Url for the web services proxy rest api. Example: https://192.168.10.100:8443/devmgr/v2
#eseries_proxy_api_username: # Username for the web services proxy rest api.
#eseries_proxy_api_password: # Password for the web services proxy rest api.
#eseries_proxy_current_api_password: # This is for changing the password for the proxy.
#eseries_proxy_api_validate_certs: # Whether the SSL certificates should be verified. (boolean)
#eseries_proxy_minimum_password_length: # Minimum required proxy password length
#eseries_proxy_discovery_subnet: # IPv4 search range for discovering E-Series storage. Must be in CIDR form.
#eseries_proxy_accept_certifications: # Force automatic acceptance of all storage system's certificate
#eseries_proxy_default_system_tags: # Default meta tags to associate with all storage systems
#eseries_proxy_default_password: # Default password to associate with all storage systems
#eseries_proxy_systems: # List of storage system information which defines which systems should be added to proxy web services.
# Automatically populated from storage system's inventory when not defined.
# See na_santricity_proxy_systems for more details.
# Storage proxy non-admin passwords
# ---------------------------------
#eseries_proxy_monitor_password: # Proxy monitor username password
#eseries_proxy_security_password: # Proxy security username password
#eseries_proxy_storage_password: # Proxy storage username password
#eseries_proxy_support_password: # Proxy support username password
# Storage system non-admin passwords
# ----------------------------------
#eseries_system_monitor_password: # Storage system monitor username password
#eseries_system_security_password: # Storage system security username password
#eseries_system_storage_password: # Storage system storage username password
#eseries_system_support_password: # Storage system support username password
# Storage system defaults
# -----------------------------
#eseries_system_name: # Name of the storage system.
#eseries_system_cache_block_size: # Cache block size
#eseries_system_cache_flush_threshold: # Unwritten data will be flushed when exceeds this threshold
#eseries_system_autoload_balance: # Whether automatic load balancing should be enabled. Choices: enabled, disabled
#eseries_system_host_connectivity_reporting: # Whether host connectivity reporting should be enabled. Choices: enabled, disabled
#eseries_system_login_banner_message: # Message that appears prior to the login.
#eseries_system_default_host_type: # Only required when using something other than Linux kernel 3.10 or later with DM-MP (Linux DM-MP),
# non-clustered Windows (Windows), or the storage system default host type is incorrect. Common definitions below:
# - AIX MPIO: The Advanced Interactive Executive (AIX) OS and the native MPIO driver
# - AVT 4M: Silicon Graphics, Inc. (SGI) proprietary multipath driver; refer to the SGI installation documentation for more information
# - HP-UX: The HP-UX OS with native multipath driver
# - Linux ATTO: The Linux OS and the ATTO Technology, Inc. driver (must use ATTO FC HBAs)
# - Linux DM-MP: The Linux OS and the native DM-MP driver
# - Linux Pathmanager: The Linux OS and the SGI proprietary multipath driver; refer to the SGI installation documentation for more information
# - Mac: The Mac OS and the ATTO Technology, Inc. driver
# - ONTAP: FlexArray
# - Solaris 11 or later: The Solaris 11 or later OS and the native MPxIO driver
# - Solaris 10 or earlier: The Solaris 10 or earlier OS and the native MPxIO driver
# - SVC: IBM SAN Volume Controller
# - VMware: ESXi OS
# - Windows: Windows Server OS and Windows MPIO with a DSM driver
# - Windows Clustered: Clustered Windows Server OS and Windows MPIO with a DSM driver
# - Windows ATTO: Windows OS and the ATTO Technology, Inc. driver
# Storage system SSL certificates
# -------------------------------
eseries_client_certificate_remove_unspecified_user_certificates: True # Whether existing user certificates should be automatically removed.
#eseries_client_certificate_certificates: # Dictionary containing the SSL certificate file paths. The key will be used as the alias.
#eseries_client_certificate_absent_certificates: # List of aliases to remove from the storage array's trust store.
# Storage management interface defaults
# -------------------------------------
#eseries_management_config_method:
#eseries_management_subnet_mask:
#eseries_management_gateway:
#eseries_management_dns_config_method:
#eseries_management_dns_address:
#eseries_management_dns_address_backup:
#eseries_management_ntp_config_method:
#eseries_management_ntp_address:
#eseries_management_ntp_address_backup:
#eseries_management_ssh:
#eseries_management_interfaces:
# config_method:
# subnet_mask:
# gateway_mask:
# dns_config_method:
# dns_address:
# dns_address_backup:
# ntp_config_method:
# ntp_address:
# ntp_address_backup:
# ssh
# controller_a:
# config_method:
# address:
# subnet_mask:
# gateway:
# dns_config_method:
# dns_address:
# dns_address_backup:
# ntp_config_method:
# ntp_address:
# ntp_address_backup:
# ssh:
# - (...)
# controller_b:
# - (...)
# - (...)
# Alerts configuration defaults
# -----------------------------
#eseries_alerts_state: # Whether to enable storage system alerts. Choices: enabled, disabled
#eseries_alerts_contact: # This allows owner to specify free-form contact information such as email or phone number.
#eseries_alerts_recipients: # List containing e-mails that should be sent notifications when alerts are issued.
#eseries_alerts_sender: # Sender email. This does not necessarily need to be a valid e-mail.
#eseries_alerts_server: # Fully qualified domain name, IPv4 address, or IPv6 address of the mail server.
#eseries_alert_syslog_servers: # List of dictionaries where each dictionary contains a syslog server entry. [{"address": <syslog_address>, "port": 514}]
eseries_alerts_test: false # When changes are made to the storage system alert configuration a test e-mail will be sent. Choices: true, false
eseries_alert_syslog_test: false # When changes are made to the alerts syslog servers configuration a test message will be sent to them. Choices: true, false
# LDAP configuration defaults
# ---------------------------
#eseries_ldap_state: # Whether LDAP should be configured
#eseries_ldap_identifier: memberOf # The user attributes that should be considered for the group to role mapping
#eseries_ldap_user_attribute: sAMAccountName # Attribute used to the provided username during authentication.
#eseries_ldap_bind_username: # User account that will be used for querying the LDAP server.
#eseries_ldap_bind_password: # Password for the bind user account
#eseries_ldap_server: # LDAP server URL.
#eseries_ldap_search_base: # Search base used for find user's group membership
#eseries_ldap_role_mappings: # Dictionary of user groups, each containing the list of access roles.
# Role choices: storage.admin - allows users full read/writes access to storage objects and operations.
# storage.monitor - allows users read-only access to storage objects and operations.
# storage.admin - allows users access to hardware, diagnostic information, major event logs, and
# other critical support-related functionality, but not the sorage configuration.
# security.admin - allows users access to authentication/authorization configuration, as well as
# the audit log configuration, adn certification management.
# Drive firmware defaults
# -----------------------
#eseries_drive_firmware_firmware_list: # Local path list for drive firmware.
eseries_drive_firmware_wait_for_completion: true # Forces drive firmware upgrades to wait for all associated tasks to complete. Choices: true, false
eseries_drive_firmware_ignore_inaccessible_drives: false # Forces drive firmware upgrades to ignore any inaccessible drives. Choices: true, false
eseries_drive_firmware_upgrade_drives_online: true # Forces drive firmware upgrades to be performed while I/Os are accepted. Choices: true, false
# Controller firmware defaults
# ----------------------------
#eseries_firmware_nvsram: # Local path for NVSRAM file.
#eseries_firmware_firmware: # Local path for controller firmware file.
eseries_firmware_wait_for_completion: true # Forces controller firmware upgrade to wait until upgrade has completed before continuing. Choices: true, false
eseries_firmware_ignore_mel_events: false # Forces firmware upgrade to be attempted regardless of the health check results. Choices: true, false
# ASUP configuration defaults
# ---------------------------
#eseries_asup_state: # Whether auto support (ASUP) should be enabled. Choices: enabled, disabled
eseries_asup_active: true # Enables active monitoring which allows NetApp support personnel to request support data to resolve issues. Choices: true, false
#eseries_asup_days: # List of days of the week. Choices: monday, tuesday, wednesday, thursday, friday, saturday, sunday
eseries_asup_start: 0 # Hour of the day(s) to start ASUP bundle transmissions. Start time must be less than end time. Choices: 0-23
eseries_asup_end: 24 # Hour of the day(s) to end ASUP bundle transmissions. Start time must be less than end time. Choices: 1-24
#eseries_asup_method: # ASUP delivery method. Choices https, http, email (default: https)
#eseries_asup_routing_type: # ASUP delivery routing type for https or http. Choices: direct, proxy, script (default: direct)
#eseries_asup_proxy: # ASUP proxy delivery method information.
# host: # ASUP proxy host IP address or FQDN. When eseries_asup_routing_type==proxy this must be specified.
# port: # ASUP proxy host port. When eseries_asup_routing_type==proxy this must be specified.
# script: # ASUP proxy host script.
#eseries_asup_email: # ASUP email delivery configuration information
# server: # ASUP email server
# sender: # ASUP email sender
# test_recipient: # ASUP configuration mail test recipient
#eseries_maintenance_duration: # Duration in hours (1-72) the ASUP maintenance mode will be active
#eseries_maintenance_emails: # List of email addresses for maintenance notifications
#eseries_asup_validate: # Verify ASUP configuration prior to applying changes.
# Audit-log configuration defaults
# --------------------------------
eseries_auditlog_enforce_policy: false # Whether to make audit-log policy changes. Choices: true, false
eseries_auditlog_force: false # Forces audit-log to delete log messages when fullness threshold has been exceeded.
# Applicable when eseries_auditlog_full_policy=preventSystemAccess. Choices: true, false
eseries_auditlog_full_policy: overWrite # Policy for what to do when record limit has been reached. Choices: overWrite, preventSystemAccess
eseries_auditlog_log_level: writeOnly # Filters logs based on the specified level. Choices: all, writeOnly
eseries_auditlog_max_records: 50000 # Maximum number of audit-log messages retained. Choices: 100-50000.
eseries_auditlog_threshold: 90 # Memory full percentage threshold that audit-log will start issuing warning messages. Choices: 60-90
# Syslog configuration defaults
# -----------------------------
#eseries_syslog_state: # Whether syslog servers should be added or removed from storage system. Choices: present, absent
#eseries_syslog_address: # Syslog server IPv4 address or fully qualified hostname.
eseries_syslog_test: false # Whether a test messages should be sent to syslog server when added to the storage system. Choices: true, false
eseries_syslog_protocol: udp # Protocol to be used when transmitting log messages to syslog server. Choices: udp, tc, tls
eseries_syslog_port: 514 # Port to be used when transmitting log messages to syslog server.
eseries_syslog_components: ["auditLog"] # List of components log to syslog server. Choices: auditLog, (others may be available)

View File

@@ -0,0 +1,13 @@
galaxy_info:
author: Nathan Swartz (@ndswartz)
description: Manages NetApp E-Series storage system's firmware, management interfaces, security, system, and logging configuration.
company: NetApp, Inc
license: BSD-3 Clause
platforms: []
min_ansible_version: 2.13
galaxy_tags:
- netapp
- eseries
- storage
dependencies: []

View File

@@ -0,0 +1,83 @@
- name: Upload required drive, nvsram, and firmware files to Web Services Proxy.
block:
- name: Collect expected firmware file lists
ansible.builtin.set_fact:
eseries_proxy_drive_firmware: |-
{%- set drive_firmware = [] %}
{%- for host in ansible_play_hosts_all %}
{%- if hostvars[host]["current_eseries_api_is_proxy"] and "eseries_drive_firmware_firmware_list" in hostvars[host] %}
{%- if drive_firmware.extend(hostvars[host]["eseries_drive_firmware_firmware_list"]) %}{%- endif %}
{%- endif %}
{%- endfor %}
{{ drive_firmware | list }}
eseries_proxy_nvsram: |-
{%- set nvsram = [] %}
{%- for host in ansible_play_hosts_all %}
{%- if hostvars[host]["current_eseries_api_is_proxy"] and "eseries_firmware_nvsram" in hostvars[host] %}
{%- if nvsram.append(hostvars[host]["eseries_firmware_nvsram"]) %}{%- endif %}
{%- endif %}
{%- endfor %}
{{ nvsram | list }}
eseries_proxy_firmware: |-
{%- set firmware = [] %}
{%- for host in ansible_play_hosts_all %}
{%- if hostvars[host]["current_eseries_api_is_proxy"] and "eseries_firmware_firmware" in hostvars[host] %}
{%- if firmware.append(hostvars[host]["eseries_firmware_firmware"]) %}{%- endif %}
{%- endif %}
{%- endfor %}
{{ firmware | list }}
- name: Ensure SANtricity Web Services Proxy has the expected drive firmware
netapp_eseries.santricity.na_santricity_proxy_drive_firmware_upload:
api_url: "{{ eseries_proxy_api_url }}"
api_username: "{{ eseries_proxy_api_username }}"
api_password: "{{ eseries_proxy_api_password }}"
validate_certs: "{{ eseries_validate_certs | default(omit) }}"
firmware: "{{ eseries_proxy_drive_firmware | default(omit) }}"
connection: local
when: eseries_proxy_drive_firmware != []
- name: Ensure SANtricity Web Services Proxy has the expected controller firmware and NVSRAM
netapp_eseries.santricity.na_santricity_proxy_firmware_upload:
api_url: "{{ eseries_proxy_api_url }}"
api_username: "{{ eseries_proxy_api_username }}"
api_password: "{{ eseries_proxy_api_password }}"
validate_certs: "{{ eseries_validate_certs | default(omit) }}"
firmware: "{{ eseries_proxy_firmware | default(omit) + eseries_proxy_nvsram | default(omit) }}"
connection: local
when: eseries_proxy_nvsram != [] or eseries_proxy_firmware != []
run_once: true
- name: Ensure drive firmware is properly configured
netapp_eseries.santricity.na_santricity_drive_firmware:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
firmware: "{{ eseries_drive_firmware_firmware_list }}"
wait_for_completion: "{{ eseries_drive_firmware_wait_for_completion | default(true) }}"
ignore_inaccessible_drives: "{{ eseries_drive_firmware_ignore_inaccessible_drives | default(omit) }}"
upgrade_drives_online: "{{ eseries_drive_firmware_upgrade_drives_online | default(omit) }}"
connection: local
when: eseries_drive_firmware_firmware_list is defined
tags:
- firmware
- drive_firmware
- name: Ensure controller firmware is properly configured
netapp_eseries.santricity.na_santricity_firmware:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
nvsram: "{{ eseries_firmware_nvsram | default('') }}"
firmware: "{{ eseries_firmware_firmware | default('') }}"
wait_for_completion: "{{ eseries_firmware_wait_for_completion | default(true) }}"
clear_mel_events: "{{ eseries_firmware_ignore_mel_events | default(omit) }}"
connection: local
when: eseries_firmware_nvsram is defined or eseries_firmware_firmware is defined
tags:
- firmware
- controller_firmware

View File

@@ -0,0 +1,171 @@
- name: Determine individual management interface information.
ansible.builtin.set_fact:
do_not_remove: 0 # Placeholder to prevent task from failing when no interfaces are defined.
interface_a1: "{{ eseries_management_interfaces['controller_a'][0] | default(omit) }}"
interface_a2: "{{ eseries_management_interfaces['controller_a'][1] | default(omit) }}"
interface_b1: "{{ eseries_management_interfaces['controller_b'][0] | default(omit) }}"
interface_b2: "{{ eseries_management_interfaces['controller_b'][1] | default(omit) }}"
# This task is only executed when no controller A interfaces are defined so global interface options can still be set.
- name: Ensure controller A DNS, NTP and SSH configuration is set.
netapp_eseries.santricity.na_santricity_mgmt_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: A
dns_config_method: "{{ eseries_management_interfaces['dns_config_method'] |
default(eseries_management_dns_config_method | default(omit)) }}"
dns_address: "{{ eseries_management_interfaces['dns_address'] |
default(eseries_management_dns_address | default(omit)) }}"
dns_address_backup: "{{ eseries_management_interfaces['dns_address_backup'] |
default(eseries_management_dns_address_backup | default(omit)) }}"
ntp_config_method: "{{ eseries_management_interfaces['ntp_config_method'] |
default(eseries_management_ntp_config_method | default(omit)) }}"
ntp_address: "{{ eseries_management_interfaces['ntp_address'] |
default(eseries_management_ntp_address | default(omit)) }}"
ntp_address_backup: "{{ eseries_management_interfaces['ntp_address_backup'] |
default(eseries_management_ntp_address_backup | default(omit)) }}"
ssh: "{{ eseries_management_interfaces['ssh'] | default(eseries_management_ssh | default(omit)) }}"
when: interface_a1 is not defined and interface_a2 is not defined
# This task is only executed when no controller B interfaces are defined so global interface options can still be set.
- name: Ensure controller B DNS, NTP and SSH configuration is set.
netapp_eseries.santricity.na_santricity_mgmt_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: B
dns_config_method: "{{ eseries_management_interfaces['dns_config_method'] |
default(eseries_management_dns_config_method | default(omit)) }}"
dns_address: "{{ eseries_management_interfaces['dns_address'] |
default(eseries_management_dns_address | default(omit)) }}"
dns_address_backup: "{{ eseries_management_interfaces['dns_address_backup'] |
default(eseries_management_dns_address_backup | default(omit)) }}"
ntp_config_method: "{{ eseries_management_interfaces['ntp_config_method'] |
default(eseries_management_ntp_config_method | default(omit)) }}"
ntp_address: "{{ eseries_management_interfaces['ntp_address'] |
default(eseries_management_ntp_address | default(omit)) }}"
ntp_address_backup: "{{ eseries_management_interfaces['ntp_address_backup'] |
default(eseries_management_ntp_address_backup | default(omit)) }}"
ssh: "{{ eseries_management_interfaces['ssh'] | default(eseries_management_ssh | default(omit)) }}"
when: interface_b1 is not defined and interface_b2 is not defined
- name: Ensure the management interface (controller A, port 1) has been configured.
block:
- name: Ensure the management interface (controller A, port 1) has been configured.
netapp_eseries.santricity.na_santricity_mgmt_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: A
port: 1
address: "{{ interface_a1['address'] | default(omit) }}"
config_method: "{{ interface_a1['config_method'] | default(eseries_management_interfaces['config_method'] | default(eseries_management_config_method | default(omit))) }}"
subnet_mask: "{{ interface_a1['subnet_mask'] | default(eseries_management_interfaces['subnet_mask'] | default(eseries_management_subnet_mask | default(omit))) }}"
gateway: "{{ interface_a1['gateway'] | default(eseries_management_interfaces['gateway'] | default(eseries_management_gateway | default(omit))) }}"
dns_config_method: "{{ interface_a1['dns_config_method'] | default(eseries_management_interfaces['dns_config_method'] | default(eseries_management_dns_config_method | default(omit))) }}"
dns_address: "{{ interface_a1['dns_address'] | default(eseries_management_interfaces['dns_address'] | default(eseries_management_dns_address | default(omit))) }}"
dns_address_backup: "{{ interface_a1['dns_address_backup'] | default(eseries_management_interfaces['dns_address_backup'] | default(eseries_management_dns_address_backup | default(omit))) }}"
ntp_config_method: "{{ interface_a1['ntp_config_method'] | default(eseries_management_interfaces['ntp_config_method'] | default(eseries_management_ntp_config_method | default(omit))) }}"
ntp_address: "{{ interface_a1['ntp_address'] | default(eseries_management_interfaces['ntp_address'] | default(eseries_management_ntp_address | default(omit))) }}"
ntp_address_backup: "{{ interface_a1['ntp_address_backup'] | default(eseries_management_interfaces['ntp_address_backup'] | default(eseries_management_ntp_address_backup | default(omit))) }}"
ssh: "{{ interface_a1['ssh'] | default(eseries_management_interfaces['ssh'] | default(eseries_management_ssh | default(omit))) }}"
connection: local
register: current_management_urls_a1
- name: Update Web Services URL
ansible.builtin.set_fact:
current_eseries_api_url: "{{ current_management_urls_a1['available_embedded_api_urls'][0] | default(current_eseries_api_url) }}"
when: interface_a1 is defined and interface_a1
- name: Ensure the management interface (controller A, port 2) has been configured.
block:
- name: Ensure the management interface (controller A, port 2) has been configured.
netapp_eseries.santricity.na_santricity_mgmt_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: A
port: 2
address: "{{ interface_a2['address'] | default(omit) }}"
config_method: "{{ interface_a2['config_method'] | default(eseries_management_interfaces['config_method'] | default(eseries_management_config_method | default(omit))) }}"
subnet_mask: "{{ interface_a2['subnet_mask'] | default(eseries_management_interfaces['subnet_mask'] | default(eseries_management_subnet_mask | default(omit))) }}"
gateway: "{{ interface_a2['gateway'] | default(eseries_management_interfaces['gateway'] | default(eseries_management_gateway | default(omit))) }}"
dns_config_method: "{{ interface_a2['dns_config_method'] | default(eseries_management_interfaces['dns_config_method'] | default(eseries_management_dns_config_method | default(omit))) }}"
dns_address: "{{ interface_a2['dns_address'] | default(eseries_management_interfaces['dns_address'] | default(eseries_management_dns_address | default(omit))) }}"
dns_address_backup: "{{ interface_a2['dns_address_backup'] | default(eseries_management_interfaces['dns_address_backup'] | default(eseries_management_dns_address_backup | default(omit))) }}"
ntp_config_method: "{{ interface_a2['ntp_config_method'] | default(eseries_management_interfaces['ntp_config_method'] | default(eseries_management_ntp_config_method | default(omit))) }}"
ntp_address: "{{ interface_a2['ntp_address'] | default(eseries_management_interfaces['ntp_address'] | default(eseries_management_ntp_address | default(omit))) }}"
ntp_address_backup: "{{ interface_a2['ntp_address_backup'] | default(eseries_management_interfaces['ntp_address_backup'] | default(eseries_management_ntp_address_backup | default(omit))) }}"
ssh: "{{ interface_a2['ssh'] | default(eseries_management_interfaces['ssh'] | default(eseries_management_ssh | default(omit))) }}"
connection: local
register: current_management_urls_a2
- name: Try backup Web Services REST API url.
ansible.builtin.set_fact:
current_eseries_api_url: "{{ current_management_urls_a2['available_embedded_api_urls'][0] | default(current_eseries_api_url) }}"
when: interface_a2 is defined and interface_a2
- name: Ensure the management interface (controller B, port 1) has been configured.
block:
- name: Ensure the management interface (controller B, port 1) has been configured.
netapp_eseries.santricity.na_santricity_mgmt_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: B
port: 1
address: "{{ interface_b1['address'] | default(omit) }}"
config_method: "{{ interface_b1['config_method'] | default(eseries_management_interfaces['config_method'] | default(eseries_management_config_method | default(omit))) }}"
subnet_mask: "{{ interface_b1['subnet_mask'] | default(eseries_management_interfaces['subnet_mask'] | default(eseries_management_subnet_mask | default(omit))) }}"
gateway: "{{ interface_b1['gateway'] | default(eseries_management_interfaces['gateway'] | default(eseries_management_gateway | default(omit))) }}"
dns_config_method: "{{ interface_b1['dns_config_method'] | default(eseries_management_interfaces['dns_config_method'] | default(eseries_management_dns_config_method | default(omit))) }}"
dns_address: "{{ interface_b1['dns_address'] | default(eseries_management_interfaces['dns_address'] | default(eseries_management_dns_address | default(omit))) }}"
dns_address_backup: "{{ interface_b1['dns_address_backup'] | default(eseries_management_interfaces['dns_address_backup'] | default(eseries_management_dns_address_backup | default(omit))) }}"
ntp_config_method: "{{ interface_b1['ntp_config_method'] | default(eseries_management_interfaces['ntp_config_method'] | default(eseries_management_ntp_config_method | default(omit))) }}"
ntp_address: "{{ interface_b1['ntp_address'] | default(eseries_management_interfaces['ntp_address'] | default(eseries_management_ntp_address | default(omit))) }}"
ntp_address_backup: "{{ interface_b1['ntp_address_backup'] | default(eseries_management_interfaces['ntp_address_backup'] | default(eseries_management_ntp_address_backup | default(omit))) }}"
ssh: "{{ interface_b1['ssh'] | default(eseries_management_interfaces['ssh'] | default(eseries_management_ssh | default(omit))) }}"
connection: local
register: current_management_urls_b1
- name: Try backup Web Services REST API url.
ansible.builtin.set_fact:
current_eseries_api_url: "{{ current_management_urls_b1['available_embedded_api_urls'][0] | default(current_eseries_api_url) }}"
when: interface_b1 is defined and interface_b1
- name: Ensure the management interface (controller B, port 2) has been configured.
block:
- name: Ensure the management interface (controller B, port 2) has been configured.
netapp_eseries.santricity.na_santricity_mgmt_interface:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: B
port: 2
address: "{{ interface_b2['address'] | default(omit) }}"
config_method: "{{ interface_b2['config_method'] | default(eseries_management_interfaces['config_method'] | default(eseries_management_config_method | default(omit))) }}"
subnet_mask: "{{ interface_b2['subnet_mask'] | default(eseries_management_interfaces['subnet_mask'] | default(eseries_management_subnet_mask | default(omit))) }}"
gateway: "{{ interface_b2['gateway'] | default(eseries_management_interfaces['gateway'] | default(eseries_management_gateway | default(omit))) }}"
dns_config_method: "{{ interface_b2['dns_config_method'] | default(eseries_management_interfaces['dns_config_method'] | default(eseries_management_dns_config_method | default(omit))) }}"
dns_address: "{{ interface_b2['dns_address'] | default(eseries_management_interfaces['dns_address'] | default(eseries_management_dns_address | default(omit))) }}"
dns_address_backup: "{{ interface_b2['dns_address_backup'] | default(eseries_management_interfaces['dns_address_backup'] | default(eseries_management_dns_address_backup | default(omit))) }}"
ntp_config_method: "{{ interface_b2['ntp_config_method'] | default(eseries_management_interfaces['ntp_config_method'] | default(eseries_management_ntp_config_method | default(omit))) }}"
ntp_address: "{{ interface_b2['ntp_address'] | default(eseries_management_interfaces['ntp_address'] | default(eseries_management_ntp_address | default(omit))) }}"
ntp_address_backup: "{{ interface_b2['ntp_address_backup'] | default(eseries_management_interfaces['ntp_address_backup'] | default(eseries_management_ntp_address_backup | default(omit))) }}"
ssh: "{{ interface_b2['ssh'] | default(eseries_management_interfaces['ssh'] | default(eseries_management_ssh | default(omit))) }}"
connection: local
register: current_management_urls_b2
- name: Try backup Web Services REST API url.
ansible.builtin.set_fact:
current_eseries_api_url: "{{ current_management_urls_b2['available_embedded_api_urls'][0] | default(current_eseries_api_url) }}"
when: interface_b2 is defined and interface_b2

View File

@@ -0,0 +1,95 @@
- name: Ensure ASUP configuration
netapp_eseries.santricity.na_santricity_asup:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ eseries_validate_certs | default(omit) }}"
state: "{{ eseries_asup_state }}"
active: "{{ eseries_asup_active | default(omit) }}"
days: "{{ eseries_asup_days | default(omit) }}"
start: "{{ eseries_asup_start | default(omit) }}"
end: "{{ eseries_asup_end | default(omit) }}"
method: "{{ eseries_asup_method | default(omit) }}"
routing_type: "{{ eseries_asup_routing_type | default(omit) }}"
proxy: "{{ eseries_asup_proxy | default(omit) }}"
email: "{{ eseries_asup_email | default(omit) }}"
maintenance_duration: "{{ eseries_maintenance_duration | default(omit) }}"
maintenance_emails: "{{ eseries_maintenance_emails | default(omit) }}"
validate: "{{ eseries_asup_validate | default(omit) }}"
connection: local
when: eseries_asup_state is defined
tags:
- logging
- asup
- name: Ensure alerts have been configured
netapp_eseries.santricity.na_santricity_alerts:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ eseries_validate_certs | default(omit) }}"
state: "{{ eseries_alerts_state }}"
contact: "{{ eseries_alerts_contact | default(omit) }}"
recipients: "{{ eseries_alerts_recipients | default(omit) }}"
sender: "{{ eseries_alerts_sender| default(omit) }}"
server: "{{ eseries_alerts_server | default(omit) }}"
test: "{{ eseries_alerts_test | default(omit) }}"
connection: local
when: eseries_alerts_state is defined
tags:
- logging
- alerts
- name: Ensure auditLog configuration
netapp_eseries.santricity.na_santricity_auditlog:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ eseries_validate_certs | default(omit) }}"
force: "{{ eseries_auditlog_force | default(omit) }}"
full_policy: "{{ eseries_auditlog_full_policy | default(omit) }}"
log_level: "{{ eseries_auditlog_log_level | default(omit) }}"
max_records: "{{ eseries_auditlog_max_records | default(omit) }}"
threshold: "{{ eseries_auditlog_threshold | default(omit) }}"
connection: local
when: eseries_auditlog_enforce_policy
tags:
- logging
- auditlog
- name: Ensure components are configured to be sent to the approriate syslog servers
netapp_eseries.santricity.na_santricity_syslog:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ eseries_validate_certs | default(omit) }}"
state: "{{ eseries_syslog_state }}"
address: "{{ eseries_syslog_address }}"
test: "{{ eseries_syslog_test | default(omit) }}"
protocol: "{{ eseries_syslog_protocol | default(omit) }}"
port: "{{ eseries_syslog_port | default(omit) }}"
components: "{{ eseries_syslog_components | default(omit) }}"
connection: local
when: eseries_syslog_state is defined and eseries_syslog_address is defined
tags:
- logging
- syslog
- name: Ensure alerts are configured to be sent to the approriate syslog servers
netapp_eseries.santricity.na_santricity_alerts_syslog:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ eseries_validate_certs | default(omit) }}"
servers: "{{ eseries_alert_syslog_servers | default(omit) }}"
test: "{{ eseries_alert_syslog_test | default(omit) }}"
connection: local
when: eseries_syslog_state is defined and eseries_syslog_address is defined
tags:
- logging
- syslog

View File

@@ -0,0 +1,27 @@
- name: Set current storage system credentials
ansible.builtin.include_role:
name: netapp_eseries.santricity.nar_santricity_common
tasks_from: build_info.yml
when: current_eseries_api_url is not defined
tags:
- always
- name: Ensure security settings are configured
ansible.builtin.import_tasks: security.yml
- name: Ensure management interfaces are configured
ansible.builtin.import_tasks: interface.yml
tags:
- interface
- ntp
- dns
- ssh
- name: Ensure all global system settings are configured
ansible.builtin.import_tasks: system.yml
- name: Ensure event logging has been configured
ansible.builtin.import_tasks: logging.yml
- name: Ensure drive and controller firmware are correct
ansible.builtin.import_tasks: firmware.yml

View File

@@ -0,0 +1,213 @@
- name: Ensure admin password is set and is correct
netapp_eseries.santricity.na_santricity_auth:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: |-
{%- if current_eseries_api_is_proxy == True -%}
{{- current_eseries_api_password -}}
{%- else -%}
{{- eseries_system_old_password | default(current_eseries_api_password) -}}
{%- endif -%}
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
current_admin_password: |-
{%- if current_eseries_api_is_proxy == True -%}
{{- eseries_system_old_password | default(eseries_system_password) -}}
{%- else -%}
{{- omit -}}
{%- endif -%}
user: admin
password: "{{ eseries_system_password }}"
connection: local
register: admin_password
when: eseries_system_password is defined
tags:
- always
- name: Update current_eseries_api_password if storage system password changed.
block:
- name: Update current_eseries_api_password.
ansible.builtin.set_fact:
current_eseries_api_password: |-
{%- if current_eseries_api_is_proxy == True -%}
{{- current_eseries_api_password -}}
{%- else -%}
{{- eseries_system_password -}}
{%- endif -%}
no_log: true
- name: Wait for password to update
ansible.builtin.pause:
seconds: 5
when: admin_password['changed'] == True
- name: Ensure non-admin passwords have been set
netapp_eseries.santricity.na_santricity_auth:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
current_admin_password: |-
{%- if current_eseries_api_is_proxy == True -%}
{{- eseries_system_password -}}
{%- else -%}
{{- omit -}}
{%- endif -%}
user: "{{ item['key'] }}"
password: "{{ item['value'] }}"
connection: local
loop: "{{ lookup('dict', non_admin_user_authentication, wantlist=True) }}"
vars:
non_admin_user_authentication: |-
{%- set non_admin_list = {} %}
{%- if eseries_system_monitor_password is defined and eseries_system_monitor_password and non_admin_list.update({"monitor": eseries_system_monitor_password})%}{%- endif %}
{%- if eseries_system_security_password is defined and eseries_system_security_password and non_admin_list.update({"security": eseries_system_security_password})%}{%- endif %}
{%- if eseries_system_storage_password is defined and eseries_system_storage_password and non_admin_list.update({"storage": eseries_system_storage_password})%}{%- endif %}
{%- if eseries_system_support_password is defined and eseries_system_support_password and non_admin_list.update({"support": eseries_system_support_password})%}{%- endif %}
{{ non_admin_list }}
- name: Ensure client certificates are installed
netapp_eseries.santricity.na_santricity_client_certificate:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
certificates: "{{ certificates }}"
remove_unspecified_user_certificates: "{{ eseries_client_certificate_remove_unspecified_user_certificates | default(omit) }}"
connection: local
when: eseries_client_certificate_certificates is defined or eseries_client_certificate_common_certificates is defined
tags:
- security
- certificates
vars:
certificates: |-
{%- set certs = [] -%}
{#- Add common client certificates -#}
{%- if eseries_client_certificate_common_certificates is defined -%}
{%- if eseries_client_certificate_common_certificates is string -%}
{%- if certs.append(eseries_client_certificate_common_certificates) -%}{%- endif -%}
{%- elif eseries_client_certificate_common_certificates is iterable -%}
{%- if certs.extend(eseries_client_certificate_common_certificates) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{#- Add controller A client certificates -#}
{%- if eseries_client_certificate_certificates is defined -%}
{%- if eseries_client_certificate_certificates is string -%}
{%- if eseries_client_certificate_certificates not in certs -%}
{%- if certs.append(eseries_client_certificate_certificates) -%}{%- endif -%}
{%- endif -%}
{%- elif eseries_client_certificate_certificates is iterable -%}
{%- for client_cert in eseries_client_certificate_certificates if client_cert not in certs -%}
{%- if certs.append(client_cert) -%}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endif -%}
{{- certs -}}
- name: Ensure controller A server certificates are installed
netapp_eseries.santricity.na_santricity_server_certificate:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: "A"
certificates: "{{ certificates }}"
passphrase: "{{ eseries_server_certificate['controller_a']['passphrase'] | default(eseries_server_certificate_common_passphrase | default(omit)) }}"
connection: local
when: eseries_server_certificate_common_certificates is defined or eseries_server_certificate['controller_a'] is defined or eseries_server_certificate['controller_a']['certificates'] is defined
tags:
- security
- certificates
vars:
certificates: |-
{%- set certs = [] -%}
{#- Add common server certificates -#}
{%- if eseries_server_certificate_common_certificates is defined -%}
{%- if eseries_server_certificate_common_certificates is string -%}
{%- if certs.append(eseries_server_certificate_common_certificates) -%}{%- endif -%}
{%- elif eseries_server_certificate_common_certificates is iterable -%}
{%- if certs.extend(eseries_server_certificate_common_certificates) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{#- Add controller A certificates -#}
{%- if eseries_server_certificate is defined and eseries_server_certificate["controller_a"] is defined or eseries_server_certificate["controller_b"]["certificates"] is defined -%}
{%- if eseries_server_certificate["controller_a"]["certificates"] is string -%}
{%- if eseries_server_certificate["controller_a"]["certificates"] not in certs -%}
{%- if certs.append(eseries_server_certificate["controller_a"]["certificates"]) -%}{%- endif -%}
{%- endif -%}
{%- elif eseries_server_certificate["controller_a"]["certificates"] is iterable -%}
{%- for server_cert in eseries_server_certificate["controller_a"]["certificates"] if server_cert not in certs -%}
{%- if certs.append(server_cert) -%}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endif -%}
{{- certs -}}
- name: Ensure controller B server certificates are installed
netapp_eseries.santricity.na_santricity_server_certificate:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
controller: "B"
certificates: "{{ certificates }}"
passphrase: "{{ eseries_server_certificate['controller_b']['passphrase'] | default(eseries_server_certificate_common_passphrase | default(omit)) }}"
connection: local
when: eseries_server_certificate_common_certificates is defined or eseries_server_certificate['controller_b'] is defined or eseries_server_certificate['controller_b']['certificates'] is defined
tags:
- security
- certificates
vars:
certificates: |-
{%- set certs = [] -%}
{#- Add common server certificates -#}
{%- if eseries_server_certificate_common_certificates is defined -%}
{%- if eseries_server_certificate_common_certificates is string -%}
{%- if certs.append(eseries_server_certificate_common_certificates) -%}{%- endif -%}
{%- elif eseries_server_certificate_common_certificates is iterable -%}
{%- if certs.extend(eseries_server_certificate_common_certificates) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{#- Add controller B certificates -#}
{%- if eseries_server_certificate is defined and eseries_server_certificate["controller_b"] is defined or eseries_server_certificate["controller_b"]["certificates"] is defined -%}
{%- if eseries_server_certificate["controller_b"]["certificates"] is string -%}
{%- if eseries_server_certificate["controller_b"] not in certs -%}
{%- if certs.append(eseries_server_certificate["controller_b"]["certificates"]) -%}{%- endif -%}
{%- endif -%}
{%- elif eseries_server_certificate["controller_b"]["certificates"] is iterable -%}
{%- for server_cert in eseries_server_certificate["controller_b"]["certificates"] if server_cert not in certs -%}
{%- if certs.append(server_cert) -%}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endif -%}
{{- certs -}}
- name: Ensure LDAP has been configured
netapp_eseries.santricity.na_santricity_ldap:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
state: "{{ eseries_ldap_state }}"
identifier: "{{ eseries_ldap_identifier | default(omit) }}"
server_url: "{{ eseries_ldap_server | default(omit) }}"
bind_user: "{{ eseries_ldap_bind_username | default(omit) }}"
bind_password: "{{ eseries_ldap_bind_password | default(omit) }}"
search_base: "{{ eseries_ldap_search_base | default(omit) }}"
user_attribute: "{{ eseries_ldap_user_attribute | default(omit) }}"
role_mappings: "{{ eseries_ldap_role_mappings | default(omit) }}"
connection: local
when: eseries_ldap_state is defined
tags:
- security
- ldap

View File

@@ -0,0 +1,26 @@
- name: Ensure storage array has the correct array globals
netapp_eseries.santricity.na_santricity_global:
ssid: "{{ current_eseries_ssid }}"
api_url: "{{ current_eseries_api_url }}"
api_username: "{{ current_eseries_api_username }}"
api_password: "{{ current_eseries_api_password }}"
validate_certs: "{{ current_eseries_validate_certs | default(omit) }}"
name: "{{ eseries_system_name | default(omit) }}"
cache_block_size: "{{ eseries_system_cache_block_size | default(omit) }}"
cache_flush_threshold: "{{ eseries_system_cache_flush_threshold | default(omit) }}"
automatic_load_balancing: "{{ eseries_system_autoload_balance | default(omit) }}"
host_connectivity_reporting: "{{ eseries_system_host_connectivity_reporting | default(omit) }}"
default_host_type: "{{ eseries_system_default_host_type | default(omit) }}"
login_banner_message: "{{ eseries_system_login_banner_message | default(omit) }}"
controller_shelf_id: "{{ eseries_system_controller_shelf_id | default(omit) }}"
connection: local
when: "eseries_system_name is defined or
eseries_system_cache_block_size is defined or
eseries_system_cache_flush_threshold is defined or
eseries_system_autoload_balance is defined or
eseries_system_host_connectivity_reporting is defined or
eseries_system_default_host_type is defined or
eseries_system_login_banner_message is defined or
eseries_system_controller_shelf_id is defined"
tags:
- system