adding the modules to /nxos/storage/ folder (#64269)

* adding the modules to /nxos/storage/ folder

* fix pep8 stuff

* fixed provider specific information from doc

* Fix integration tests

* Added tested against note

* Review comments

* added assertions for the commands sent in the integration tests
This commit is contained in:
Suhas Bharadwaj 2019-12-16 14:44:33 +05:30 committed by Nilashish Chakraborty
parent 7b2cfdacd0
commit 0a04a5efc2
43 changed files with 3152 additions and 0 deletions

View file

@ -0,0 +1,499 @@
#!/usr/bin/python
# Copyright: Ansible Project
# 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)
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'network'}
DOCUMENTATION = '''
module: nxos_devicealias
version_added: "2.10"
short_description: Configuration of device alias.
description:
- Configuration of device alias for Cisco MDS NXOS.
author:
- Suhas Bharadwaj (@srbharadwaj) (subharad@cisco.com)
notes:
- Tested against NX-OS 8.4(1)
options:
distribute:
description:
- Enable/Disable device-alias distribution
type: bool
default: False
mode:
description:
- Mode of devices-alias, basic or enhanced
choices: ['basic', 'enhanced']
type: str
da:
description:
- List of device-alias to be added or removed
type: list
suboptions:
name:
description:
- Name of the device-alias to be added or removed
required:
True
type: str
pwwn:
description:
- pwwn to which the name needs to be associated with
type: str
remove:
description:
- Removes the device-alias if set to True
type: bool
default: False
rename:
description:
- List of device-alias to be renamed
type: list
suboptions:
old_name:
description:
- Old name of the device-alias that needs to be renamed
required:
True
type: str
new_name:
description:
- New name of the device-alias
required:
True
type: str
'''
EXAMPLES = '''
---
- name: 'Test that device alias module works'
nxos_devicealias:
da:
- name: test1_add
pwwn: '56:2:22:11:22:88:11:67'
- name: test2_add
pwwn: '65:22:22:11:22:22:11:d'
- name: dev1
remove: true
- name: dev2
remove: true
distribute: true
mode: enhanced
rename:
- new_name: bcd
old_name: abc
- new_name: bcd1
old_name: abc1
'''
RETURN = '''
commands:
description: commands sent to the device
returned: always
type: list
sample:
- terminal dont-ask
- device-alias database
- device-alias name somename pwwn 10:00:00:00:89:a1:01:03
- device-alias name somename1 pwwn 10:00:00:00:89:a1:02:03
- device-alias commit
- no terminal dont-ask
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.nxos.nxos import load_config, run_commands
import string
__metaclass__ = type
class showDeviceAliasStatus(object):
"""docstring for showDeviceAliasStatus"""
def __init__(self, module):
self.module = module
self.distribute = ""
self.mode = ""
self.locked = False
self.update()
def execute_show_cmd(self, cmd):
output = execute_show_command(cmd, self.module)[0]
return output
def update(self):
command = 'show device-alias status'
output = self.execute_show_cmd(command).split("\n")
for o in output:
if "Fabric Distribution" in o:
self.distribute = o.split(":")[1].strip().lower()
if "Mode" in o:
self.mode = o.split("Mode:")[1].strip().lower()
if "Locked" in o:
self.locked = True
def isLocked(self):
return self.locked
def getDistribute(self):
return self.distribute
def getMode(self):
return self.mode
class showDeviceAliasDatabase(object):
"""docstring for showDeviceAliasDatabase"""
def __init__(self, module):
self.module = module
self.da_dict = {}
self.update()
def execute_show_cmd(self, cmd):
output = execute_show_command(cmd, self.module)[0]
return output
def update(self):
command = 'show device-alias database'
# output = execute_show_command(command, self.module)[0].split("\n")
output = self.execute_show_cmd(command)
self.da_list = output.split("\n")
for eachline in self.da_list:
if 'device-alias' in eachline:
sv = eachline.strip().split()
self.da_dict[sv[2]] = sv[4]
def isNameInDaDatabase(self, name):
return name in self.da_dict.keys()
def isPwwnInDaDatabase(self, pwwn):
newpwwn = ':'.join(["0" + str(ep) if len(ep) == 1 else ep for ep in pwwn.split(":")])
return newpwwn in self.da_dict.values()
def isNamePwwnPresentInDatabase(self, name, pwwn):
newpwwn = ':'.join(["0" + str(ep) if len(ep) == 1 else ep for ep in pwwn.split(":")])
if name in self.da_dict.keys():
if newpwwn == self.da_dict[name]:
return True
return False
def getPwwnByName(self, name):
if name in self.da_dict.keys():
return self.da_dict[name]
else:
return None
def getNameByPwwn(self, pwwn):
newpwwn = ':'.join(["0" + str(ep) if len(ep) == 1 else ep for ep in pwwn.split(":")])
for n, p in self.da_dict.items():
if p == newpwwn:
return n
return None
def isPwwnValid(pwwn):
pwwnsplit = pwwn.split(":")
if len(pwwnsplit) != 8:
return False
for eachpwwnsplit in pwwnsplit:
if len(eachpwwnsplit) > 2 or len(eachpwwnsplit) < 1:
return False
if not all(c in string.hexdigits for c in eachpwwnsplit):
return False
return True
def isNameValid(name):
if not name[0].isalpha():
# Illegal first character. Name must start with a letter
return False
if len(name) > 64:
return False
return True
def execute_show_command(command, module, command_type='cli_show'):
output = 'text'
commands = [{
'command': command,
'output': output,
}]
out = run_commands(module, commands)
return out
def flatten_list(command_lists):
flat_command_list = []
for command in command_lists:
if isinstance(command, list):
flat_command_list.extend(command)
else:
flat_command_list.append(command)
return flat_command_list
def main():
element_spec = dict(
name=dict(required=True, type='str'),
pwwn=dict(type='str'),
remove=dict(type='bool', default=False)
)
element_spec_rename = dict(
old_name=dict(required=True, type='str'),
new_name=dict(required=True, type='str'),
)
argument_spec = dict(
distribute=dict(type='bool'),
mode=dict(type='str', choices=['enhanced', 'basic']),
da=dict(type='list', elements='dict', options=element_spec),
rename=dict(type='list', elements='dict', options=element_spec_rename)
)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
warnings = list()
messages = list()
commands_to_execute = list()
result = {'changed': False}
distribute = module.params['distribute']
mode = module.params['mode']
da = module.params['da']
rename = module.params['rename']
# Step 0.0: Validate syntax of name and pwwn
# Also validate syntax of rename arguments
if da is not None:
for eachdict in da:
name = eachdict['name']
pwwn = eachdict['pwwn']
remove = eachdict['remove']
if pwwn is not None:
pwwn = pwwn.lower()
if not remove:
if pwwn is None:
module.fail_json(
msg='This device alias name ' +
str(name) +
' which needs to be added, doenst have pwwn specified . Please specify a valid pwwn')
if not isNameValid(name):
module.fail_json(msg='This pwwn name is invalid : ' + str(name) +
'. Note that name cannot be more than 64 chars and it should start with a letter')
if not isPwwnValid(pwwn):
module.fail_json(msg='This pwwn is invalid : ' + str(pwwn) + '. Please check that its a valid pwwn')
if rename is not None:
for eachdict in rename:
oldname = eachdict['old_name']
newname = eachdict['new_name']
if not isNameValid(oldname):
module.fail_json(msg='This pwwn name is invalid : ' + str(oldname) +
'. Note that name cannot be more than 64 chars and it should start with a letter')
if not isNameValid(newname):
module.fail_json(msg='This pwwn name is invalid : ' + str(newname) +
'. Note that name cannot be more than 64 chars and it should start with a letter')
# Step 0.1: Check DA status
shDAStausObj = showDeviceAliasStatus(module)
d = shDAStausObj.getDistribute()
m = shDAStausObj.getMode()
if shDAStausObj.isLocked():
module.fail_json(msg='device-alias has acquired lock on the switch. Hence cannot procced.')
# Step 1: Process distribute
commands = []
if distribute is not None:
if distribute:
# playbook has distribute as True(enabled)
if d == "disabled":
# but switch distribute is disabled(false), so set it to true(enabled)
commands.append("device-alias distribute")
messages.append('device-alias distribute changed from disabled to enabled')
else:
messages.append('device-alias distribute remains unchanged. current distribution mode is enabled')
else:
# playbook has distribute as False(disabled)
if d == "enabled":
# but switch distribute is enabled(true), so set it to false(disabled)
commands.append("no device-alias distribute")
messages.append('device-alias distribute changed from enabled to disabled')
else:
messages.append('device-alias distribute remains unchanged. current distribution mode is disabled')
cmds = flatten_list(commands)
if cmds:
commands_to_execute = commands_to_execute + cmds
if module.check_mode:
# Check mode implemented at the da_add/da_remove stage
pass
else:
result['changed'] = True
load_config(module, cmds)
# Step 2: Process mode
commands = []
if mode is not None:
if mode == 'basic':
# playbook has mode as basic
if m == 'enhanced':
# but switch mode is enhanced, so set it to basic
commands.append("no device-alias mode enhanced")
messages.append('device-alias mode changed from enhanced to basic')
else:
messages.append('device-alias mode remains unchanged. current mode is basic')
else:
# playbook has mode as enhanced
if m == 'basic':
# but switch mode is basic, so set it to enhanced
commands.append("device-alias mode enhanced")
messages.append('device-alias mode changed from basic to enhanced')
else:
messages.append('device-alias mode remains unchanged. current mode is enhanced')
if commands:
if distribute:
commands.append("device-alias commit")
commands = ["terminal dont-ask"] + commands + ["no terminal dont-ask"]
else:
if distribute is None and d == 'enabled':
commands.append("device-alias commit")
commands = ["terminal dont-ask"] + commands + ["no terminal dont-ask"]
cmds = flatten_list(commands)
if cmds:
commands_to_execute = commands_to_execute + cmds
if module.check_mode:
# Check mode implemented at the end
pass
else:
result['changed'] = True
load_config(module, cmds)
# Step 3: Process da
commands = []
shDADatabaseObj = showDeviceAliasDatabase(module)
if da is not None:
da_remove_list = []
da_add_list = []
for eachdict in da:
name = eachdict['name']
pwwn = eachdict['pwwn']
remove = eachdict['remove']
if pwwn is not None:
pwwn = pwwn.lower()
if remove:
if shDADatabaseObj.isNameInDaDatabase(name):
commands.append("no device-alias name " + name)
da_remove_list.append(name)
else:
messages.append(name + ' - This device alias name is not in switch device-alias database, hence cannot be removed.')
else:
if shDADatabaseObj.isNamePwwnPresentInDatabase(name, pwwn):
messages.append(name + ' : ' + pwwn + ' - This device alias name,pwwn is already in switch device-alias database, \
hence nothing to configure')
else:
if shDADatabaseObj.isNameInDaDatabase(name):
module.fail_json(
msg=name +
' - This device alias name is already present in switch device-alias database but assigned to another pwwn (' +
shDADatabaseObj.getPwwnByName(name) +
') hence cannot be added')
elif shDADatabaseObj.isPwwnInDaDatabase(pwwn):
module.fail_json(
msg=pwwn +
' - This device alias pwwn is already present in switch device-alias database but assigned to another name (' +
shDADatabaseObj.getNameByPwwn(pwwn) +
') hence cannot be added')
else:
commands.append("device-alias name " + name + " pwwn " + pwwn)
da_add_list.append(name)
if len(da_add_list) != 0 or len(da_remove_list) != 0:
commands = ["device-alias database"] + commands
if distribute:
commands.append("device-alias commit")
commands = ["terminal dont-ask"] + commands + ["no terminal dont-ask"]
else:
if distribute is None and d == 'enabled':
commands.append("device-alias commit")
commands = ["terminal dont-ask"] + commands + ["no terminal dont-ask"]
cmds = flatten_list(commands)
if cmds:
commands_to_execute = commands_to_execute + cmds
if module.check_mode:
# Check mode implemented at the end
pass
else:
result['changed'] = True
load_config(module, cmds)
if len(da_remove_list) != 0:
messages.append('the required device-alias were removed. ' + ','.join(da_remove_list))
if len(da_add_list) != 0:
messages.append('the required device-alias were added. ' + ','.join(da_add_list))
# Step 5: Process rename
commands = []
if rename is not None:
for eachdict in rename:
oldname = eachdict['old_name']
newname = eachdict['new_name']
if shDADatabaseObj.isNameInDaDatabase(newname):
module.fail_json(
changed=False,
commands=cmds,
msg=newname +
" - this name is already present in the device-alias database, hence we cannot rename " +
oldname +
" with this one")
if shDADatabaseObj.isNameInDaDatabase(oldname):
commands.append('device-alias rename ' + oldname + ' ' + newname)
else:
module.fail_json(changed=False, commands=cmds, msg=oldname +
" - this name is not present in the device-alias database, hence we cannot rename.")
if len(commands) != 0:
commands = ["device-alias database"] + commands
if distribute:
commands.append("device-alias commit")
commands = ["terminal dont-ask"] + commands + ["no terminal dont-ask"]
else:
if distribute is None and d == 'enabled':
commands.append("device-alias commit")
commands = ["terminal dont-ask"] + commands + ["no terminal dont-ask"]
cmds = flatten_list(commands)
if cmds:
commands_to_execute = commands_to_execute + cmds
if module.check_mode:
# Check mode implemented at the end
pass
else:
result['changed'] = True
load_config(module, cmds)
# Step END: check for 'check' mode
if module.check_mode:
module.exit_json(changed=False, commands=commands_to_execute, msg="Check Mode: No cmds issued to the hosts")
result['messages'] = messages
result['commands'] = commands_to_execute
result['warnings'] = warnings
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,326 @@
#!/usr/bin/python
# Copyright: Ansible Project
# 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)
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'network'}
DOCUMENTATION = '''
module: nxos_vsan
version_added: "2.10"
short_description: Configuration of vsan.
description:
- Configuration of vsan for Cisco MDS NXOS.
author:
- Suhas Bharadwaj (@srbharadwaj) (subharad@cisco.com)
notes:
- Tested against NX-OS 8.4(1)
options:
vsan:
description:
- List of vsan details to be added or removed
type: list
suboptions:
id:
description:
- Vsan id
required: True
type: int
name:
description:
- Name of the vsan
type: str
suspend:
description:
- suspend the vsan if True
type: bool
default: False
remove:
description:
- Removes the vsan if True
type: bool
default: False
interface:
description:
- List of vsan's interfaces to be added
type: list
'''
EXAMPLES = '''
---
-
name: "Test that vsan module works"
nxos_vsan:
vsan:
- id: 922
interface:
- fc1/1
- fc1/2
- "port-channel 1"
name: vsan-SAN-A
remove: false
suspend: false
- id: 923
interface:
- fc1/11
- fc1/21
- "port-channel 2"
name: vsan-SAN-B
remove: false
suspend: true
- id: 1923
name: vsan-SAN-Old
remove: true
'''
RETURN = '''
commands:
description: commands sent to the device
returned: always
type: list
sample:
- terminal dont-ask
- vsan database
- vsan 922 interface fc1/40
- vsan 922 interface port-channel 155
- no terminal dont-ask
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.nxos.nxos import load_config, run_commands
import re
__metaclass__ = type
class Vsan(object):
def __init__(self, vsanid):
self.vsanid = vsanid
self.vsanname = None
self.vsanstate = None
self.vsanoperstate = None
self.vsaninterfaces = []
class GetVsanInfoFromSwitch(object):
"""docstring for GetVsanInfoFromSwitch"""
def __init__(self, module):
self.module = module
self.vsaninfo = {}
self.processShowVsan()
self.processShowVsanMembership()
def execute_show_vsan_cmd(self):
output = execute_show_command('show vsan', self.module)[0]
return output
def execute_show_vsan_mem_cmd(self):
output = execute_show_command('show vsan membership', self.module)[0]
return output
def processShowVsan(self):
patv = r"^vsan\s+(\d+)\s+information"
patnamestate = "name:(.*)state:(.*)"
patoperstate = "operational state:(.*)"
output = self.execute_show_vsan_cmd().split("\n")
for o in output:
z = re.match(patv, o.strip())
if z:
v = z.group(1).strip()
self.vsaninfo[v] = Vsan(v)
z1 = re.match(patnamestate, o.strip())
if z1:
n = z1.group(1).strip()
s = z1.group(2).strip()
self.vsaninfo[v].vsanname = n
self.vsaninfo[v].vsanstate = s
z2 = re.match(patoperstate, o.strip())
if z2:
oper = z2.group(1).strip()
self.vsaninfo[v].vsanoperstate = oper
# 4094/4079 vsan is always present
self.vsaninfo['4079'] = Vsan('4079')
self.vsaninfo['4094'] = Vsan('4094')
def processShowVsanMembership(self):
patv = r"^vsan\s+(\d+).*"
output = self.execute_show_vsan_mem_cmd().split("\n")
memlist = []
v = None
for o in output:
z = re.match(patv, o.strip())
if z:
if v is not None:
self.vsaninfo[v].vsaninterfaces = memlist
memlist = []
v = z.group(1)
if 'interfaces' not in o:
llist = o.strip().split()
memlist = memlist + llist
self.vsaninfo[v].vsaninterfaces = memlist
def getVsanInfoObjects(self):
return self.vsaninfo
def execute_show_command(command, module, command_type='cli_show'):
output = 'text'
commands = [{
'command': command,
'output': output,
}]
return run_commands(module, commands)
def flatten_list(command_lists):
flat_command_list = []
for command in command_lists:
if isinstance(command, list):
flat_command_list.extend(command)
else:
flat_command_list.append(command)
return flat_command_list
def main():
vsan_element_spec = dict(
id=dict(required=True, type='int'),
name=dict(type='str'),
remove=dict(type='bool'),
suspend=dict(type='bool'),
interface=dict(type='list', elements='str')
)
argument_spec = dict(
vsan=dict(type='list', elements='dict', options=vsan_element_spec)
)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
warnings = list()
messages = list()
commands_executed = list()
result = {'changed': False}
obj = GetVsanInfoFromSwitch(module)
dictSwVsanObjs = obj.getVsanInfoObjects()
commands = []
vsan_list = module.params['vsan']
for eachvsan in vsan_list:
vsanid = str(eachvsan['id'])
vsanname = eachvsan['name']
vsanremove = eachvsan['remove']
vsansuspend = eachvsan['suspend']
vsaninterface_list = eachvsan['interface']
if int(vsanid) < 1 or int(vsanid) >= 4095:
module.fail_json(msg=vsanid + " - This is an invalid vsan. Supported vsan range is 1-4094")
if vsanid in dictSwVsanObjs.keys():
sw_vsanid = vsanid
sw_vsanname = dictSwVsanObjs[vsanid].vsanname
sw_vsanstate = dictSwVsanObjs[vsanid].vsanstate
sw_vsaninterfaces = dictSwVsanObjs[vsanid].vsaninterfaces
else:
sw_vsanid = None
sw_vsanname = None
sw_vsanstate = None
sw_vsaninterfaces = []
if vsanremove:
# Negetive case:
if vsanid == '4079' or vsanid == '4094':
messages.append(str(vsanid) + " is a reserved vsan, hence cannot be removed")
continue
if vsanid == sw_vsanid:
commands.append("no vsan " + str(vsanid))
messages.append("deleting the vsan " + str(vsanid))
else:
messages.append("There is no vsan " + str(vsanid) + " present in the switch. Hence there is nothing to delete")
continue
else:
# Negetive case:
if vsanid == '4079' or vsanid == '4094':
messages.append(str(vsanid) + " is a reserved vsan, and always present on the switch")
else:
if vsanid == sw_vsanid:
messages.append("There is already a vsan " + str(vsanid) + " present in the switch. Hence there is nothing to configure")
else:
commands.append("vsan " + str(vsanid))
messages.append("creating vsan " + str(vsanid))
if vsanname is not None:
# Negetive case:
if vsanid == '4079' or vsanid == '4094':
messages.append(str(vsanid) + " is a reserved vsan, and cannot be renamed")
else:
if vsanname == sw_vsanname:
messages.append(
"There is already a vsan " +
str(vsanid) +
" present in the switch, which has the name " +
vsanname +
" Hence there is nothing to configure")
else:
commands.append("vsan " + str(vsanid) + " name " + vsanname)
messages.append("setting vsan name to " + vsanname + " for vsan " + str(vsanid))
if vsansuspend:
# Negetive case:
if vsanid == '4079' or vsanid == '4094':
messages.append(str(vsanid) + " is a reserved vsan, and cannot be suspended")
else:
if sw_vsanstate == 'suspended':
messages.append("There is already a vsan " + str(vsanid) + " present in the switch, which is in suspended state ")
else:
commands.append("vsan " + str(vsanid) + " suspend")
messages.append("suspending the vsan " + str(vsanid))
else:
if sw_vsanstate == 'active':
messages.append("There is already a vsan " + str(vsanid) + " present in the switch, which is in active state ")
else:
commands.append("no vsan " + str(vsanid) + " suspend")
messages.append("no suspending the vsan " + str(vsanid))
if vsaninterface_list is not None:
for each_interface_name in vsaninterface_list:
# For fcip,port-channel,vfc-port-channel need to remove the extra space to compare
temp = re.sub(' +', '', each_interface_name)
if temp in sw_vsaninterfaces:
messages.append(each_interface_name + " is already present in the vsan " + str(vsanid) + " interface list")
else:
commands.append("vsan " + str(vsanid) + " interface " + each_interface_name)
messages.append("adding interface " + each_interface_name + " to vsan " + str(vsanid))
if len(commands) != 0:
commands = ["terminal dont-ask"] + ["vsan database"] + commands + ["no terminal dont-ask"]
cmds = flatten_list(commands)
commands_executed = cmds
if commands_executed:
if module.check_mode:
module.exit_json(changed=False, commands=commands_executed, msg="Check Mode: No cmds issued to the hosts")
else:
result['changed'] = True
load_config(module, commands_executed)
result['messages'] = messages
result['commands'] = commands_executed
result['warnings'] = warnings
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,722 @@
#!/usr/bin/python
# Copyright: Ansible Project
# 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)
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'network'}
DOCUMENTATION = '''
---
module: nxos_zone_zoneset
version_added: "2.10"
short_description: Configuration of zone/zoneset.
description:
- Configuration of zone/zoneset for Cisco MDS NXOS.
author:
- Suhas Bharadwaj (@srbharadwaj) (subharad@cisco.com)
notes:
- Tested against NX-OS 8.4(1)
options:
zone_zoneset_details:
description:
- List of zone/zoneset details to be added or removed
type: list
suboptions:
vsan:
description:
- vsan id
required:
True
type: int
mode:
description:
- mode of the zone for the vsan
choices: ['enhanced', 'basic']
type: str
default_zone:
description:
- default zone behaviour for the vsan
choices: ['permit', 'deny']
type: str
smart_zoning:
description:
- Removes the vsan if True
type: bool
default: False
zone:
description:
- List of zone options for that vsan
type: list
suboptions:
name:
description:
- name of the zone
required:
True
type: str
remove:
description:
- Deletes the zone if True
type: bool
default: False
members:
description:
- Members of the zone that needs to be removed or added
type: list
suboptions:
pwwn:
description:
- pwwn member of the zone, use alias 'device_alias' as option for device_alias member
aliases: [device_alias]
required: true
type: str
remove:
description:
- Removes member from the zone if True
type: bool
default: false
devtype:
description:
- devtype of the zone member used along with Smart zoning config
choices: ['initiator', 'target', 'both']
type: str
zoneset:
description:
- List of zoneset options for the vsan
type: list
suboptions:
name:
description:
- name of the zoneset
required:
True
type: str
remove:
description:
- Removes zoneset if True
type: bool
default: False
action:
description:
- activates/de-activates the zoneset
choices: ['activate', 'deactivate']
type: str
members:
description:
- Members of the zoneset that needs to be removed or added
type: list
suboptions:
name:
description:
- name of the zone that needs to be added to the zoneset or removed from the zoneset
required: True
type: str
remove:
description:
- Removes zone member from the zoneset
type: bool
default: False
'''
EXAMPLES = '''
---
-
name: 'Test that zone/zoneset module works'
nxos_zone_zoneset:
zone_zoneset_details:
- mode: enhanced
vsan: 22
zone:
- members:
- pwwn: '11:11:11:11:11:11:11:11'
- device_alias: test123
- pwwn: '61:61:62:62:12:12:12:12'
remove: true
name: zoneA
- members:
- pwwn: '10:11:11:11:11:11:11:11'
- pwwn: '62:62:62:62:21:21:21:21'
name: zoneB
- name: zoneC
remove: true
zoneset:
- action: activate
members:
- name: zoneA
- name: zoneB
- name: zoneC
remove: true
name: zsetname1
- action: deactivate
name: zsetTestExtra
remove: true
- mode: basic
smart_zoning: true
vsan: 21
zone:
- members:
- devtype: both
pwwn: '11:11:11:11:11:11:11:11'
- pwwn: '62:62:62:62:12:12:12:12'
- devtype: both
pwwn: '92:62:62:62:12:12:1a:1a'
remove: true
name: zone21A
- members:
- pwwn: '10:11:11:11:11:11:11:11'
- pwwn: '62:62:62:62:21:21:21:21'
name: zone21B
zoneset:
- action: activate
members:
- name: zone21A
- name: zone21B
name: zsetname212
'''
RETURN = '''
commands:
description: commands sent to the device
returned: always
type: list
sample:
- terminal dont-ask
- zone name zoneA vsan 923
- member pwwn 11:11:11:11:11:11:11:11
- no member device-alias test123
- zone commit vsan 923
- no terminal dont-ask
'''
import re
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.nxos.nxos import load_config, run_commands
__metaclass__ = type
class ShowZonesetActive(object):
"""docstring for ShowZonesetActive"""
def __init__(self, module, vsan):
self.vsan = vsan
self.module = module
self.activeZSName = None
self.parseCmdOutput()
def execute_show_zoneset_active_cmd(self):
command = 'show zoneset active vsan ' + str(self.vsan) + ' | grep zoneset'
output = execute_show_command(command, self.module)[0]
return output
def parseCmdOutput(self):
patZoneset = r"zoneset name (\S+) vsan " + str(self.vsan)
output = self.execute_show_zoneset_active_cmd().split("\n")
if len(output) == 0:
return
else:
for line in output:
line = line.strip()
mzs = re.match(patZoneset, line.strip())
if mzs:
self.activeZSName = mzs.group(1).strip()
return
def isZonesetActive(self, zsname):
if zsname == self.activeZSName:
return True
return False
class ShowZoneset(object):
"""docstring for ShowZoneset"""
def __init__(self, module, vsan):
self.vsan = vsan
self.module = module
self.zsDetails = {}
self.parseCmdOutput()
def execute_show_zoneset_cmd(self):
command = 'show zoneset vsan ' + str(self.vsan)
output = execute_show_command(command, self.module)[0]
return output
def parseCmdOutput(self):
patZoneset = r"zoneset name (\S+) vsan " + str(self.vsan)
patZone = r"zone name (\S+) vsan " + str(self.vsan)
output = self.execute_show_zoneset_cmd().split("\n")
for line in output:
line = line.strip()
mzs = re.match(patZoneset, line.strip())
mz = re.match(patZone, line.strip())
if mzs:
zonesetname = mzs.group(1).strip()
self.zsDetails[zonesetname] = []
continue
elif mz:
zonename = mz.group(1).strip()
v = self.zsDetails[zonesetname]
v.append(zonename)
self.zsDetails[zonesetname] = v
def isZonesetPresent(self, zsname):
return zsname in self.zsDetails.keys()
def isZonePresentInZoneset(self, zsname, zname):
if zsname in self.zsDetails.keys():
return zname in self.zsDetails[zsname]
return False
class ShowZone(object):
"""docstring for ShowZone"""
def __init__(self, module, vsan):
self.vsan = vsan
self.module = module
self.zDetails = {}
self.parseCmdOutput()
def execute_show_zone_vsan_cmd(self):
command = 'show zone vsan ' + str(self.vsan)
output = execute_show_command(command, self.module)[0]
return output
def parseCmdOutput(self):
patZone = r"zone name (\S+) vsan " + str(self.vsan)
output = self.execute_show_zone_vsan_cmd().split("\n")
for line in output:
line = ' '.join(line.strip().split())
m = re.match(patZone, line)
if m:
zonename = m.group(1).strip()
self.zDetails[zonename] = []
continue
else:
# For now we support only pwwn and device-alias under zone
# Ideally should use 'supported_choices'....but maybe next time.
if "pwwn" in line or "device-alias" in line:
v = self.zDetails[zonename]
v.append(line)
self.zDetails[zonename] = v
def isZonePresent(self, zname):
return zname in self.zDetails.keys()
def isZoneMemberPresent(self, zname, cmd):
if zname in self.zDetails.keys():
return cmd in self.zDetails[zname]
return False
class ShowZoneStatus(object):
"""docstring for ShowZoneStatus"""
def __init__(self, module, vsan):
self.vsan = vsan
self.vsanAbsent = False
self.module = module
self.default_zone = ""
self.mode = ""
self.session = ""
self.sz = ""
self.locked = False
self.update()
def execute_show_zone_status_cmd(self):
command = 'show zone status vsan ' + str(self.vsan)
output = execute_show_command(command, self.module)[0]
return output
def update(self):
output = self.execute_show_zone_status_cmd().split("\n")
patfordefzone = "VSAN: " + str(self.vsan) + r" default-zone:\s+(\S+).*"
patformode = r".*mode:\s+(\S+).*"
patforsession = r".*session:\s+(\S+).*"
patforsz = r".*smart-zoning:\s+(\S+).*"
for line in output:
if "is not configured" in line:
self.vsanAbsent = True
break
mdefz = re.match(patfordefzone, line.strip())
mmode = re.match(patformode, line.strip())
msession = re.match(patforsession, line.strip())
msz = re.match(patforsz, line.strip())
if mdefz:
self.default_zone = mdefz.group(1)
if mmode:
self.mode = mmode.group(1)
if msession:
self.session = msession.group(1)
if self.session != "none":
self.locked = True
if msz:
self.sz = msz.group(1)
def isLocked(self):
return self.locked
def getDefaultZone(self):
return self.default_zone
def getMode(self):
return self.mode
def getSmartZoningStatus(self):
return self.sz
def isVsanAbsent(self):
return self.vsanAbsent
def execute_show_command(command, module, command_type='cli_show'):
output = 'text'
commands = [{
'command': command,
'output': output,
}]
return run_commands(module, commands)
def flatten_list(command_lists):
flat_command_list = []
for command in command_lists:
if isinstance(command, list):
flat_command_list.extend(command)
else:
flat_command_list.append(command)
return flat_command_list
def getMemType(supported_choices, allmemkeys, default='pwwn'):
for eachchoice in supported_choices:
if eachchoice in allmemkeys:
return eachchoice
return default
def main():
supported_choices = ['device_alias']
zone_member_spec = dict(
pwwn=dict(required=True, type='str', aliases=['device_alias']),
devtype=dict(type='str', choices=['initiator', 'target', 'both']),
remove=dict(type='bool', default=False)
)
zone_spec = dict(
name=dict(required=True, type='str'),
members=dict(type='list', elements='dict', options=zone_member_spec),
remove=dict(type='bool', default=False)
)
zoneset_member_spec = dict(
name=dict(required=True, type='str'),
remove=dict(type='bool', default=False)
)
zoneset_spec = dict(
name=dict(type='str', required=True),
members=dict(type='list', elements='dict', options=zoneset_member_spec),
remove=dict(type='bool', default=False),
action=dict(type='str', choices=['activate', 'deactivate'])
)
zonedetails_spec = dict(
vsan=dict(required=True, type='int'),
mode=dict(type='str', choices=['enhanced', 'basic']),
default_zone=dict(type='str', choices=['permit', 'deny']),
smart_zoning=dict(type='bool'),
zone=dict(type='list', elements='dict', options=zone_spec),
zoneset=dict(type='list', elements='dict', options=zoneset_spec),
)
argument_spec = dict(
zone_zoneset_details=dict(type='list', elements='dict', options=zonedetails_spec)
)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
warnings = list()
messages = list()
commands = list()
result = {'changed': False}
commands_executed = []
listOfZoneDetails = module.params['zone_zoneset_details']
for eachZoneZonesetDetail in listOfZoneDetails:
vsan = eachZoneZonesetDetail['vsan']
op_mode = eachZoneZonesetDetail['mode']
op_default_zone = eachZoneZonesetDetail['default_zone']
op_smart_zoning = eachZoneZonesetDetail['smart_zoning']
op_zone = eachZoneZonesetDetail['zone']
op_zoneset = eachZoneZonesetDetail['zoneset']
# Step1: execute show zone status and get
shZoneStatusObj = ShowZoneStatus(module, vsan)
sw_default_zone = shZoneStatusObj.getDefaultZone()
sw_mode = shZoneStatusObj.getMode()
sw_smart_zoning = shZoneStatusObj.getSmartZoningStatus()
if sw_smart_zoning.lower() == "Enabled".lower():
sw_smart_zoning_bool = True
else:
sw_smart_zoning_bool = False
if shZoneStatusObj.isVsanAbsent():
module.fail_json(msg='Vsan ' + str(vsan) + ' is not present in the switch. Hence cannot procced.')
if shZoneStatusObj.isLocked():
module.fail_json(msg='zone has acquired lock on the switch for vsan ' + str(vsan) + '. Hence cannot procced.')
# Process zone default zone options
if op_default_zone is not None:
if op_default_zone != sw_default_zone:
if op_default_zone == "permit":
commands_executed.append("zone default-zone permit vsan " + str(vsan))
messages.append("default zone configuration changed from deny to permit for vsan " + str(vsan))
else:
commands_executed.append("no zone default-zone permit vsan " + str(vsan))
messages.append("default zone configuration changed from permit to deny for vsan " + str(vsan))
else:
messages.append("default zone is already " + op_default_zone + " ,no change in default zone configuration for vsan " + str(vsan))
# Process zone mode options
if op_mode is not None:
if op_mode != sw_mode:
if op_mode == "enhanced":
commands_executed.append("zone mode enhanced vsan " + str(vsan))
messages.append("zone mode configuration changed from basic to enhanced for vsan " + str(vsan))
else:
commands_executed.append("no zone mode enhanced vsan " + str(vsan))
messages.append("zone mode configuration changed from enhanced to basic for vsan " + str(vsan))
else:
messages.append("zone mode is already " + op_mode + " ,no change in zone mode configuration for vsan " + str(vsan))
# Process zone smart-zone options
if op_smart_zoning is not None:
if op_smart_zoning != sw_smart_zoning_bool:
if op_smart_zoning:
commands_executed.append("zone smart-zoning enable vsan " + str(vsan))
messages.append("smart-zoning enabled for vsan " + str(vsan))
else:
commands_executed.append("no zone smart-zoning enable vsan " + str(vsan))
messages.append("smart-zoning disabled for vsan " + str(vsan))
else:
messages.append("smart-zoning is already set to " + sw_smart_zoning + " , no change in smart-zoning configuration for vsan " + str(vsan))
# Process zone member options
# TODO: Obviously this needs to be cleaned up properly, as there are a lot of ifelse statements which is bad
# Will take it up later becoz of time constraints
if op_zone is not None:
shZoneObj = ShowZone(module, vsan)
for eachzone in op_zone:
zname = eachzone['name']
zmembers = eachzone['members']
removeflag = eachzone['remove']
if removeflag:
if shZoneObj.isZonePresent(zname):
messages.append("zone '" + zname + "' is removed from vsan " + str(vsan))
commands_executed.append("no zone name " + zname + " vsan " + str(vsan))
else:
messages.append("zone '" + zname + "' is not present in vsan " + str(vsan) + " , so nothing to remove")
else:
if zmembers is None:
if shZoneObj.isZonePresent(zname):
messages.append("zone '" + zname + "' is already present in vsan " + str(vsan))
else:
commands_executed.append("zone name " + zname + " vsan " + str(vsan))
messages.append("zone '" + zname + "' is created in vsan " + str(vsan))
else:
cmdmemlist = []
for eachmem in zmembers:
memtype = getMemType(supported_choices, eachmem.keys())
cmd = memtype.replace('_', '-') + " " + eachmem[memtype]
if op_smart_zoning or sw_smart_zoning_bool:
if eachmem['devtype'] is not None:
cmd = cmd + " " + eachmem['devtype']
if eachmem["remove"]:
if shZoneObj.isZonePresent(zname):
if shZoneObj.isZoneMemberPresent(zname, cmd):
cmd = "no member " + cmd
cmdmemlist.append(cmd)
if op_smart_zoning and eachmem['devtype'] is not None:
messages.append(
"removing zone member '" +
eachmem[memtype] +
" of device type '" +
eachmem['devtype'] +
"' from zone '" +
zname +
"' in vsan " +
str(vsan))
else:
messages.append("removing zone member '" + eachmem[memtype] + "' from zone '" + zname + "' in vsan " + str(vsan))
else:
if op_smart_zoning and eachmem['devtype'] is not None:
messages.append(
"zone member '" +
eachmem[memtype] +
"' of device type '" +
eachmem['devtype'] +
"' is not present in zone '" +
zname +
"' in vsan " +
str(vsan) +
" hence nothing to remove")
else:
messages.append(
"zone member '" +
eachmem[memtype] +
"' is not present in zone '" +
zname +
"' in vsan " +
str(vsan) +
" hence nothing to remove")
else:
messages.append("zone '" + zname + "' is not present in vsan " + str(vsan) + " , hence cannot remove the members")
else:
if shZoneObj.isZoneMemberPresent(zname, cmd):
if op_smart_zoning and eachmem['devtype'] is not None:
messages.append(
"zone member '" +
eachmem[memtype] +
"' of device type '" +
eachmem['devtype'] +
"' is already present in zone '" +
zname +
"' in vsan " +
str(vsan) +
" hence nothing to add")
else:
messages.append(
"zone member '" +
eachmem[memtype] +
"' is already present in zone '" +
zname +
"' in vsan " +
str(vsan) +
" hence nothing to add")
else:
cmd = "member " + cmd
cmdmemlist.append(cmd)
if op_smart_zoning and eachmem['devtype'] is not None:
messages.append(
"adding zone member '" +
eachmem[memtype] +
"' of device type '" +
eachmem['devtype'] +
"' to zone '" +
zname +
"' in vsan " +
str(vsan))
else:
messages.append("adding zone member '" + eachmem[memtype] + "' to zone '" + zname + "' in vsan " + str(vsan))
if len(cmdmemlist) != 0:
commands_executed.append("zone name " + zname + " vsan " + str(vsan))
commands_executed = commands_executed + cmdmemlist
# Process zoneset member options
if op_zoneset is not None:
dactcmd = []
actcmd = []
shZonesetObj = ShowZoneset(module, vsan)
shZonesetActiveObj = ShowZonesetActive(module, vsan)
for eachzoneset in op_zoneset:
zsetname = eachzoneset['name']
zsetmembers = eachzoneset['members']
removeflag = eachzoneset['remove']
actionflag = eachzoneset['action']
if removeflag:
if shZonesetObj.isZonesetPresent(zsetname):
messages.append("zoneset '" + zsetname + "' is removed from vsan " + str(vsan))
commands_executed.append("no zoneset name " + zsetname + " vsan " + str(vsan))
else:
messages.append("zoneset '" + zsetname + "' is not present in vsan " + str(vsan) + " ,hence there is nothing to remove")
else:
if zsetmembers is not None:
cmdmemlist = []
for eachzsmem in zsetmembers:
zsetmem_name = eachzsmem['name']
zsetmem_removeflag = eachzsmem['remove']
if zsetmem_removeflag:
if shZonesetObj.isZonePresentInZoneset(zsetname, zsetmem_name):
cmd = "no member " + zsetmem_name
cmdmemlist.append(cmd)
messages.append("removing zoneset member '" + zsetmem_name + "' from zoneset '" + zsetname + "' in vsan " + str(vsan))
else:
messages.append("zoneset member '" + zsetmem_name + "' is not present in zoneset '" +
zsetname + "' in vsan " + str(vsan) + " ,hence there is nothing to remove")
else:
if shZonesetObj.isZonePresentInZoneset(zsetname, zsetmem_name):
messages.append("zoneset member '" + zsetmem_name + "' is already present in zoneset '" +
zsetname + "' in vsan " + str(vsan) + " ,hence there is nothing to add")
else:
cmd = "member " + zsetmem_name
cmdmemlist.append(cmd)
messages.append("adding zoneset member '" + zsetmem_name + "' to zoneset '" + zsetname + "' in vsan " + str(vsan))
if len(cmdmemlist) != 0:
commands_executed.append("zoneset name " + zsetname + " vsan " + str(vsan))
commands_executed = commands_executed + cmdmemlist
else:
if shZonesetObj.isZonesetPresent(zsetname):
messages.append("zoneset '" + zsetname + "' is already present in vsan " + str(vsan))
else:
commands_executed.append("zoneset name " + zsetname + " vsan " + str(vsan))
messages.append("zoneset '" + zsetname + "' is created in vsan " + str(vsan))
# Process zoneset activate options
if actionflag == 'deactivate':
if shZonesetActiveObj.isZonesetActive(zsetname):
messages.append("deactivating zoneset '" + zsetname + "' in vsan " + str(vsan))
dactcmd.append("no zoneset activate name " + zsetname + " vsan " + str(vsan))
else:
messages.append("zoneset '" + zsetname + "' in vsan " + str(vsan) + " is not activated, hence cannot deactivate")
elif actionflag == 'activate':
if shZonesetActiveObj.isZonesetActive(zsetname):
messages.append("zoneset '" + zsetname + "' in vsan " + str(vsan) + " is already activated")
else:
messages.append("activating zoneset '" + zsetname + "' in vsan " + str(vsan))
actcmd.append("zoneset activate name " + zsetname + " vsan " + str(vsan))
commands_executed = commands_executed + dactcmd + actcmd
if commands_executed:
if op_mode == "enhanced":
commands_executed.append("zone commit vsan " + str(vsan))
elif op_mode is None:
if sw_mode == "enhanced":
commands_executed.append("zone commit vsan " + str(vsan))
if commands_executed:
commands_executed = ["terminal dont-ask"] + commands_executed + ["no terminal dont-ask"]
cmds = flatten_list(commands_executed)
if cmds:
if module.check_mode:
module.exit_json(changed=False, commands=cmds, msg="Check Mode: No cmds issued to the hosts")
else:
result['changed'] = True
commands = commands + cmds
load_config(module, cmds)
result['messages'] = messages
result['commands'] = commands_executed
result['warnings'] = warnings
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,2 @@
---
testcase: "*"

