UCS SAN Connectivity Policy module and integration test (#34009)

* vhba template and integration test

* SAN Connectivity Policies and integration test

* VSANs and integration tests

* WWNN/WWPN Pools and integration test

* SAN Connectivity Policies only

* 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:
David Soper 2017-12-21 14:15:07 -06:00 committed by Dag Wieers
parent 57575d1cfa
commit d80b873a69
3 changed files with 373 additions and 0 deletions

View file

@ -0,0 +1,235 @@
#!/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_san_connectivity
short_description: Configures SAN Connectivity Policies on Cisco UCS Manager
description:
- Configures SAN Connectivity Policies 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 SAN Connectivity Policies are present and will create if needed.
- If C(absent), will verify SAN Connectivity Policies are absent and will delete if needed.
choices: [present, absent]
default: present
name:
description:
- Name of the SAN Connectivity Policy
required: yes
description:
description:
- Description for the SAN Connectivity Policy
aliases: [ descr ]
wwnn_pool:
description:
- WWNN Pool name
default: default
vhba_list:
description:
- List of vHBAs contained in the SAN Connectivity Policy
- Each list element has the following suboptions
- name (Name of the vHBA (required))
- vhba_template (vHBA template (required))
- adapter_policy ('' (default), Linux, Solaris, VMware, Windows, WindowsBoot, or default)
- order (string specifying vHBA assignment order (unspecified (default), '1', '2', etc.)
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 SAN Connectivity Policy
ucs_san_connectivity:
hostname: 172.16.143.150
username: admin
password: password
name: Cntr-FC-Boot
wwnn_pool: WWNN-Pool
vhba_list:
- name: Fabric-A
vhba_template: vHBA-Template-A
adapter_policy: Linux
- name: Fabric-B
vhba_template: vHBA-Template-B
adapter_policy: Linux
- name: Remove SAN Connectivity Policy
ucs_san_connectivity:
hostname: 172.16.143.150
username: admin
password: password
name: Cntr-FC-Boot
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'),
descr=dict(type='str'),
wwnn_pool=dict(type='str', default='default'),
vhba_list=dict(type='list'),
state=dict(type='str', default='present', choices=['present', 'absent']),
san_connectivity_list=dict(type='list'),
)
# Note that use of san_connectivity_list is an experimental feature which allows multiple resource updates with a single UCSM connection.
# Support for san_connectivity_list may change or be removed once persistent UCS connections are supported.
# Either san_connectivity_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=[
['san_connectivity_list', 'name'],
],
mutually_exclusive=[
['san_connectivity_list', 'name'],
],
)
ucs = UCSModule(module)
err = False
from ucsmsdk.mometa.vnic.VnicSanConnPolicy import VnicSanConnPolicy
from ucsmsdk.mometa.vnic.VnicFcNode import VnicFcNode
from ucsmsdk.mometa.vnic.VnicFc import VnicFc
from ucsmsdk.mometa.vnic.VnicFcIf import VnicFcIf
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 san_connectivity_list below.
if module.params['san_connectivity_list']:
# directly use the list (single resource and list are mutually exclusive
san_connectivity_list = module.params['san_connectivity_list']
else:
# single resource specified, create list from the current params
san_connectivity_list = [module.params]
for san_connectivity in san_connectivity_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 san_connectivity.get('descr'):
san_connectivity['descr'] = ''
if not san_connectivity.get('wwnn_pool'):
san_connectivity['wwnn_pool'] = 'default'
if san_connectivity.get('vhba_list'):
for vhba in san_connectivity['vhba_list']:
if not vhba.get('adapter_policy'):
vhba['adapter_policy'] = ''
if not vhba.get('order'):
vhba['order'] = 'unspecified'
# dn is <org_dn>/san-conn-pol-<name>
dn = module.params['org_dn'] + '/san-conn-pol-' + san_connectivity['name']
mo = ucs.login_handle.query_dn(dn)
if mo:
mo_exists = True
# check top-level mo props
kwargs = {}
kwargs['descr'] = san_connectivity['descr']
if (mo.check_prop_match(**kwargs)):
# top-level props match, check next level mo/props
# vnicFcNode object
child_dn = dn + '/fc-node'
mo_1 = ucs.login_handle.query_dn(child_dn)
if mo_1:
kwargs = {}
kwargs['ident_pool_name'] = san_connectivity['wwnn_pool']
if (mo_1.check_prop_match(**kwargs)):
if not san_connectivity.get('vhba_list'):
props_match = True
else:
# check vnicFc props
for vhba in san_connectivity['vhba_list']:
child_dn = dn + '/fc-' + vhba['name']
mo_2 = ucs.login_handle.query_dn(child_dn)
kwargs = {}
kwargs['adaptor_profile_name'] = vhba['adapter_policy']
kwargs['order'] = vhba['order']
kwargs['nw_templ_name'] = vhba['vhba_template']
if (mo_2.check_prop_match(**kwargs)):
props_match = True
if module.params['state'] == 'absent':
# mo must exist but all properties do not have to match
if mo_exists:
if not module.check_mode:
ucs.login_handle.remove_mo(mo)
ucs.login_handle.commit()
changed = True
else:
if not props_match:
if not module.check_mode:
# create if mo does not already exist
mo = VnicSanConnPolicy(
parent_mo_or_dn=module.params['org_dn'],
name=san_connectivity['name'],
descr=san_connectivity['descr'],
)
mo_1 = VnicFcNode(
parent_mo_or_dn=mo,
ident_pool_name=san_connectivity['wwnn_pool'],
addr='pool-derived',
)
if san_connectivity.get('vhba_list'):
for vhba in san_connectivity['vhba_list']:
mo_2 = VnicFc(
parent_mo_or_dn=mo,
name=vhba['name'],
adaptor_profile_name=vhba['adapter_policy'],
nw_templ_name=vhba['vhba_template'],
order=vhba['order'],
)
mo_2_1 = VnicFcIf(
parent_mo_or_dn=mo_2,
name='default',
)
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()

