Ucsm WWNN/WWPN pools (#34017)
* vhba template and integration test * SAN Connectivity Policies and integration test * VSANs and integration tests * WWNN/WWPN Pools and integration test * WWNN/WWPN Pools and integration test * option description spelled out (aliased to descr) removed docs for list of dictionaries syntax follow ACI indent style state absent only requires dn name match (not full prop match)
This commit is contained in:
parent
027f8dcafd
commit
58239671c0
3 changed files with 359 additions and 0 deletions
224
lib/ansible/modules/remote_management/ucs/ucs_wwn_pool.py
Normal file
224
lib/ansible/modules/remote_management/ucs/ucs_wwn_pool.py
Normal file
|
@ -0,0 +1,224 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: ucs_wwn_pool
|
||||
short_description: Configures WWNN or WWPN pools on Cisco UCS Manager
|
||||
description:
|
||||
- Configures WWNNs or WWPN pools on Cisco UCS Manager.
|
||||
- Examples can be used with the UCS Platform Emulator U(https://communities.cisco.com/ucspe).
|
||||
extends_documentation_fragment: ucs
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- If C(present), will verify WWNNs/WWPNs are present and will create if needed.
|
||||
- If C(absent), will verify WWNNs/WWPNs are absent and will delete if needed.
|
||||
choices: [present, absent]
|
||||
default: present
|
||||
name:
|
||||
description:
|
||||
- Name of the WWNN/WWPN
|
||||
required: yes
|
||||
purpose:
|
||||
description:
|
||||
- Specify node (WWNN) or port (WWPN)
|
||||
- Optional if state absent
|
||||
choices: [node, port]
|
||||
required: yes
|
||||
descrption:
|
||||
description:
|
||||
- Description for the WWNN/WWPN pool
|
||||
aliases: [ descr ]
|
||||
order:
|
||||
description:
|
||||
- Assignment order
|
||||
choices: [default, sequential]
|
||||
default: default
|
||||
first_addr:
|
||||
description: First WWNN/WWPN address in the WWN addresses block
|
||||
last_addr:
|
||||
description: Last WWNN/WWPN address in the WWN addresses block
|
||||
org_dn:
|
||||
description:
|
||||
- Org dn (distinguished name)
|
||||
default: org-root
|
||||
requirements:
|
||||
- ucsmsdk
|
||||
author:
|
||||
- David Soper (@dsoper2)
|
||||
- CiscoUcs (@CiscoUcs)
|
||||
version_added: '2.5'
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Configure WWNN/WWPN pools
|
||||
ucs_wwn_pool:
|
||||
hostname: 172.16.143.150
|
||||
username: admin
|
||||
password: password
|
||||
name: WWNN-Pool
|
||||
purpose: node
|
||||
first_addr: 20:00:00:25:B5:48:00:00
|
||||
last_addr: 20:00:00:25:B5:48:00:0F
|
||||
ucs_wwn_pool:
|
||||
hostname: 172.16.143.150
|
||||
username: admin
|
||||
password: password
|
||||
name: WWPN-Pool-A
|
||||
purpose: port
|
||||
order: sequential
|
||||
first_addr: 20:00:00:25:B5:48:0A:00
|
||||
last_addr: 20:00:00:25:B5:48:0A:0F
|
||||
|
||||
- name: Remove WWNN/WWPN pools
|
||||
ucs_wwn_pool:
|
||||
hostname: 172.16.143.150
|
||||
username: admin
|
||||
password: password
|
||||
name: WWNN-Pool
|
||||
state: absent
|
||||
ucs_wwn_pool:
|
||||
hostname: 172.16.143.150
|
||||
username: admin
|
||||
password: password
|
||||
name: WWPN-Pool-A
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
#
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.remote_management.ucs import UCSModule, ucs_argument_spec
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = ucs_argument_spec
|
||||
argument_spec.update(
|
||||
org_dn=dict(type='str', default='org-root'),
|
||||
name=dict(type='str'),
|
||||
purpose=dict(type='str', choices=['node', 'port']),
|
||||
descr=dict(type='str'),
|
||||
order=dict(type='str', default='default', choices=['default', 'sequential']),
|
||||
first_addr=dict(type='str'),
|
||||
last_addr=dict(type='str'),
|
||||
state=dict(type='str', default='present', choices=['present', 'absent']),
|
||||
wwn_list=dict(type='list'),
|
||||
)
|
||||
|
||||
# Note that use of wwn_list is an experimental feature which allows multiple resource updates with a single UCSM connection.
|
||||
# Support for wwn_list may change or be removed once persistent UCS connections are supported.
|
||||
# Either wwn_list or name is required (user can specify either a list or single resource).
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
required_one_of=[
|
||||
['wwn_list', 'name']
|
||||
],
|
||||
mutually_exclusive=[
|
||||
['wwn_list', 'name']
|
||||
],
|
||||
)
|
||||
ucs = UCSModule(module)
|
||||
|
||||
err = False
|
||||
|
||||
from ucsmsdk.mometa.fcpool.FcpoolInitiators import FcpoolInitiators
|
||||
from ucsmsdk.mometa.fcpool.FcpoolBlock import FcpoolBlock
|
||||
|
||||
changed = False
|
||||
try:
|
||||
# Only documented use is a single resource, but to also support experimental
|
||||
# feature allowing multiple updates all params are converted to a wwn_list below.
|
||||
|
||||
if module.params['wwn_list']:
|
||||
# directly use the list (single resource and list are mutually exclusive
|
||||
wwn_list = module.params['wwn_list']
|
||||
else:
|
||||
# single resource specified, create list from the current params
|
||||
wwn_list = [module.params]
|
||||
for wwn in wwn_list:
|
||||
mo_exists = False
|
||||
props_match = False
|
||||
# set default params. Done here to set values for lists which can't be done in the argument_spec
|
||||
if not wwn.get('descr'):
|
||||
wwn['descr'] = ''
|
||||
if not wwn.get('order'):
|
||||
wwn['order'] = 'default'
|
||||
# dn is <org_dn>/wwn-pool-<name> for WWNN or WWPN
|
||||
dn = module.params['org_dn'] + '/wwn-pool-' + wwn['name']
|
||||
|
||||
mo = ucs.login_handle.query_dn(dn)
|
||||
if mo:
|
||||
mo_exists = True
|
||||
|
||||
if module.params['state'] == 'absent':
|
||||
if mo_exists:
|
||||
if not module.check_mode:
|
||||
ucs.login_handle.remove_mo(mo)
|
||||
ucs.login_handle.commit()
|
||||
changed = True
|
||||
else:
|
||||
# append purpose param with suffix used by UCSM
|
||||
purpose_param = wwn['purpose'] + '-wwn-assignment'
|
||||
if mo_exists:
|
||||
# check top-level mo props
|
||||
kwargs = {}
|
||||
kwargs['assignment_order'] = wwn['order']
|
||||
kwargs['descr'] = wwn['descr']
|
||||
kwargs['purpose'] = purpose_param
|
||||
if (mo.check_prop_match(**kwargs)):
|
||||
# top-level props match, check next level mo/props
|
||||
if 'last_addr' in wwn and 'first_addr' in wwn:
|
||||
block_dn = dn + '/block-' + wwn['first_addr'].upper() + '-' + wwn['last_addr'].upper()
|
||||
mo_1 = ucs.login_handle.query_dn(block_dn)
|
||||
if mo_1:
|
||||
props_match = True
|
||||
else:
|
||||
props_match = True
|
||||
|
||||
if not props_match:
|
||||
if not module.check_mode:
|
||||
# create if mo does not already exist
|
||||
mo = FcpoolInitiators(
|
||||
parent_mo_or_dn=module.params['org_dn'],
|
||||
name=wwn['name'],
|
||||
descr=wwn['descr'],
|
||||
assignment_order=wwn['order'],
|
||||
purpose=purpose_param,
|
||||
)
|
||||
if 'last_addr' in wwn and 'first_addr' in wwn:
|
||||
mo_1 = FcpoolBlock(
|
||||
parent_mo_or_dn=mo,
|
||||
to=wwn['last_addr'],
|
||||
r_from=wwn['first_addr'],
|
||||
)
|
||||
|
||||
ucs.login_handle.add_mo(mo, True)
|
||||
ucs.login_handle.commit()
|
||||
changed = True
|
||||
|
||||
except Exception as e:
|
||||
err = True
|
||||
ucs.result['msg'] = "setup error: %s " % str(e)
|
||||
|
||||
ucs.result['changed'] = changed
|
||||
if err:
|
||||
module.fail_json(**ucs.result)
|
||||
module.exit_json(**ucs.result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
6
test/integration/targets/ucs_wwn_pool/aliases
Normal file
6
test/integration/targets/ucs_wwn_pool/aliases
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Not enabled, but can be used with the UCS Platform Emulator or UCS hardware.
|
||||
# Example integration_config.yml:
|
||||
# ---
|
||||
# ucs_hostname: 172.16.143.136
|
||||
# ucs_username: admin
|
||||
# ucs_password: password
|
129
test/integration/targets/ucs_wwn_pool/tasks/main.yml
Normal file
129
test/integration/targets/ucs_wwn_pool/tasks/main.yml
Normal file
|
@ -0,0 +1,129 @@
|
|||
# Test code for the UCS modules
|
||||
# Copyright 2017, David Soper (@dsoper2)
|
||||
|
||||
- name: Test that we have a UCS host, UCS username, and UCS password
|
||||
fail:
|
||||
msg: 'Please define the following variables: ucs_hostname, ucs_username and ucs_password.'
|
||||
when: ucs_hostname is not defined or ucs_username is not defined or ucs_password is not defined
|
||||
|
||||
|
||||
# Setup (clean environment)
|
||||
- name: WWNN/WWPN Pools absent
|
||||
ucs_wwn_pool: &wwn_pool_absent
|
||||
hostname: "{{ ucs_hostname }}"
|
||||
username: "{{ ucs_username }}"
|
||||
password: "{{ ucs_password }}"
|
||||
name: WWPN-Pool-A
|
||||
state: absent
|
||||
|
||||
|
||||
# Test present (check_mode)
|
||||
- name: WWNN/WWPN Pools present (check_mode)
|
||||
ucs_wwn_pool: &wwn_pool_present
|
||||
hostname: "{{ ucs_hostname }}"
|
||||
username: "{{ ucs_username }}"
|
||||
password: "{{ ucs_password }}"
|
||||
name: WWPN-Pool-A
|
||||
purpose: port
|
||||
order: sequential
|
||||
first_addr: 20:00:00:25:B5:48:0A:00
|
||||
last_addr: 20:00:00:25:B5:48:0A:0F
|
||||
check_mode: yes
|
||||
register: cm_wwn_pool_present
|
||||
|
||||
|
||||
# Present (normal mode)
|
||||
- name: WWNN/WWPN Pools present (normal mode)
|
||||
ucs_wwn_pool: *wwn_pool_present
|
||||
register: nm_wwn_pool_present
|
||||
|
||||
|
||||
# Test present again (idempotent)
|
||||
- name: WWNN/WWPN Pools present again (check_mode)
|
||||
ucs_wwn_pool: *wwn_pool_present
|
||||
check_mode: yes
|
||||
register: cm_wwn_pool_present_again
|
||||
|
||||
|
||||
# Present again (normal mode)
|
||||
- name: WWNN/WWPN Pools present again (normal mode)
|
||||
ucs_wwn_pool: *wwn_pool_present
|
||||
register: nm_wwn_pool_present_again
|
||||
|
||||
|
||||
# Verfiy present
|
||||
- name: Verify WWNN/WWPN Pools present results
|
||||
assert:
|
||||
that:
|
||||
- cm_wwn_pool_present.changed == nm_wwn_pool_present.changed == true
|
||||
- cm_wwn_pool_present_again.changed == nm_wwn_pool_present_again.changed == false
|
||||
|
||||
|
||||
# Test change (check_mode)
|
||||
- name: WWNN/WWPN Pools description change (check_mode)
|
||||
ucs_wwn_pool: &wwn_pool_change
|
||||
<<: *wwn_pool_present
|
||||
descr: Testing Ansible
|
||||
check_mode: yes
|
||||
register: cm_wwn_pool_descr_change
|
||||
|
||||
|
||||
# Change (normal mode)
|
||||
- name: WWNN/WWPN Pools description change (normal mode)
|
||||
ucs_wwn_pool: *wwn_pool_change
|
||||
register: nm_wwn_pool_descr_change
|
||||
|
||||
|
||||
# Test change again (idempotent)
|
||||
- name: WWNN/WWPN Pools description again (check_mode)
|
||||
ucs_wwn_pool: *wwn_pool_change
|
||||
check_mode: yes
|
||||
register: cm_wwn_pool_descr_change_again
|
||||
|
||||
|
||||
# Change again (normal mode)
|
||||
- name: WWNN/WWPN Pools description change again (normal mode)
|
||||
ucs_wwn_pool: *wwn_pool_change
|
||||
register: nm_wwn_pool_descr_change_again
|
||||
|
||||
|
||||
# Verfiy change
|
||||
- name: Verify WWNN/WWPN Pools change results
|
||||
assert:
|
||||
that:
|
||||
- cm_wwn_pool_descr_change.changed == nm_wwn_pool_descr_change.changed == true
|
||||
- cm_wwn_pool_descr_change_again.changed == nm_wwn_pool_descr_change_again.changed == false
|
||||
|
||||
|
||||
# Teardown (clean environment)
|
||||
- name: WWNN/WWPN Pools absent (check_mode)
|
||||
ucs_wwn_pool: *wwn_pool_absent
|
||||
check_mode: yes
|
||||
register: cm_wwn_pool_absent
|
||||
|
||||
|
||||
# Absent (normal mode)
|
||||
- name: WWNN/WWPN Pools absent (normal mode)
|
||||
ucs_wwn_pool: *wwn_pool_absent
|
||||
register: nm_wwn_pool_absent
|
||||
|
||||
|
||||
# Test absent again (idempotent)
|
||||
- name: WWNN/WWPN Pools absent again (check_mode)
|
||||
ucs_wwn_pool: *wwn_pool_absent
|
||||
check_mode: yes
|
||||
register: cm_wwn_pool_absent_again
|
||||
|
||||
|
||||
# Absent again (normal mode)
|
||||
- name: WWNN/WWPN Pools absent again (normal mode)
|
||||
ucs_wwn_pool: *wwn_pool_absent
|
||||
register: nm_wwn_pool_absent_again
|
||||
|
||||
|
||||
# Verfiy absent
|
||||
- name: Verify WWNN/WWPN Pools absent results
|
||||
assert:
|
||||
that:
|
||||
- cm_wwn_pool_absent.changed == nm_wwn_pool_absent.changed == true
|
||||
- cm_wwn_pool_absent_again.changed == nm_wwn_pool_absent_again.changed == false
|
Loading…
Reference in a new issue