View file

@ -0,0 +1,2 @@
# dependencies:
# - prepare_nxos_tests

View file

@ -0,0 +1,27 @@
---
- name: collect common test cases
find:
paths: "{{ role_path }}/tests/common"
patterns: "{{ testcase }}.yaml"
connection: local
register: test_cases
- name: collect cli test cases
find:
paths: "{{ role_path }}/tests/cli"
patterns: "{{ testcase }}.yaml"
connection: local
register: cli_cases
- set_fact:
test_cases:
files: "{{ test_cases.files }} + {{ cli_cases.files }}"
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test cases (connection=network_cli)
include: "{{ test_case_to_run }} ansible_connection=network_cli connection={{ cli }}"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -0,0 +1,16 @@
#---
# Check platform type and skip if not MDS
---
- name: Check platform type and skip if not MDS
nxos_command:
commands: show version | grep MDS
register: result
- set_fact: skip_test=False
- set_fact: skip_test=True
when: result.stdout[0] is not search('MDS')
- include: cli.yaml
tags: 'cli'
when: not skip_test

View file

@ -0,0 +1,42 @@
---
- debug: msg="START connection={{ ansible_connection }} nxos_devicealias sanity test"
- name: Setup - Remove device alias if configured
nxos_devicealias: &remove
da:
- { name: 'ansible_test1_add', remove: True}
- { name: 'ansible_test2_add', remove: True}
ignore_errors: yes
- block:
- name: Configure device alias
nxos_devicealias: &config
da:
- { name: 'ansible_test1_add', pwwn: '57:bb:cc:dd:ee:ff:11:67'}
- { name: 'ansible_test2_add', pwwn: '65:22:21:20:19:18:1a:0d'}
register: result
- assert: &true
that:
- result.changed == true
- assert:
that:
- result.commands == ["terminal dont-ask", "device-alias database", "device-alias name ansible_test1_add pwwn 57:bb:cc:dd:ee:ff:11:67", "device-alias name ansible_test2_add pwwn 65:22:21:20:19:18:1a:0d", "device-alias commit", "no terminal dont-ask"]
- name: Idempotence Check
nxos_devicealias: *config
register: result
- assert: &false
that:
- result.changed == false
- assert:
that:
- result.commands == []
always:
- name: Remove device alias config
nxos_devicealias: *remove
- debug: msg="END connection={{ ansible_connection }} nxos_devicealias sanity test"

