summaryrefslogtreecommitdiffstats
path: root/ansible_collections/netapp_eseries/santricity/roles
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/netapp_eseries/santricity/roles
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/netapp_eseries/santricity/roles')
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/.travis.yml29
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/README.md149
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/defaults/main.yml45
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/meta/main.yml13
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/build_info.yml38
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/discovery.yml64
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/prefer_embedded.yml150
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/prefer_proxy.yml107
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/validate_system_api_url.yml34
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/main.yml14
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/proxy.yml49
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/proxy_security.yml241
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/README.md443
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/defaults/main.yml367
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/meta/main.yml19
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/initiator.yml114
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface.yml27
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/ib_iser.yml29
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/iscsi.yml56
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/nvme_ib.yml29
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/nvme_roce.yml41
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/lun_mapping.yml178
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/main.yml52
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot.yml19
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/group.yml75
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/rollback.yml41
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/view.yml116
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/storage_pool_absent.yml27
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/storage_pool_present.yml28
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/volume.yml34
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/templates/hostnqn.j21
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/templates/initiatorname_iscsi.j211
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/.travis.yml29
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/README.md301
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/defaults/main.yml197
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/meta/main.yml13
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/firmware.yml83
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/interface.yml171
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/logging.yml95
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/main.yml27
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/security.yml213
-rw-r--r--ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/system.yml26
42 files changed, 3795 insertions, 0 deletions
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/.travis.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/.travis.yml
new file mode 100644
index 000000000..36bbf6208
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/.travis.yml
@@ -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/ \ No newline at end of file
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/README.md b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/README.md
new file mode 100644
index 000000000..b5ae41037
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/README.md
@@ -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)
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/defaults/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/defaults/main.yml
new file mode 100644
index 000000000..4c0233b24
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/defaults/main.yml
@@ -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.
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/meta/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/meta/main.yml
new file mode 100644
index 000000000..62da5894a
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/meta/main.yml
@@ -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: [] \ No newline at end of file
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/build_info.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/build_info.yml
new file mode 100644
index 000000000..a78af62ff
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/build_info.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/discovery.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/discovery.yml
new file mode 100644
index 000000000..3a5e0da49
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/discovery.yml
@@ -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 }}
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/prefer_embedded.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/prefer_embedded.yml
new file mode 100644
index 000000000..e9fb16bc7
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/prefer_embedded.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/prefer_proxy.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/prefer_proxy.yml
new file mode 100644
index 000000000..593a5c57c
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/prefer_proxy.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/validate_system_api_url.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/validate_system_api_url.yml
new file mode 100644
index 000000000..709239d8e
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/collect_facts/validate_system_api_url.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/main.yml
new file mode 100644
index 000000000..ba568b99f
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/main.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/proxy.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/proxy.yml
new file mode 100644
index 000000000..965801d2f
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/proxy.yml
@@ -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 }}
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/proxy_security.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/proxy_security.yml
new file mode 100644
index 000000000..6cfb60246
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_common/tasks/proxy_security.yml
@@ -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 }}
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/README.md b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/README.md
new file mode 100644
index 000000000..011b98565
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/README.md
@@ -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)
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/defaults/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/defaults/main.yml
new file mode 100644
index 000000000..da9db4c7d
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/defaults/main.yml
@@ -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 \ No newline at end of file
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/meta/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/meta/main.yml
new file mode 100644
index 000000000..05169af14
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/meta/main.yml
@@ -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: []
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/initiator.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/initiator.yml
new file mode 100644
index 000000000..4d40051d5
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/initiator.yml
@@ -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"
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface.yml
new file mode 100644
index 000000000..673084908
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/ib_iser.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/ib_iser.yml
new file mode 100644
index 000000000..01d253647
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/ib_iser.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/iscsi.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/iscsi.yml
new file mode 100644
index 000000000..7bc047ec5
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/iscsi.yml
@@ -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)
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/nvme_ib.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/nvme_ib.yml
new file mode 100644
index 000000000..d39e3b504
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/nvme_ib.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/nvme_roce.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/nvme_roce.yml
new file mode 100644
index 000000000..fae92f8a6
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/interface/nvme_roce.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/lun_mapping.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/lun_mapping.yml
new file mode 100644
index 000000000..395a5d399
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/lun_mapping.yml
@@ -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 != []
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/main.yml
new file mode 100644
index 000000000..d19ff8427
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/main.yml
@@ -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)
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot.yml
new file mode 100644
index 000000000..c99c2861b
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/group.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/group.yml
new file mode 100644
index 000000000..473226f1d
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/group.yml
@@ -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 -}}
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/rollback.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/rollback.yml
new file mode 100644
index 000000000..45fae418e
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/rollback.yml
@@ -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 -}}
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/view.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/view.yml
new file mode 100644
index 000000000..f8de06c6c
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/snapshot/view.yml
@@ -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 -}} \ No newline at end of file
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/storage_pool_absent.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/storage_pool_absent.yml
new file mode 100644
index 000000000..49e2c2d35
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/storage_pool_absent.yml
@@ -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') }}"
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/storage_pool_present.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/storage_pool_present.yml
new file mode 100644
index 000000000..d90430ab4
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/storage_pool_present.yml
@@ -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') }}"
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/volume.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/volume.yml
new file mode 100644
index 000000000..86a32ac29
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/tasks/volume.yml
@@ -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]) }}"
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/templates/hostnqn.j2 b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/templates/hostnqn.j2
new file mode 100644
index 000000000..90478d074
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/templates/hostnqn.j2
@@ -0,0 +1 @@
+{{ item["stdout_lines"][0] }}
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/templates/initiatorname_iscsi.j2 b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/templates/initiatorname_iscsi.j2
new file mode 100644
index 000000000..f6c3740eb
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_host/templates/initiatorname_iscsi.j2
@@ -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] }}
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/.travis.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/.travis.yml
new file mode 100644
index 000000000..36bbf6208
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/.travis.yml
@@ -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/ \ No newline at end of file
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/README.md b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/README.md
new file mode 100644
index 000000000..d5b454c96
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/README.md
@@ -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)
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/defaults/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/defaults/main.yml
new file mode 100644
index 000000000..9e99c7d2f
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/defaults/main.yml
@@ -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)
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/meta/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/meta/main.yml
new file mode 100644
index 000000000..a519eeceb
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/meta/main.yml
@@ -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: [] \ No newline at end of file
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/firmware.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/firmware.yml
new file mode 100644
index 000000000..d53d2568c
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/firmware.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/interface.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/interface.yml
new file mode 100644
index 000000000..2e8f535fe
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/interface.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/logging.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/logging.yml
new file mode 100644
index 000000000..852f22793
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/logging.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/main.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/main.yml
new file mode 100644
index 000000000..f2b2bbe6e
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/main.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/security.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/security.yml
new file mode 100644
index 000000000..d176b1922
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/security.yml
@@ -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
diff --git a/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/system.yml b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/system.yml
new file mode 100644
index 000000000..8bcf87cda
--- /dev/null
+++ b/ansible_collections/netapp_eseries/santricity/roles/nar_santricity_management/tasks/system.yml
@@ -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