2018-08-24 16:44:59 +02:00
|
|
|
---
|
|
|
|
# Test code for the netapp_e_host module
|
|
|
|
# (c) 2018, NetApp, Inc
|
|
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
|
|
|
|
- name: NetApp Test Host module
|
|
|
|
fail:
|
|
|
|
msg: 'Please define netapp_e_api_username, netapp_e_api_password, netapp_e_api_host, and netapp_e_ssid.'
|
|
|
|
when: netapp_e_api_username is undefined or netapp_e_api_password is undefined or
|
|
|
|
netapp_e_api_host is undefined or netapp_e_ssid is undefined
|
|
|
|
vars:
|
|
|
|
gather_facts: yes
|
|
|
|
credentials: &creds
|
|
|
|
api_url: "https://{{ netapp_e_api_host }}/devmgr/v2"
|
|
|
|
api_username: "{{ netapp_e_api_username }}"
|
|
|
|
api_password: "{{ netapp_e_api_password }}"
|
|
|
|
ssid: "{{ netapp_e_ssid }}"
|
|
|
|
validate_certs: no
|
|
|
|
hosts: &hosts
|
|
|
|
1:
|
|
|
|
host_type: 27
|
|
|
|
update_host_type: 28
|
|
|
|
ports:
|
|
|
|
- type: 'iscsi'
|
|
|
|
label: 'I_1'
|
|
|
|
port: 'iqn.1996-04.de.suse:01:56f86f9bd1fe'
|
|
|
|
- type: 'iscsi'
|
|
|
|
label: 'I_2'
|
|
|
|
port: 'iqn.1996-04.de.suse:01:56f86f9bd1ff'
|
|
|
|
ports2:
|
|
|
|
- type: 'iscsi'
|
|
|
|
label: 'I_1'
|
|
|
|
port: 'iqn.1996-04.de.suse:01:56f86f9bd1fe'
|
|
|
|
- type: 'iscsi'
|
|
|
|
label: 'I_2'
|
|
|
|
port: 'iqn.1996-04.de.suse:01:56f86f9bd1ff'
|
|
|
|
- type: 'fc'
|
|
|
|
label: 'FC_3'
|
|
|
|
port: '10:00:8C:7C:FF:1A:B9:01'
|
|
|
|
2:
|
|
|
|
host_type: 27
|
|
|
|
update_host_type: 28
|
|
|
|
ports:
|
|
|
|
- type: 'fc'
|
|
|
|
label: 'FC_1'
|
|
|
|
port: '10:00:8C:7C:FF:1A:B9:01'
|
|
|
|
- type: 'fc'
|
|
|
|
label: 'FC_2'
|
|
|
|
port: '10:00:8C:7C:FF:1A:B9:00'
|
|
|
|
ports2:
|
|
|
|
- type: 'fc'
|
|
|
|
label: 'FC_6'
|
|
|
|
port: '10:00:8C:7C:FF:1A:B9:01'
|
|
|
|
- type: 'fc'
|
|
|
|
label: 'FC_4'
|
|
|
|
port: '10:00:8C:7C:FF:1A:B9:00'
|
|
|
|
|
|
|
|
|
|
|
|
# ********************************************
|
|
|
|
# *** Ensure jmespath package is installed ***
|
|
|
|
# ********************************************
|
|
|
|
# NOTE: jmespath must be installed for the json_query filter
|
|
|
|
- name: Ensure that jmespath is installed
|
|
|
|
pip:
|
|
|
|
name: jmespath
|
|
|
|
state: present
|
|
|
|
register: jmespath
|
|
|
|
- fail:
|
|
|
|
msg: "Restart playbook, the jmespath package was installed and is need for the playbook's execution."
|
|
|
|
when: jmespath.changed
|
|
|
|
|
|
|
|
|
|
|
|
# *****************************************
|
|
|
|
# *** Set credential and host variables ***
|
|
|
|
# *****************************************
|
|
|
|
- name: Set hosts variable
|
|
|
|
set_fact:
|
|
|
|
hosts: *hosts
|
|
|
|
- name: set credentials
|
|
|
|
set_fact:
|
|
|
|
credentials: *creds
|
|
|
|
- name: Show some debug information
|
|
|
|
debug:
|
|
|
|
msg: "Using user={{ credentials.api_username }} on server={{ credentials.api_url }}."
|
|
|
|
|
|
|
|
# *** Remove any existing hosts to set initial state and verify state ***
|
|
|
|
- name: Remove any existing hosts
|
|
|
|
netapp_e_host:
|
|
|
|
<<: *creds
|
|
|
|
state: absent
|
|
|
|
name: "{{ item.key }}"
|
|
|
|
with_dict: *hosts
|
|
|
|
|
|
|
|
# Retrieve array host definitions
|
|
|
|
- name: HTTP request for all host definitions from array
|
|
|
|
uri:
|
|
|
|
url: "{{ credentials.api_url }}/storage-systems/{{ credentials.ssid }}/hosts"
|
|
|
|
user: "{{ credentials.api_username }}"
|
|
|
|
password: "{{ credentials.api_password }}"
|
|
|
|
body_format: json
|
|
|
|
validate_certs: no
|
|
|
|
register: result
|
|
|
|
|
|
|
|
# Verify that host 1 and 2 host objects do not exist
|
|
|
|
- name: Collect host side port labels
|
|
|
|
set_fact:
|
|
|
|
host_labels: "{{ result | json_query('json[*].label') }}"
|
|
|
|
- name: Assert hosts were removed
|
|
|
|
assert:
|
|
|
|
that: "'{{ item.key }}' not in host_labels"
|
|
|
|
msg: "Host, {{ item.key }}, failed to be removed from the hosts!"
|
|
|
|
loop: "{{ lookup('dict', hosts) }}"
|
|
|
|
|
|
|
|
|
|
|
|
# *****************************************************************
|
|
|
|
# *** Create host definitions and validate host object creation ***
|
|
|
|
# *****************************************************************
|
|
|
|
- name: Define hosts
|
|
|
|
netapp_e_host:
|
|
|
|
<<: *creds
|
|
|
|
state: present
|
|
|
|
host_type: "{{ item.value.host_type }}"
|
|
|
|
ports: "{{ item.value.ports }}"
|
|
|
|
name: "{{ item.key }}"
|
|
|
|
with_dict: *hosts
|
|
|
|
|
|
|
|
# Retrieve array host definitions
|
|
|
|
- name: https request to validate host definitions were created
|
|
|
|
uri:
|
|
|
|
url: "{{ credentials.api_url }}/storage-systems/{{ credentials.ssid }}/hosts"
|
|
|
|
user: "{{ credentials.api_username }}"
|
|
|
|
password: "{{ credentials.api_password }}"
|
|
|
|
body_format: json
|
|
|
|
validate_certs: no
|
|
|
|
register: result
|
|
|
|
|
|
|
|
# Verify hosts were indeed created
|
|
|
|
- name: Collect host label list
|
|
|
|
set_fact:
|
|
|
|
hosts_labels: "{{ result | json_query('json[*].label') }}"
|
|
|
|
- name: Validate hosts were in fact created
|
|
|
|
assert:
|
|
|
|
that: "'{{ item.key }}' in hosts_labels"
|
|
|
|
msg: "host, {{ item.key }}, not define on array!"
|
|
|
|
loop: "{{ lookup('dict', hosts) }}"
|
|
|
|
|
|
|
|
# *** Update with no state changes results in no changes ***
|
|
|
|
- name: Redefine hosts, expecting no changes
|
|
|
|
netapp_e_host:
|
|
|
|
<<: *creds
|
|
|
|
state: present
|
|
|
|
host_type: "{{ item.value.host_type }}"
|
|
|
|
ports: "{{ item.value.ports }}"
|
|
|
|
name: "{{ item.key }}"
|
|
|
|
with_dict: *hosts
|
|
|
|
register: result
|
|
|
|
|
|
|
|
# Verify that no changes occurred
|
|
|
|
- name: Ensure no change occurred
|
|
|
|
assert:
|
|
|
|
msg: "A change was not detected!"
|
|
|
|
that: "not result.changed"
|
|
|
|
|
|
|
|
|
|
|
|
# ***********************************************************************************
|
|
|
|
# *** Redefine hosts using ports2 host definitions and validate the updated state ***
|
|
|
|
# ***********************************************************************************
|
|
|
|
- name: Redefine hosts, expecting changes
|
|
|
|
netapp_e_host:
|
|
|
|
<<: *creds
|
|
|
|
state: present
|
|
|
|
host_type: "{{ item.value.host_type }}"
|
|
|
|
ports: "{{ item.value.ports2 }}"
|
|
|
|
name: "{{ item.key }}"
|
|
|
|
force_port: yes
|
|
|
|
with_dict: *hosts
|
|
|
|
register: result
|
|
|
|
|
|
|
|
# Request from the array all host definitions
|
|
|
|
- name: HTTP request for port information
|
|
|
|
uri:
|
|
|
|
url: "{{ credentials.api_url }}/storage-systems/{{ credentials.ssid }}/hosts"
|
|
|
|
user: "{{ credentials.api_username }}"
|
|
|
|
password: "{{ credentials.api_password }}"
|
|
|
|
body_format: json
|
|
|
|
validate_certs: no
|
|
|
|
register: result
|
|
|
|
|
|
|
|
# Compile a list of array host port information for verifying changes
|
|
|
|
- name: Compile array host port information list
|
|
|
|
set_fact:
|
|
|
|
tmp: []
|
|
|
|
|
|
|
|
# Append each loop to the previous extraction. Each loop consists of host definitions and the filters will perform
|
|
|
|
# the following: grab host side port lists; combine to each list a dictionary containing the host name(label);
|
|
|
|
# lastly, convert the zip_longest object into a list
|
|
|
|
- set_fact:
|
|
|
|
tmp: "{{ tmp }} + {{ [item | json_query('hostSidePorts[*]')] |
|
|
|
|
zip_longest([], fillvalue={'host_name': item.label}) | list }}"
|
|
|
|
loop: "{{ result.json }}"
|
|
|
|
|
|
|
|
# Make new list, port_info, by combining each list entry's dictionaries into a single dictionary
|
|
|
|
- name: Create port information list
|
|
|
|
set_fact:
|
|
|
|
port_info: []
|
|
|
|
- set_fact:
|
2019-06-06 21:36:22 +02:00
|
|
|
port_info: "{{ port_info + [item[0] |combine(item[1])] }}"
|
2018-08-24 16:44:59 +02:00
|
|
|
loop: "{{ tmp }}"
|
|
|
|
|
|
|
|
# Compile list of expected host port information for verifying changes
|
|
|
|
- name: Create expected port information list
|
|
|
|
set_fact:
|
|
|
|
tmp: []
|
|
|
|
|
|
|
|
# Append each loop to the previous extraction. Each loop consists of host definitions and the filters will perform
|
|
|
|
# the following: grab host side port lists; combine to each list a dictionary containing the host name(label);
|
|
|
|
# lastly, convert the zip_longest object into a list
|
|
|
|
- set_fact:
|
|
|
|
tmp: "{{ tmp }} + {{ [item | json_query('value.ports2[*]')]|
|
|
|
|
zip_longest([], fillvalue={'host_name': item.key|string}) | list }}"
|
|
|
|
loop: "{{ lookup('dict', hosts) }}"
|
|
|
|
|
|
|
|
# Make new list, expected_port_info, by combining each list entry's dictionaries into a single dictionary
|
|
|
|
- name: Create expected port information list
|
|
|
|
set_fact:
|
|
|
|
expected_port_info: []
|
|
|
|
- set_fact:
|
2019-06-06 21:36:22 +02:00
|
|
|
expected_port_info: "{{ expected_port_info + [ item[0] |combine(item[1]) ] }}"
|
2018-08-24 16:44:59 +02:00
|
|
|
loop: "{{ tmp }}"
|
|
|
|
|
|
|
|
# Verify that each host object has the expected protocol type and address/port
|
|
|
|
- name: Assert hosts information was updated with new port information
|
|
|
|
assert:
|
|
|
|
that: "{{ item[0].host_name != item[1].host_name or
|
|
|
|
item[0].label != item[1].label or
|
|
|
|
(item[0].type == item[1].type and
|
|
|
|
(item[0].address|regex_replace(':','')) == (item[1].port|regex_replace(':',''))) }}"
|
|
|
|
msg: "port failed to be updated!"
|
|
|
|
loop: "{{ query('nested', port_info, expected_port_info) }}"
|
|
|
|
|
|
|
|
|
|
|
|
# ****************************************************
|
|
|
|
# *** Remove any existing hosts and verify changes ***
|
|
|
|
# ****************************************************
|
|
|
|
- name: Remove any existing hosts
|
|
|
|
netapp_e_host:
|
|
|
|
<<: *creds
|
|
|
|
state: absent
|
|
|
|
name: "{{ item.key }}"
|
|
|
|
with_dict: *hosts
|
|
|
|
|
|
|
|
# Request all host object definitions
|
|
|
|
- name: HTTP request for all host definitions from array
|
|
|
|
uri:
|
|
|
|
url: "{{ credentials.api_url }}/storage-systems/{{ credentials.ssid }}/hosts"
|
|
|
|
user: "{{ credentials.api_username }}"
|
|
|
|
password: "{{ credentials.api_password }}"
|
|
|
|
body_format: json
|
|
|
|
validate_certs: no
|
|
|
|
register: results
|
|
|
|
|
|
|
|
# Collect port label information
|
|
|
|
- name: Collect host side port labels
|
|
|
|
set_fact:
|
|
|
|
host_side_port_labels: "{{ results | json_query('json[*].hostSidePorts[*].label') }}"
|
|
|
|
|
|
|
|
- name: Collect removed port labels
|
|
|
|
set_fact:
|
|
|
|
removed_host_side_port_labels: "{{ hosts | json_query('*.ports[*].label') }}"
|
|
|
|
|
|
|
|
# Verify host 1 and 2 objects were removed
|
|
|
|
- name: Assert hosts were removed
|
|
|
|
assert:
|
|
|
|
that: item not in host_side_port_labels
|
|
|
|
msg: "Host {{ item }} failed to be removed from the hosts!"
|
|
|
|
loop: "{{ removed_host_side_port_labels }}"
|