View file

@ -0,0 +1,2 @@
---
testcase: "*"

View file

@ -0,0 +1,2 @@
# dependencies:
# - prepare_nxos_tests

View file

@ -0,0 +1,27 @@
---
- name: collect common test cases
find:
paths: "{{ role_path }}/tests/common"
patterns: "{{ testcase }}.yaml"
connection: local
register: test_cases
- name: collect cli test cases
find:
paths: "{{ role_path }}/tests/cli"
patterns: "{{ testcase }}.yaml"
connection: local
register: cli_cases
- set_fact:
test_cases:
files: "{{ test_cases.files }} + {{ cli_cases.files }}"
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test cases (connection=network_cli)
include: "{{ test_case_to_run }} ansible_connection=network_cli connection={{ cli }}"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -0,0 +1,16 @@
#---
# Check platform type and skip if not MDS
---
- name: Check platform type and skip if not MDS
nxos_command:
commands: show version | grep MDS
register: result
- set_fact: skip_test=False
- set_fact: skip_test=True
when: result.stdout[0] is not search('MDS')
- include: cli.yaml
tags: 'cli'
when: not skip_test

View file

@ -0,0 +1,50 @@
---
- debug: msg="START nxos_vsan sanity test with connection={{ ansible_connection }} "
- debug: msg="Using vsans {{ vsan1 }}, {{ vsan2 }} for running this sanity test, please make sure these are not used in the setup, these will be deleted after the tests"
- block:
- name: Setup - Remove vsan if configured
nxos_vsan: &remove
vsan:
- { id: "{{ vsan1 | int }}", remove: True}
- { id: "{{ vsan2 | int }}", remove: True}
ignore_errors: yes
- name: Configure vsan
nxos_vsan: &config
vsan:
- id: "{{ vsan1 | int }}"
name: vsan-SAN-A
suspend: True
interface:
- "{{intA1}}"
remove: False
- id: "{{ vsan2 | int }}"
name: vsan-SAN-B
interface:
- "{{intB1}}"
remove: False
register: result
- assert: &true
that:
- result.changed == true
- assert:
that:
- result.commands == ["terminal dont-ask", "vsan database", "vsan 922", "vsan 922 name vsan-SAN-A", "vsan 922 suspend", "vsan 922 interface fc1/1", "vsan 923", "vsan 923 name vsan-SAN-B", "no vsan 923 suspend", "vsan 923 interface fc1/2", "no terminal dont-ask"]
- name: Idempotence Check
nxos_vsan: *config
register: result
- assert: &false
that:
- result.changed == false
- assert:
that:
- result.commands == []
always:
- name: Remove vsan config
nxos_vsan: *remove