View 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

View file

@ -0,0 +1,132 @@
# 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: SAN Connectivity Policies absent
ucs_san_connectivity: &san_connectivity_absent
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: Cntr-FC-Boot
state: absent
# Test present (check_mode)
- name: SAN Connectivity Policies present (check_mode)
ucs_san_connectivity: &san_connectivity_present
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: Cntr-FC-Boot
wwnn_pool: WWNN-Pool
vhba_list:
- name: Fabric-A
vhba_template: vHBA-Template-A
adapter_policy: Linux
- name: Fabric-B
vhba_template: vHBA-Template-B
adapter_policy: Linux
check_mode: yes
register: cm_san_connectivity_present
# Present (normal mode)
- name: SAN Connectivity Policies present (normal mode)
ucs_san_connectivity: *san_connectivity_present
register: nm_san_connectivity_present
# Test present again (idempotent)
- name: SAN Connectivity Policies present again (check_mode)
ucs_san_connectivity: *san_connectivity_present
check_mode: yes
register: cm_san_connectivity_present_again
# Present again (normal mode)
- name: SAN Connectivity Policies present again (normal mode)
ucs_san_connectivity: *san_connectivity_present
register: nm_san_connectivity_present_again
# Verfiy present
- name: Verify SAN Connectivity Policies present results
assert:
that:
- cm_san_connectivity_present.changed == nm_san_connectivity_present.changed == true
- cm_san_connectivity_present_again.changed == nm_san_connectivity_present_again.changed == false
# Test change (check_mode)
- name: SAN Connectivity Policies description change (check_mode)
ucs_san_connectivity: &san_connectivity_change
<<: *san_connectivity_present
descr: Testing Ansible
check_mode: yes
register: cm_san_connectivity_descr_change
# Change (normal mode)
- name: SAN Connectivity Policies description change (normal mode)
ucs_san_connectivity: *san_connectivity_change
register: nm_san_connectivity_descr_change
# Test change again (idempotent)
- name: SAN Connectivity Policies description again (check_mode)
ucs_san_connectivity: *san_connectivity_change
check_mode: yes
register: cm_san_connectivity_descr_change_again
# Change again (normal mode)
- name: SAN Connectivity Policies description change again (normal mode)
ucs_san_connectivity: *san_connectivity_change
register: nm_san_connectivity_descr_change_again
# Verfiy change
- name: Verify SAN Connectivity Policies change results
assert:
that:
- cm_san_connectivity_descr_change.changed == nm_san_connectivity_descr_change.changed == true
- cm_san_connectivity_descr_change_again.changed == nm_san_connectivity_descr_change_again.changed == false
# Teardown (clean environment)
- name: SAN Connectivity Policies absent (check_mode)
ucs_san_connectivity: *san_connectivity_absent
check_mode: yes
register: cm_san_connectivity_absent
# Absent (normal mode)
- name: SAN Connectivity Policies absent (normal mode)
ucs_san_connectivity: *san_connectivity_absent
register: nm_san_connectivity_absent
# Test absent again (idempotent)
- name: SAN Connectivity Policies absent again (check_mode)
ucs_san_connectivity: *san_connectivity_absent
check_mode: yes
register: cm_san_connectivity_absent_again
# Absent again (normal mode)
- name: SAN Connectivity Policies absent again (normal mode)
ucs_san_connectivity: *san_connectivity_absent
register: nm_san_connectivity_absent_again
# Verfiy absent
- name: Verify SAN Connectivity Policies absent results
assert:
that:
- cm_san_connectivity_absent.changed == nm_san_connectivity_absent.changed == true
- cm_san_connectivity_absent_again.changed == nm_san_connectivity_absent_again.changed == false