View file

@ -0,0 +1,4 @@
vsan1: 922
vsan2: 923
intA1: fc1/1
intB1: fc1/2

View file

@ -0,0 +1,2 @@
---
testcase: "*"

View file

@ -0,0 +1,2 @@
# dependencies:
# - prepare_nxos_tests

View file

@ -0,0 +1,27 @@
---
- name: collect common test cases
find:
paths: "{{ role_path }}/tests/common"
patterns: "{{ testcase }}.yaml"
connection: local
register: test_cases
- name: collect cli test cases
find:
paths: "{{ role_path }}/tests/cli"
patterns: "{{ testcase }}.yaml"
connection: local
register: cli_cases
- set_fact:
test_cases:
files: "{{ test_cases.files }} + {{ cli_cases.files }}"
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test cases (connection=network_cli)
include: "{{ test_case_to_run }} ansible_connection=network_cli connection={{ cli }}"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -0,0 +1,16 @@
#---
# Check platform type and skip if not MDS
---
- name: Check platform type and skip if not MDS
nxos_command:
commands: show version | grep MDS
register: result
- set_fact: skip_test=False
- set_fact: skip_test=True
when: result.stdout[0] is not search('MDS')
- include: cli.yaml
tags: 'cli'
when: not skip_test

View file

@ -0,0 +1,145 @@
---
- debug: "msg=\"START nxos_zone_zoneset sanity test with connection={{ ansible_connection }} \""
- debug: "msg=\"Using vsans {{ vsan1 }}, {{ vsan2 }} for running this sanity test, please make sure these are not used in the setup, these will be deleted after the tests\""
- always:
- name: "Remove vsan config"
nxos_vsan:
vsan:
- id: "{{ vsan1 | int }}"
remove: true
- id: "{{ vsan2 | int }}"
remove: true
block:
- ignore_errors: true
name: "Setup - Remove vsan if configured"
nxos_vsan:
vsan:
- id: "{{ vsan1 | int }}"
remove: true
- id: "{{ vsan2 | int }}"
remove: true
- name: "Configure vsan"
nxos_vsan:
vsan:
- id: "{{ vsan1 | int }}"
- id: "{{ vsan2 | int }}"
- name: "Configure zone and zoneset"
nxos_zone_zoneset: &zoneset
zone_zoneset_details:
- mode: enhanced
vsan: "{{ vsan1 | int }}"
zone:
- members:
- pwwn: "11:11:11:11:11:11:11:11"
- device_alias: test123
- pwwn: "61:61:62:62:12:12:12:12"
remove: true
name: zoneA
- members:
- pwwn: "10:11:11:11:11:11:11:11"
- pwwn: "62:62:62:62:21:21:21:21"
name: zoneB
- name: zoneC
remove: true
zoneset:
- action: activate
members:
- name: zoneA
- name: zoneB
- name: zoneC
remove: true
name: zsetname1
- action: deactivate
name: zsetTestExtra
remove: true
- mode: basic
smart_zoning: true
vsan: "{{ vsan2 | int }}"
zone:
- members:
- devtype: both
pwwn: "11:11:11:11:11:11:11:11"
- pwwn: "62:62:62:62:12:12:12:12"
- devtype: both
pwwn: "92:62:62:62:12:12:1a:1a"
remove: true
name: zone21A
- members:
- pwwn: "10:11:11:11:11:11:11:11"
- pwwn: "62:62:62:62:21:21:21:21"
- device_alias: somedummyname
- device_alias: anydummyname
remove: true
name: zone21B
zoneset:
- action: activate
members:
- name: zone21A
- name: zone21B
name: zsetname21
register: result
- assert:
that:
- result.changed == true
- assert:
that:
- result.commands == ["terminal dont-ask", "zone mode enhanced vsan 922", "zone name zoneA vsan 922", "member pwwn 11:11:11:11:11:11:11:11", "member device-alias test123", "zone name zoneB vsan 922", "member pwwn 10:11:11:11:11:11:11:11", "member pwwn 62:62:62:62:21:21:21:21", "zoneset name zsetname1 vsan 922", "member zoneA", "member zoneB", "zoneset activate name zsetname1 vsan 922", "zone commit vsan 922", "zone smart-zoning enable vsan 923", "zone name zone21A vsan 923", "member pwwn 11:11:11:11:11:11:11:11 both", "member pwwn 62:62:62:62:12:12:12:12", "zone name zone21B vsan 923", "member pwwn 10:11:11:11:11:11:11:11", "member pwwn 62:62:62:62:21:21:21:21", "member device-alias somedummyname", "zoneset name zsetname21 vsan 923", "member zone21A", "member zone21B", "zoneset activate name zsetname21 vsan 923", "no terminal dont-ask"]
- name: "Idempotence Check"
nxos_zone_zoneset: *zoneset
register: result
- assert:
that:
- result.commands == []
- assert:
that:
- result.changed == false
- name: "Delete zone and zoneset that was configured"
nxos_zone_zoneset: &zonesetdelete
zone_zoneset_details:
- mode: enhanced
vsan: "{{ vsan1 | int }}"
zone:
- name: zoneA
remove: true
- name: zoneB
remove: true
- name: zoneC
remove: true
zoneset:
- name: zsetname1
remove: true
- action: deactivate
name: zsetTestExtra
remove: true
- mode: basic
smart_zoning: true
vsan: "{{ vsan2 | int }}"
zone:
- name: zone21A
remove: true
- name: zone21B
remove: true
zoneset:
- name: zsetname21
remove: true
register: result
- assert:
that:
- result.changed == true
- assert:
that:
- result.commands == ["terminal dont-ask", "no zone name zoneA vsan 922", "no zone name zoneB vsan 922", "no zoneset name zsetname1 vsan 922", "zone commit vsan 922", "no zone name zone21A vsan 923", "no zone name zone21B vsan 923", "no zoneset name zsetname21 vsan 923", "no terminal dont-ask"]
- name: "Idempotence Check for zone/zoneset removal"
nxos_zone_zoneset: *zonesetdelete
register: result
- assert:
that:
- result.commands == []
- assert:
that:
- result.changed == false

View file

@ -0,0 +1,4 @@
vsan1: 922
vsan2: 923
intA1: fc1/1
intB1: fc1/2

View file

@ -0,0 +1,5 @@
device-alias name test1_add pwwn 56:02:22:11:22:88:11:67
device-alias name test2_add pwwn 65:22:22:11:22:22:11:0d
device-alias name tieHost-1 pwwn 10:00:00:00:89:a1:01:01
device-alias name tieHost-2 pwwn 10:00:00:00:89:a1:01:02

View file

@ -0,0 +1,4 @@
Fabric Distribution : Enabled
Database:- Device Aliases 3831 Mode: Enhanced
Checksum: 0xdc7b6c6c124abd8fe28cf6a1ab293c

View file

@ -0,0 +1,4 @@
Fabric Distribution : Disabled
Database:- Device Aliases 3831 Mode: Basic
Checksum: 0xdc7b6c6c124abd8fe28cf6a1ab293c

View file

@ -0,0 +1,6 @@
Fabric Distribution : Enabled
Database:- Device Aliases 3831 Mode: Enhanced
Checksum: 0xdc7b6c6c124abd8fe28cf6a1ab293c
Locked By:- User "CLI/SNMPv3:admin" SWWN 20:00:54:7f:ee:1b:13:f0
Pending Database:- Device Aliases 3831 Mode: Enhanced

View file

@ -0,0 +1,35 @@
vsan 1 information
name:VSAN0001 state:active
interoperability mode:default
loadbalancing:src-id/dst-id/oxid
operational state:up
vsan 10 information
name:VsanAll state:suspended
interoperability mode:default
loadbalancing:src-id/dst-id/oxid
operational state:down
vsan 221 information
name:VSAN0221 state:active
interoperability mode:default
loadbalancing:src-id/dst-id/oxid
operational state:up
vsan 922 information
name:vsan-SAN-A state:active
interoperability mode:default
loadbalancing:src-id/dst-id/oxid
operational state:down
vsan 923 information
name:vsan-SAN-B state:active
interoperability mode:default
loadbalancing:src-id/dst-id/oxid
operational state:up
vsan 4079:evfp_isolated_vsan
vsan 4094:isolated_vsan

View file

@ -0,0 +1,30 @@
vsan 1 interfaces:
fc1/4 fc1/5 fc1/6 fc1/7
fc1/8 fc1/9 fc1/10 fc1/12
fc1/13 fc1/14 fc1/15 fc1/16
fc1/17 fc1/18 fc1/19 fc1/20
fc1/22 fc1/23 fc1/24 fc1/25
fc1/26 fc1/27 fc1/28 fc1/29
fc1/30 fc1/31 fc1/32 fc1/33
fc1/34 fc1/35 fc1/36 fc1/37
fc1/38 fc1/39 fc1/40
vsan 10 interfaces:
vsan 221 interfaces:
vsan 922 interfaces:
fc1/1 fc1/2 fc1/3 port-channel55
vsan 923 interfaces:
fc1/11 fc1/21 port-channel56
vsan 4079(evfp_isolated_vsan) interfaces:
vsan 4094(isolated_vsan) interfaces:
port-channel145

View file

@ -0,0 +1,8 @@
zone name zoneA vsan 923
pwwn 11:11:11:11:11:11:11:11
device-alias test123
zone name zoneB vsan 923
pwwn 10:11:11:11:11:11:11:11
pwwn 62:62:62:62:21:21:21:21

View file

@ -0,0 +1,8 @@
zone name zoneA vsan 922
pwwn 11:11:11:11:11:11:11:11
device-alias test123 both
zone name zoneB vsan 922
pwwn 10:11:11:11:11:11:11:11
pwwn 62:62:62:62:21:21:21:21

View file

@ -0,0 +1,6 @@
zone name zv221 vsan 221
pwwn 21:01:00:1b:32:a1:c0:a8 [h181-dell-linux-top-p2]
pwwn 10:00:00:90:fa:c7:da:42 [h172-32ghost-p2]
pwwn 21:01:00:1b:32:aa:50:4b [h190-dell-linux-top-p2]
pwwn 50:06:01:6a:47:e4:6e:59 [VNX_UNITY_235_SPB-1-2]
pwwn 21:01:00:1b:32:aa:ff:4a [h189-dell-windows-bottom-p2]

View file

@ -0,0 +1,10 @@
zoneset name zsetname21 vsan 922
zone name zone21A vsan 922
pwwn 11:11:11:11:11:11:11:11 both
pwwn 62:62:62:62:12:12:12:12
zone name zone21B vsan 922
pwwn 10:11:11:11:11:11:11:11
pwwn 62:62:62:62:21:21:21:21
device-alias somedummyname

View file

@ -0,0 +1,9 @@
zoneset name zsetname1 vsan 923
zone name zoneA vsan 923
pwwn 11:11:11:11:11:11:11:11
device-alias test123
zone name zoneB vsan 923
pwwn 10:11:11:11:11:11:11:11
pwwn 62:62:62:62:21:21:21:21

View file

@ -0,0 +1,7 @@
zoneset name zsv221 vsan 221
zone name zv221 vsan 221
pwwn 21:01:00:1b:32:a1:c0:a8 [h181-dell-linux-top-p2]
pwwn 10:00:00:90:fa:c7:da:42 [h172-32ghost-p2]
pwwn 21:01:00:1b:32:aa:50:4b [h190-dell-linux-top-p2]
pwwn 50:06:01:6a:47:e4:6e:59 [VNX_UNITY_235_SPB-1-2]
pwwn 21:01:00:1b:32:aa:ff:4a [h189-dell-windows-bottom-p2]

View file

@ -0,0 +1,8 @@
zoneset name zsv221 vsan 221
zone name zv221 vsan 221
* fcid 0x2f0000 [pwwn 21:01:00:1b:32:a1:c0:a8] [h181-dell-linux-top-p2]
* fcid 0xa90000 [pwwn 10:00:00:90:fa:c7:da:42] [h172-32ghost-p2]
* fcid 0xd50000 [pwwn 21:01:00:1b:32:aa:50:4b] [h190-dell-linux-top-p2]
* fcid 0xde0000 [pwwn 50:06:01:6a:47:e4:6e:59] [VNX_UNITY_235_SPB-1-2]
pwwn 21:01:00:1b:32:aa:ff:4a [h189-dell-windows-bottom-p2]

View file

@ -0,0 +1,23 @@
VSAN: 922 default-zone: deny distribute: active only Interop: default
mode: basic merge-control: allow
session: none
hard-zoning: enabled broadcast: unsupported
smart-zoning: enabled
rscn-format: fabric-address
activation overwrite control: disabled
Default zone:
qos: none broadcast: unsupported ronly: unsupported
Full Zoning Database :
DB size: 358 bytes
Zonesets: 1 Zones: 2 Aliases: 0
Active Zoning Database :
DB Size: 125 bytes
Name: zsetname21 Zonesets: 1 Zones: 2
Current Total Zone DB Usage: 483 / 2097152 bytes (0 % used)
Pending (Session) DB size:
Full DB Copy size: n/a
Active DB Copy size: n/a
SFC size: 483 / 2097152 bytes (0 % used)
Status: Activation completed at 23:50:35 IST Jul 3 2019

View file

@ -0,0 +1,23 @@
VSAN: 922 default-zone: deny distribute: full Interop: default
mode: enhanced merge-control: allow
session: none
hard-zoning: enabled broadcast: unsupported
smart-zoning: disabled
rscn-format: fabric-address
activation overwrite control: disabled
Default zone:
qos: none broadcast: unsupported ronly: unsupported
Full Zoning Database :
DB size: 376 bytes
Zonesets: 1 Zones: 2 Aliases: 0 Attribute-groups: 1
Active Zoning Database :
DB Size: 156 bytes
Name: zsetname21 Zonesets: 1 Zones: 2
Current Total Zone DB Usage: 532 / 2097152 bytes (0 % used)
Pending (Session) DB size:
Full DB Copy size: 0 bytes
Active DB Copy size: 0 bytes
SFC size: 0 / 2097152 bytes (0 % used)
Status: Set zoning mode complete at 10:19:02 IST Jul 5 2019

View file

@ -0,0 +1,24 @@
VSAN: 923 default-zone: permit distribute: full Interop: default
mode: enhanced merge-control: allow
session: none
hard-zoning: enabled broadcast: unsupported
smart-zoning: disabled
rscn-format: fabric-address
activation overwrite control: disabled
Default zone:
qos: none broadcast: unsupported ronly: unsupported
Full Zoning Database :
DB size: 356 bytes
Zonesets: 1 Zones: 2 Aliases: 0 Attribute-groups: 1
Active Zoning Database :
DB Size: 136 bytes
Name: zsetname1 Zonesets: 1 Zones: 2
Current Total Zone DB Usage: 492 / 2097152 bytes (0 % used)
Pending (Session) DB size:
Full DB Copy size: 0 bytes
Active DB Copy size: 0 bytes
SFC size: 0 / 2097152 bytes (0 % used)
Status: Operation failed: [Error: WARNING: Specified zoneset already active and unchanged]:
at 11:06:21 IST Jul 5 2019

View file

@ -0,0 +1,24 @@
VSAN: 923 default-zone: permit distribute: full Interop: default
mode: basic merge-control: allow
session: none
hard-zoning: enabled broadcast: unsupported
smart-zoning: disabled
rscn-format: fabric-address
activation overwrite control: disabled
Default zone:
qos: none broadcast: unsupported ronly: unsupported
Full Zoning Database :
DB size: 356 bytes
Zonesets: 1 Zones: 2 Aliases: 0 Attribute-groups: 1
Active Zoning Database :
DB Size: 136 bytes
Name: zsetname1 Zonesets: 1 Zones: 2
Current Total Zone DB Usage: 492 / 2097152 bytes (0 % used)
Pending (Session) DB size:
Full DB Copy size: 0 bytes
Active DB Copy size: 0 bytes
SFC size: 0 / 2097152 bytes (0 % used)
Status: Operation failed: [Error: WARNING: Specified zoneset already active and unchanged]:
at 11:06:21 IST Jul 5 2019

View file

@ -0,0 +1,23 @@
VSAN: 221 default-zone: deny distribute: full Interop: default
mode: enhanced merge-control: allow
session: none
hard-zoning: enabled broadcast: unsupported
smart-zoning: disabled
rscn-format: fabric-address
activation overwrite control: disabled
Default zone:
qos: none broadcast: unsupported ronly: unsupported
Full Zoning Database :
DB size: 300 bytes
Zonesets: 1 Zones: 1 Aliases: 0 Attribute-groups: 1
Active Zoning Database :
DB Size: 112 bytes
Name: zsv221 Zonesets: 1 Zones: 1
Current Total Zone DB Usage: 412 / 2097152 bytes (0 % used)
Pending (Session) DB size:
Full DB Copy size: 0 bytes
Active DB Copy size: 0 bytes
SFC size: 0 / 2097152 bytes (0 % used)
Status:

View file

@ -0,0 +1,229 @@
#!/usr/bin/env python
# Copyright: Ansible Project
# 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
import pytest
from units.compat.mock import patch
from units.modules.utils import AnsibleFailJson
from ansible.modules.network.nxos.storage import nxos_devicealias
from ansible.modules.network.nxos.storage.nxos_devicealias import showDeviceAliasStatus
from ansible.modules.network.nxos.storage.nxos_devicealias import showDeviceAliasDatabase
from ..nxos_module import TestNxosModule, load_fixture, set_module_args
class TestNxosDeviceAliasModule(TestNxosModule):
module = nxos_devicealias
def setUp(self):
super(TestNxosDeviceAliasModule, self).setUp()
module_path = 'ansible.modules.network.nxos.storage.nxos_devicealias.'
self.mock_run_commands = patch(module_path + 'run_commands')
self.run_commands = self.mock_run_commands.start()
self.mock_execute_show_cmd = patch(module_path + 'showDeviceAliasStatus.execute_show_cmd')
self.execute_show_cmd = self.mock_execute_show_cmd.start()
self.mock_execute_show_cmd_1 = patch(module_path + 'showDeviceAliasDatabase.execute_show_cmd')
self.execute_show_cmd_1 = self.mock_execute_show_cmd_1.start()
self.mock_load_config = patch(module_path + 'load_config')
self.load_config = self.mock_load_config.start()
def tearDown(self):
super(TestNxosDeviceAliasModule, self).tearDown()
self.mock_run_commands.stop()
self.mock_execute_show_cmd.stop()
self.mock_execute_show_cmd_1.stop()
self.mock_load_config.stop()
def load_fixtures(self, commands=None, device=''):
self.load_config.return_value = None
def test_da_mode_1(self):
# Playbook mode is basic
# Switch has mode as enahnced
set_module_args(dict(mode='basic'), True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask', 'no device-alias mode enhanced',
'device-alias commit', 'no terminal dont-ask'])
def test_da_mode_2(self):
# Playbook mode is enhanced
# Switch has mode as enahnced
set_module_args(dict(mode='enhanced'), True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
result = self.execute_module(changed=False)
self.assertEqual(result['commands'], [])
def test_da_distribute_1(self):
# Playbook mode is enhanced , distrbute = True
# Switch has mode as enahnced, distrbute = True
set_module_args(dict(distribute=True, mode='enhanced'), True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
result = self.execute_module(changed=False)
self.assertEqual(result['commands'], [])
def test_da_distribute_2(self):
# Playbook mode is enhanced , distrbute = False
# Switch has mode as enhanced, distrbute = True
set_module_args(dict(distribute=False, mode='enhanced'), True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['no device-alias distribute'])
def test_da_distribute_3(self):
# Playbook mode is basic , distrbute = False
# Switch has mode as enahnced, distrbute = True
set_module_args(dict(distribute=False, mode='basic'), True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['no device-alias distribute', 'no device-alias mode enhanced'])
def test_da_add_1(self):
# Playbook mode is enhanced , distrbute = true , some new da being added
# Switch has mode as enahnced, distrbute = True, switch doesnt have the new da being added
set_module_args(dict(distribute=True, mode='enhanced',
da=[dict(name='somename', pwwn='10:00:00:00:89:a1:01:03'),
dict(name='somename1', pwwn='10:00:00:00:89:a1:02:03')]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask', 'device-alias database',
'device-alias name somename pwwn 10:00:00:00:89:a1:01:03',
'device-alias name somename1 pwwn 10:00:00:00:89:a1:02:03',
'device-alias commit', 'no terminal dont-ask'])
def test_da_add_2(self):
# Playbook mode is enhanced , distrbute = true , some new da being added
# Switch has mode as enahnced, distrbute = True, switch already has the pwwn:name
set_module_args(dict(distribute=True, mode='enhanced',
da=[dict(name='tieHost-2', pwwn='10:00:00:00:89:a1:01:02')]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=False)
self.assertEqual(result['commands'], [])
def test_da_add_3(self):
# Playbook mode is enhanced , distrbute = true , some new da being added
# Switch has mode as enahnced, distrbute = True, switch same name present with different pwwn
set_module_args(dict(distribute=True, mode='enhanced',
da=[dict(name='tieHost-2', pwwn='10:00:00:00:89:a1:01:ff')]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=False, failed=True)
def test_da_add_4(self):
# Playbook mode is enhanced , distrbute = true , some new da being added
# Switch has mode as enahnced, distrbute = True, switch same pwwn present with different name
set_module_args(dict(distribute=True, mode='enhanced',
da=[dict(name='tieHost-2222', pwwn='10:00:00:00:89:a1:01:02')]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=False, failed=True)
def test_da_remove_1(self):
# Playbook mode is enhanced , distrbute = true , some da being removed
# Switch has mode as enahnced, distrbute = True, switch has the da that needs to be removed
set_module_args(dict(distribute=True, mode='enhanced',
da=[dict(name='tieHost-2', pwwn='10:00:00:00:89:a1:01:02', remove=True)]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask', 'device-alias database',
'no device-alias name tieHost-2',
'device-alias commit', 'no terminal dont-ask'])
def test_da_remove_2(self):
# Playbook mode is enhanced , distrbute = true , some da being removed
# Switch has mode as enahnced, distrbute = True, switch does NOT have the da that needs to be removed
set_module_args(dict(distribute=True, mode='enhanced',
da=[dict(name='somename', pwwn='10:00:00:00:89:a1:01:02', remove=True)]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=False)
self.assertEqual(result['commands'], [])
def test_da_lock(self):
# Playbook mode with some data, but switch has cfs lock acq
set_module_args(dict(distribute=True, mode='enhanced',
da=[dict(name='somename', pwwn='10:00:00:00:89:a1:01:02', remove=True)]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatuslock.cfg')
self.execute_module(failed=True)
def test_da_paramete_not_supported(self):
# Playbook mode with some data, but switch has cfs lock acq
# the below one instead of 'mode' we are passing 'mod', kind of typo in playbook
set_module_args(dict(distribute=True, mod='enhanced',
da=[dict(name='somename', pwwn='10:00:00:00:89:a1:01:02', remove=True)]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
with pytest.raises(AnsibleFailJson) as errinfo:
self.execute_module()
testdata = errinfo.value.args[0]
assert 'Unsupported parameters' in str(testdata['msg'])
assert testdata['failed']
def test_da_name_parameter_missing(self):
# Lets say you are trying to add a device alias but forgot to put 'name' in the 'da' parameter
set_module_args(dict(distribute=True, mode='enhanced',
da=[dict(pwwn='10:00:00:00:89:a1:01:02')]),
True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
with pytest.raises(AnsibleFailJson) as errinfo:
self.execute_module()
testdata = errinfo.value.args[0]
assert 'missing required arguments' in str(testdata['msg'])
assert testdata['failed']
def test_da_rename_1(self):
# rename works
set_module_args(dict(rename=[dict(old_name='test1_add', new_name='test234'),
dict(old_name='tieHost-1', new_name='tieTarget-1')]), True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask', 'device-alias database',
'device-alias rename test1_add test234',
'device-alias rename tieHost-1 tieTarget-1',
'device-alias commit', 'no terminal dont-ask'])
def test_da_rename_2(self):
# rename : oldname not present
set_module_args(dict(rename=[dict(old_name='test1', new_name='test234'),
dict(old_name='tie', new_name='tieTarget-1')]), True)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=False, failed=True)
self.assertEqual(result['commands'], [])
def test_da_mansi(self):
set_module_args(
{
"distribute": True,
"mode": "enhanced",
},
True
)
self.execute_show_cmd.return_value = load_fixture('nxos_devicealias', 'shdastatus_mansi.cfg')
self.execute_show_cmd_1.return_value = load_fixture('nxos_devicealias', 'shdadatabse.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['device-alias distribute', 'terminal dont-ask',
'device-alias mode enhanced',
'device-alias commit', 'no terminal dont-ask'])

View file

@ -0,0 +1,237 @@
#!/usr/bin/env python
# Copyright: Ansible Project
# 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
import pytest
from units.compat.mock import patch
from units.modules.utils import AnsibleFailJson
from ansible.modules.network.nxos.storage import nxos_vsan
from ansible.modules.network.nxos.storage.nxos_vsan import GetVsanInfoFromSwitch
from ..nxos_module import TestNxosModule, load_fixture, set_module_args
class TestNxosVsanModule(TestNxosModule):
module = nxos_vsan
def setUp(self):
super(TestNxosVsanModule, self).setUp()
module_path = 'ansible.modules.network.nxos.storage.nxos_vsan.'
self.mock_run_commands = patch(module_path + 'run_commands')
self.run_commands = self.mock_run_commands.start()
self.mock_execute_show_vsan_cmd = patch(module_path + 'GetVsanInfoFromSwitch.execute_show_vsan_cmd')
self.execute_show_vsan_cmd = self.mock_execute_show_vsan_cmd.start()
self.mock_execute_show_vsanmemcmd = patch(module_path + 'GetVsanInfoFromSwitch.execute_show_vsan_mem_cmd')
self.execute_show_vsanmem_cmd = self.mock_execute_show_vsanmemcmd.start()
self.mock_load_config = patch(module_path + 'load_config')
self.load_config = self.mock_load_config.start()
self.maxDiff = None
def tearDown(self):
super(TestNxosVsanModule, self).tearDown()
self.mock_run_commands.stop()
self.execute_show_vsan_cmd.stop()
self.execute_show_vsanmem_cmd.stop()
self.mock_load_config.stop()
def load_fixtures(self, commands=None, device=''):
self.load_config.return_value = None
def test_vsan_add_remove_but_present_in_switch(self):
margs = {
"vsan": [
{
"interface": [
"fc1/1",
"port-channel 55"
],
"id": 922,
"remove": False,
"name": "vsan-SAN-A"
},
{
"interface": [
"fc1/11",
"fc1/21",
"port-channel 56"
],
"id": 923,
"remove": False,
"name": "vsan-SAN-B"
},
{
"id": 1923,
"remove": True,
"name": "vsan-SAN-Old"
}
]
}
set_module_args(margs, True)
self.execute_show_vsan_cmd.return_value = load_fixture('nxos_vsan', 'shvsan.cfg')
self.execute_show_vsanmem_cmd.return_value = load_fixture('nxos_vsan', 'shvsanmem.cfg')
result = self.execute_module(changed=False)
self.assertEqual(result['commands'], [])
def test_vsan_remove(self):
margs = {
"vsan": [
{
"id": 922,
"remove": True
},
{
"id": 923,
"remove": True
}
]
}
set_module_args(margs, True)
self.execute_show_vsan_cmd.return_value = load_fixture('nxos_vsan', 'shvsan.cfg')
self.execute_show_vsanmem_cmd.return_value = load_fixture('nxos_vsan', 'shvsanmem.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ["terminal dont-ask"] + ["vsan database"] +
["no vsan 922", "no vsan 923"] + ["no terminal dont-ask"])
def test_vsan_add(self):
margs = {
"vsan": [
{
"interface": [
"fc1/1",
"port-channel 55"
],
"id": 924,
"name": "vsan-SAN-924"
},
{
"interface": [
"fc1/11",
"fc1/21",
"port-channel 56"
],
"id": 925,
"name": "vsan-SAN-925"
}
]
}
set_module_args(margs, True)
self.execute_show_vsan_cmd.return_value = load_fixture('nxos_vsan', 'shvsan.cfg')
self.execute_show_vsanmem_cmd.return_value = load_fixture('nxos_vsan', 'shvsanmem.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ["terminal dont-ask"] + ["vsan database"] +
["vsan 924", "vsan 924 name vsan-SAN-924", "no vsan 924 suspend",
"vsan 924 interface fc1/1", "vsan 924 interface port-channel 55"] +
["vsan 925", "vsan 925 name vsan-SAN-925", "no vsan 925 suspend", "vsan 925 interface fc1/11",
"vsan 925 interface fc1/21", "vsan 925 interface port-channel 56"] +
["no terminal dont-ask"])
def test_vsan_suspend(self):
margs = {
"vsan": [
{
"interface": [
"fc1/1",
"port-channel 55"
],
"id": 924,
"name": "vsan-SAN-924"
},
{
"id": 925,
"name": "vsan-SAN-925",
"suspend": True
}
]
}
set_module_args(margs, True)
self.execute_show_vsan_cmd.return_value = load_fixture('nxos_vsan', 'shvsan.cfg')
self.execute_show_vsanmem_cmd.return_value = load_fixture('nxos_vsan', 'shvsanmem.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ["terminal dont-ask"] + ["vsan database"] +
["vsan 924", "vsan 924 name vsan-SAN-924", "no vsan 924 suspend",
"vsan 924 interface fc1/1", "vsan 924 interface port-channel 55"] +
["vsan 925", "vsan 925 name vsan-SAN-925", "vsan 925 suspend"] +
["no terminal dont-ask"])
def test_vsan_invalid_vsan(self):
margs = {
"vsan": [
{
"id": 4096,
"name": "vsan-SAN-925",
"suspend": True
}
]
}
set_module_args(margs, True)
self.execute_show_vsan_cmd.return_value = load_fixture('nxos_vsan', 'shvsan.cfg')
self.execute_show_vsanmem_cmd.return_value = load_fixture('nxos_vsan', 'shvsanmem.cfg')
with pytest.raises(AnsibleFailJson) as errinfo:
self.execute_module()
testdata = errinfo.value.args[0]
assert 'invalid vsan' in str(testdata['msg'])
assert testdata['failed']
def test_vsan_change_reserved_vsan(self):
margs = {
"vsan": [
{
"id": 4094,
"name": "vsan-SAN-925",
"suspend": True
}
]
}
set_module_args(margs, True)
self.execute_show_vsan_cmd.return_value = load_fixture('nxos_vsan', 'shvsan.cfg')
self.execute_show_vsanmem_cmd.return_value = load_fixture('nxos_vsan', 'shvsanmem.cfg')
result = self.execute_module(changed=False)
assert 'reserved vsan' in str(result['messages'])
self.assertEqual(result['commands'], [])
def test_vsan_add_int_existing_vsan(self):
margs = {
"vsan": [
{
"interface": [
"fc1/1",
"fc1/40",
"port-channel 155"
],
"id": 922,
},
]
}
set_module_args(margs, True)
self.execute_show_vsan_cmd.return_value = load_fixture('nxos_vsan', 'shvsan.cfg')
self.execute_show_vsanmem_cmd.return_value = load_fixture('nxos_vsan', 'shvsanmem.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ["terminal dont-ask"] + ["vsan database"] +
["vsan 922 interface fc1/40", "vsan 922 interface port-channel 155"] +
["no terminal dont-ask"])
def test_vsan_remove_non_existing_vsan(self):
margs = {
"vsan": [
{
"id": 1111,
"remove": True
},
]
}
set_module_args(margs, True)
self.execute_show_vsan_cmd.return_value = load_fixture('nxos_vsan', 'shvsan.cfg')
self.execute_show_vsanmem_cmd.return_value = load_fixture('nxos_vsan', 'shvsanmem.cfg')
result = self.execute_module(changed=False)
self.assertEqual(result['commands'], [])
assert 'no vsan' in str(result['messages'])

View file

@ -0,0 +1,496 @@
#!/usr/bin/env python
# Copyright: Ansible Project
# 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
import pytest
from units.compat.mock import patch
from units.modules.utils import AnsibleFailJson, AnsibleExitJson
from ansible.modules.network.nxos.storage import nxos_zone_zoneset
from ansible.modules.network.nxos.storage.nxos_zone_zoneset import ShowZonesetActive
from ansible.modules.network.nxos.storage.nxos_zone_zoneset import ShowZoneset
from ansible.modules.network.nxos.storage.nxos_zone_zoneset import ShowZone
from ansible.modules.network.nxos.storage.nxos_zone_zoneset import ShowZoneStatus
from ..nxos_module import TestNxosModule, load_fixture, set_module_args
class TestNxosZoneZonesetModule(TestNxosModule):
module = nxos_zone_zoneset
def setUp(self):
super(TestNxosZoneZonesetModule, self).setUp()
module_path = 'ansible.modules.network.nxos.storage.nxos_zone_zoneset.'
self.mock_run_commands = patch(module_path + 'run_commands')
self.run_commands = self.mock_run_commands.start()
self.mock_execute_show_cmd_zoneset_active = patch(
module_path + 'ShowZonesetActive.execute_show_zoneset_active_cmd')
self.execute_show_cmd_zoneset_active = self.mock_execute_show_cmd_zoneset_active.start()
self.mock_execute_show_cmd_zoneset = patch(module_path + 'ShowZoneset.execute_show_zoneset_cmd')
self.execute_show_cmd_zoneset = self.mock_execute_show_cmd_zoneset.start()
self.mock_execute_show_cmd_zone = patch(module_path + 'ShowZone.execute_show_zone_vsan_cmd')
self.execute_show_cmd_zone = self.mock_execute_show_cmd_zone.start()
self.mock_execute_show_cmd_zone_status = patch(module_path + 'ShowZoneStatus.execute_show_zone_status_cmd')
self.execute_show_cmd_zone_status = self.mock_execute_show_cmd_zone_status.start()
self.mock_load_config = patch(module_path + 'load_config')
self.load_config = self.mock_load_config.start()
def tearDown(self):
super(TestNxosZoneZonesetModule, self).tearDown()
self.mock_run_commands.stop()
self.execute_show_cmd_zoneset_active.stop()
self.execute_show_cmd_zoneset.stop()
self.execute_show_cmd_zone.stop()
self.execute_show_cmd_zone_status.stop()
self.mock_load_config.stop()
def load_fixtures(self, commands=None, device=''):
self.load_config.return_value = None
# Test def zone from deny to permit and vice versa
def test_zone_defzone_deny_to_permit(self):
# switch has def-zone deny and mode basic
a = dict(zone_zoneset_details=[dict(vsan=922, default_zone='permit')])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'zone default-zone permit vsan 922',
'no terminal dont-ask'])
def test_zone_defzone_deny_to_permit_1(self):
# switch has def-zone deny and mode enhanced
a = dict(zone_zoneset_details=[dict(vsan=922, default_zone='permit')])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'zone default-zone permit vsan 922',
'zone commit vsan 922',
'no terminal dont-ask'])
def test_zone_defzone_permit_to_deny_1(self):
# switch has def-zone deny and mode enhanced
a = dict(zone_zoneset_details=[dict(vsan=923, default_zone='deny')])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_2.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'no zone default-zone permit vsan 923',
'zone commit vsan 923',
'no terminal dont-ask'])
def test_zone_defzone_permit_to_deny_2(self):
# switch has def-zone deny and mode enhanced
a = dict(zone_zoneset_details=[dict(vsan=923, default_zone='deny')])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_3.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'no zone default-zone permit vsan 923',
'no terminal dont-ask'])
# Test zone mode from basic to enhanced and vice versa
def test_zone_mode_basic_to_enh(self):
# switch has def-zone deny and mode basic
a = dict(zone_zoneset_details=[dict(vsan=922, mode='enhanced')])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'zone mode enhanced vsan 922',
'zone commit vsan 922',
'no terminal dont-ask'])
# Test zone mode from basic to enhanced and vice versa
def test_zone_mode_basic_to_enh_1(self):
# switch has def-zone deny and mode basic
a = dict(zone_zoneset_details=[dict(vsan=922, mode='basic')])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'no zone mode enhanced vsan 922',
'no terminal dont-ask'])
# Test zone smart-zone from enabled to disabled and vice versa
def test_zone_smart_zone(self):
# switch has def-zone deny and mode basic
a = dict(zone_zoneset_details=[dict(vsan=922, smart_zoning=False)])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'no zone smart-zoning enable vsan 922',
'no terminal dont-ask'])
def test_zone_smart_zone_1(self):
# switch has def-zone deny and mode basic
a = dict(zone_zoneset_details=[dict(vsan=923, smart_zoning=True)])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'zone smart-zoning enable vsan 923',
'zone commit vsan 923',
'no terminal dont-ask'])
# Test zone add/removal
def test_zone_add_rem(self):
a = dict(zone_zoneset_details=[dict(
vsan=923,
zone=[
dict(
name='zoneB',
remove=True)
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'],
['terminal dont-ask', 'no zone name zoneB vsan 923', 'zone commit vsan 923',
'no terminal dont-ask'])
def test_zone_add_rem_1(self):
a = dict(zone_zoneset_details=[dict(
vsan=923,
zone=[
dict(
name='zoneC',
remove=True)
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_0.cfg')
result = self.execute_module(changed=False, failed=False)
m = "zone 'zoneC' is not present in vsan 923"
assert m in str(result['messages'])
self.assertEqual(result['commands'], [])
def test_zone_add_rem_2(self):
a = dict(zone_zoneset_details=[dict(
vsan=923,
zone=[
dict(
name='zoneBNew')
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'zone name zoneBNew vsan 923',
'zone commit vsan 923',
'no terminal dont-ask'])
def test_zone_add_rem_3(self):
a = dict(zone_zoneset_details=[dict(
vsan=923,
zone=[
dict(
name='zoneB')
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_0.cfg')
result = self.execute_module(changed=False, failed=False)
m = "zone 'zoneB' is already present in vsan 923"
assert m in str(result['messages'])
self.assertEqual(result['commands'], [])
# Test zone mem add/removal
def test_zonemem_add_rem(self):
mem1 = {'pwwn': '10:00:10:94:00:00:00:01'}
mem2 = {'device_alias': 'somename'}
a = dict(zone_zoneset_details=[dict(
vsan=923,
zone=[
dict(
name='zoneBNew',
members=[mem1, mem2])
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'zone name zoneBNew vsan 923',
'member pwwn 10:00:10:94:00:00:00:01',
'member device-alias somename',
'zone commit vsan 923',
'no terminal dont-ask'])
# Test zone mem add/removal
def test_zonemem_add_rem_1(self):
mem1 = {'pwwn': '11:11:11:11:11:11:11:11', 'remove': True}
mem2 = {'device_alias': 'test123', 'remove': True}
a = dict(zone_zoneset_details=[dict(
vsan=923,
zone=[
dict(
name='zoneA',
members=[mem1, mem2])
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'], ['terminal dont-ask',
'zone name zoneA vsan 923',
'no member pwwn 11:11:11:11:11:11:11:11',
'no member device-alias test123',
'zone commit vsan 923',
'no terminal dont-ask'])
# Test zone mem add/removal
def test_zonemem_add_rem_2(self):
mem1 = {'pwwn': '11:11:11:11:11:11:11:11', 'remove': True}
mem2 = {'device_alias': 'test123', 'remove': True}
a = dict(zone_zoneset_details=[dict(
vsan=923,
zone=[
dict(
name='zoneA1',
members=[mem1, mem2])
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_1.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_0.cfg')
result = self.execute_module(changed=False, failed=False)
m = "zone 'zoneA1' is not present in vsan 923 , hence cannot remove the members"
assert m in str(result['messages'])
self.assertEqual(result['commands'], [])
def test_zonemem_add_rem_3(self):
mem1 = {'pwwn': '10:00:10:94:00:00:00:01', 'devtype': 'initiator'}
mem2 = {'device_alias': 'somename', 'devtype': 'target'}
mem3 = {'device_alias': 'somenameWithBoth', 'devtype': 'both'}
a = dict(zone_zoneset_details=[dict(
vsan=922,
zone=[
dict(
name='zoneBNew',
members=[mem1, mem2, mem3])
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_1.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'],
['terminal dont-ask', 'zone name zoneBNew vsan 922',
'member pwwn 10:00:10:94:00:00:00:01 initiator',
'member device-alias somename target',
'member device-alias somenameWithBoth both',
'no terminal dont-ask'])
# Test zone mem add/removal with devtype
def test_zonemem_add_rem_4(self):
mem2 = {'device_alias': 'test123', 'devtype': 'both', 'remove': True}
a = dict(zone_zoneset_details=[dict(
vsan=922,
zone=[
dict(
name='zoneA',
members=[mem2])
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zone.return_value = load_fixture('nxos_zone_zoneset', 'shzone_1.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'],
['terminal dont-ask', 'zone name zoneA vsan 922',
'no member device-alias test123 both',
'no terminal dont-ask'])
# Test zoneset add/removal
def test_zoneset_add_rem(self):
a = dict(zone_zoneset_details=[
dict(vsan=922,
zoneset=[
dict(name='zsetname21', remove=True)
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'],
['terminal dont-ask', 'no zoneset name zsetname21 vsan 922', 'no terminal dont-ask']
)
def test_zoneset_add_rem_1(self):
a = dict(zone_zoneset_details=[
dict(vsan=922,
zoneset=[
dict(name='zsetname21New')
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_0.cfg')
result = self.execute_module(changed=True)
self.assertEqual(result['commands'],
['terminal dont-ask', 'zoneset name zsetname21New vsan 922', 'no terminal dont-ask']
)
def test_zoneset_add_rem_2(self):
a = dict(zone_zoneset_details=[
dict(vsan=922,
zoneset=[
dict(name='zsetname21')
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_0.cfg')
result = self.execute_module(changed=False, failed=False)
m = "zoneset 'zsetname21' is already present in vsan 922"
self.assertEqual(result['commands'], [])
self.assertEqual(result['messages'], [m])
def test_zoneset_add_rem_3(self):
a = dict(zone_zoneset_details=[
dict(vsan=922,
zoneset=[
dict(name='zsetname21New', remove=True)
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_0.cfg')
result = self.execute_module(changed=False, failed=False)
m = "zoneset 'zsetname21New' is not present in vsan 922 ,hence there is nothing to remove"
self.assertEqual(result['commands'], [])
self.assertEqual(result['messages'], [m])
# Test zoneset mem add/removal
def test_zoneset_mem_add_rem(self):
mem1 = {'name': 'newZoneV100'}
a = dict(zone_zoneset_details=[
dict(vsan=922,
zoneset=[
dict(name='zsetname21', members=[mem1])
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_0.cfg')
result = self.execute_module(changed=True, failed=False)
self.assertEqual(result['commands'],
['terminal dont-ask', 'zoneset name zsetname21 vsan 922', 'member newZoneV100',
'no terminal dont-ask']
)
# Test zoneset mem add/removal
def test_zoneset_mem_add_rem_1(self):
mem1 = {'name': 'zone21A', 'remove': True}
a = dict(zone_zoneset_details=[
dict(vsan=922,
zoneset=[
dict(name='zsetname21', members=[mem1])
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_0.cfg')
result = self.execute_module(changed=True, failed=False)
self.assertEqual(result['commands'],
['terminal dont-ask', 'zoneset name zsetname21 vsan 922', 'no member zone21A',
'no terminal dont-ask']
)
# Test zoneset mem add/removal
def test_zoneset_mem_add_rem_2(self):
mem1 = {'name': 'zone21', 'remove': True}
a = dict(zone_zoneset_details=[
dict(vsan=922,
zoneset=[
dict(name='zsetname21', members=[mem1])
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_0.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_0.cfg')
result = self.execute_module(changed=False, failed=False)
m = "zoneset member 'zone21' is not present in zoneset 'zsetname21' in vsan 922 ,hence there is nothing to remove"
self.assertEqual(result['commands'], [])
self.assertEqual(result['messages'], [m])
# Test zoneset activate/deactivate
def test_zoneset_activate_deactivate(self):
a = dict(zone_zoneset_details=[
dict(vsan=221,
zoneset=[
dict(name='zsv221', action='activate')
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_4.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_2.cfg')
self.execute_show_cmd_zoneset_active.return_value = load_fixture('nxos_zone_zoneset', 'shzonesetactive_0.cfg')
result = self.execute_module(changed=False, failed=False)
m = "zoneset 'zsv221' is already present in vsan 221"
m1 = "zoneset 'zsv221' in vsan 221 is already activated"
self.assertEqual(result['commands'], [])
self.assertEqual(result['messages'], [m, m1])
def test_zoneset_activate_deactivate_1(self):
a = dict(zone_zoneset_details=[
dict(vsan=221,
zoneset=[
dict(name='zsv221', action='deactivate')
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_4.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_2.cfg')
self.execute_show_cmd_zoneset_active.return_value = load_fixture('nxos_zone_zoneset', 'shzonesetactive_0.cfg')
result = self.execute_module(changed=True, failed=False)
self.assertEqual(result['commands'], ['terminal dont-ask',
'no zoneset activate name zsv221 vsan 221',
'zone commit vsan 221',
'no terminal dont-ask'])
def test_zoneset_activate_deactivate_2(self):
a = dict(zone_zoneset_details=[
dict(vsan=221,
zoneset=[
dict(name='zsv221New', action='activate')
])
])
set_module_args(a, True)
self.execute_show_cmd_zone_status.return_value = load_fixture('nxos_zone_zoneset', 'shzonestatus_4.cfg')
self.execute_show_cmd_zoneset.return_value = load_fixture('nxos_zone_zoneset', 'shzoneset_2.cfg')
self.execute_show_cmd_zoneset_active.return_value = load_fixture('nxos_zone_zoneset', 'shzonesetactive_0.cfg')
result = self.execute_module(changed=True, failed=False)
self.assertEqual(result['commands'], ['terminal dont-ask', 'zoneset name zsv221New vsan 221',
'zoneset activate name zsv221New vsan 221',
'zone commit vsan 221',
'no terminal dont-ask'])